<commit_before>/*!
 * qwebs
 * Copyright(c) 2015 Benoît Claveau
 * MIT Licensed
 */

"use strict";

const zlib = require("zlib");
const crypto = require('crypto');
const DataError = require("./../dataerror");
const JSONStream = require("JSONStream");

class ResponseService {
    constructor() {
    };

    setCharset(data) {
        if (!data.header["Content-Type"].match(/charset/)) {
            data.header["Content-Type"] += "; charset=utf-8";
        }
    };

    setVary(data) {
        data.header["Vary"] = "Accept-Encoding";
    };

    fresh(data) {

        let etagMatches = true;
        let notModified = true;

        // fields
        let modifiedSince = data.request['If-Modified-Since'];
        let noneMatch = data.request['If-None-Match'];
        let lastModified = data.request['Last-Modified'];
        let etag = data.header["Etag"];
        let cc = data.request['Cache-Control'];

        // unconditional request
        if (!modifiedSince && !noneMatch) return false;

        // check for no-cache cache request directive
        if (cc && cc.indexOf('no-cache') !== -1) return false;

        // parse if-none-match
        if (noneMatch) noneMatch = noneMatch.split(/ *, */);

        // if-none-match
        if (noneMatch) {
            etagMatches = noneMatch.some(match => {
                return match === '*' || match === etag || match === 'W/' + etag;
            });
        }

        // if-modified-since
        if (modifiedSince) {
            modifiedSince = new Date(modifiedSince);
            lastModified = new Date(lastModified);
            notModified = lastModified <= modifiedSince;
        }
        return !! (etagMatches && notModified);
    };

    envelope(data) {
        if (!data) throw new DataError({ message: "No data." });
        if (!data.request) throw new DataError({ message: "Request is null." });
        if (!data.header) data.header = {};
        if (!data.statusCode) data.statusCode = 200;

        let atime = new Date(Date.now());

        data.header["Date"] = data.header["Date"] || atime.toUTCString();
        data.header["Cache-Control"] = data.header["Cache-Control"] || "no-cache";
        data.header["Expires"] = data.header["Expires"] || atime.toUTCString();
        data.header["Content-Type"] = data.header["Content-Type"] || "application/json";

        switch (this.method) {
            case "GET":
            case "POST":
            case "PUT":
            case "DELETE":
                if (!data.content && !data.stream) throw new DataError({ message: "Content is null." });
                break;
            case "OPTIONS":
                data.header["Content-Type"] = data.content = data.stream = null; //Only header no content
                break;
        }

        if (data.header["Content-Type"]) {
            if (data.header["Content-Type"].match(/\bapplication\/json\b/)) {
                if (data.content && !(data.content instanceof String || typeof data.content === "string")) {
                    try {
                        data.content = JSON.stringify(data.content);
                    }
                    catch(error) {
                        throw new DataError({ message: "Failed to stringify content", data: {content: data.content }, stack: error.stack });
                    }
                }
                else if (data.stream) {
                   data.stream = data.stream.on("error", error => {
                     console.error("Stream", error);
                     //reject(new DataError({ message: error.message, stack: error.stack }));
                   }).pipe(JSONStream.stringify()).on("error", error => {
                      console.error("Stringify", error);
                     //reject(new DataError({ message: error.message, stack: error.stack }));
                   }).on("finish", () => {
                    console.log("JSONStream.stringify() completed");
                   });
                }
                this.setCharset(data);
                this.setVary(data);
            }
            else if (data.header["Content-Type"].match(/\btext\/html\b/)) {
                this.setCharset(data);
                this.setVary(data);
            }

            if (!data.header["Etag"]) {
                if (data.content) data.header["Etag"] = crypto.createHash('sha256').update(data.content).digest("hex");
                //default etag stream is not managed.
            }

            data.fresh = this.fresh(data);
            if (!data.fresh) data.header["Last-Modified"] = data.header["Last-Modified"] || atime.toUTCString();

            let acceptEncoding = data.request.headers["accept-encoding"] || "";
            if (acceptEncoding.match(/\bgzip\b/)) data.header["Content-Encoding"] = "gzip";
            else if (acceptEncoding.match(/\bdeflate\b/)) data.header["Content-Encoding"] = "deflate";
        }
    };

    /* Promise ---------- */

    redirect(response, data) {
        try {
            if (!data) throw new DataError({ message: "No data." });
            if (!data.url) throw new DataError({ message: "No url." });

            data.header = data.header || {};
            data.statusCode = data.statusCode || 307;
            data.header["Content-Type"] = data.header["Content-Type"] || "text/html";
            data.header["Location"] = data.header["Location"] || data.url;

            response.writeHead(data.statusCode, data.header);
            response.end();
            return Promise.resolve(this);
        }
        catch(error) {
            return Promise.reject(error);
        }
    };

    compress(data) {
        try {
            if (data.fresh) return Promise.resolve({ header: data.header, statusCode: 304 });
            else if (data.header["Content-Encoding"] == "gzip") return this.compressGzip(data);
            else if (data.header["Content-Encoding"] == "deflate") return this.compressDeflate(data);
            else return Promise.resolve(data);
        } catch(error) {
            return Promise.reject(error);
        }
    };

    compressGzip(data) {
        return new Promise((resolve, reject) => {
            if (data.contentGzip) { //assets already gzipped
                resolve({ header: data.header, content: data.contentGzip, statusCode: data.statusCode });
            }
            else if (data.stream) { //stream
                let stream = data.stream.pipe(zlib.createGzip());
                resolve({ header: data.header, stream: stream, statusCode: data.statusCode });
            }
            else if (data.content) {
                zlib.gzip(data.content, (error, buffer) => {
                    if (error) reject(new DataError({ message: error.message, stack: error.stack }));
                    else resolve({ header: data.header, content: buffer, statusCode: data.statusCode });
                });
            }
            else resolve({ header: data.header, statusCode: data.statusCode });
        });
    };

    compressDeflate(data) {
        return new Promise((resolve, reject) => {
            if (data.contentDeflate) { //assets already deflated
                resolve({ header: data.header, content: data.contentDeflate, statusCode: data.statusCode });
            }
            else if (data.stream) { //stream
                let stream = data.stream.pipe(zlib.createDeflate());
                resolve({ header: data.header, stream: stream, statusCode: data.statusCode });
            }
            else if (data.content) {
                zlib.deflate(data.content, (error, buffer) => {
                    if (error) reject(new DataError({ message: error.message, stack: error.stack }));
                    else resolve({ header: data.header, content: buffer, statusCode: data.statusCode });
                });
            }
            else resolve({ header: data.header, statusCode: data.statusCode });
        });
    };

    send(response, data) {
        try {
            this.envelope(data);
            return this.compress(data).then(resp => {
                return new Promise((resolve, reject) => {
                    try {
                        response.writeHead(resp.statusCode, resp.header);
                        if (resp.stream) {
                            resp.stream
                                .on("error", error => {
                                    reject(new DataError({ message: error.message, stack: error.stack }));
                                }).pipe(response)
                                .on("error", error => {
                                    reject(new DataError({ message: error.message, stack: error.stack }));
                                }).on("finish", () => {
                                    resolve(resp);
                                });
                        }
                        else {
                            if (resp.content) response.end(resp.content);
                            else response.end();
                            resolve(resp);
                        }
                    }
                    catch (error) {
                        reject(new DataError({ message: error.message, stack: error.stack }));
                    }
                });
            });
        }
        catch(error) {
            return Promise.reject(error);
        }
    };
};

exports = module.exports = ResponseService;
<commit_msg>Remove log<commit_after>/*!
 * qwebs
 * Copyright(c) 2015 Benoît Claveau
 * MIT Licensed
 */

"use strict";

const zlib = require("zlib");
const crypto = require('crypto');
const DataError = require("./../dataerror");
const JSONStream = require("JSONStream");

class ResponseService {
    constructor() {
    };

    setCharset(data) {
        if (!data.header["Content-Type"].match(/charset/)) {
            data.header["Content-Type"] += "; charset=utf-8";
        }
    };

    setVary(data) {
        data.header["Vary"] = "Accept-Encoding";
    };

    fresh(data) {

        let etagMatches = true;
        let notModified = true;

        // fields
        let modifiedSince = data.request['If-Modified-Since'];
        let noneMatch = data.request['If-None-Match'];
        let lastModified = data.request['Last-Modified'];
        let etag = data.header["Etag"];
        let cc = data.request['Cache-Control'];

        // unconditional request
        if (!modifiedSince && !noneMatch) return false;

        // check for no-cache cache request directive
        if (cc && cc.indexOf('no-cache') !== -1) return false;

        // parse if-none-match
        if (noneMatch) noneMatch = noneMatch.split(/ *, */);

        // if-none-match
        if (noneMatch) {
            etagMatches = noneMatch.some(match => {
                return match === '*' || match === etag || match === 'W/' + etag;
            });
        }

        // if-modified-since
        if (modifiedSince) {
            modifiedSince = new Date(modifiedSince);
            lastModified = new Date(lastModified);
            notModified = lastModified <= modifiedSince;
        }
        return !! (etagMatches && notModified);
    };

    envelope(data) {
        if (!data) throw new DataError({ message: "No data." });
        if (!data.request) throw new DataError({ message: "Request is null." });
        if (!data.header) data.header = {};
        if (!data.statusCode) data.statusCode = 200;

        let atime = new Date(Date.now());

        data.header["Date"] = data.header["Date"] || atime.toUTCString();
        data.header["Cache-Control"] = data.header["Cache-Control"] || "no-cache";
        data.header["Expires"] = data.header["Expires"] || atime.toUTCString();
        data.header["Content-Type"] = data.header["Content-Type"] || "application/json";

        switch (this.method) {
            case "GET":
            case "POST":
            case "PUT":
            case "DELETE":
                if (!data.content && !data.stream) throw new DataError({ message: "Content is null." });
                break;
            case "OPTIONS":
                data.header["Content-Type"] = data.content = data.stream = null; //Only header no content
                break;
        }

        if (data.header["Content-Type"]) {
            if (data.header["Content-Type"].match(/\bapplication\/json\b/)) {
                if (data.content && !(data.content instanceof String || typeof data.content === "string")) {
                    try {
                        data.content = JSON.stringify(data.content);
                    }
                    catch(error) {
                        throw new DataError({ message: "Failed to stringify content", data: {content: data.content }, stack: error.stack });
                    }
                }
                else if (data.stream) {
                   data.stream = data.stream.pipe(JSONStream.stringify());
                }
                this.setCharset(data);
                this.setVary(data);
            }
            else if (data.header["Content-Type"].match(/\btext\/html\b/)) {
                this.setCharset(data);
                this.setVary(data);
            }

            if (!data.header["Etag"]) {
                if (data.content) data.header["Etag"] = crypto.createHash('sha256').update(data.content).digest("hex");
                //default etag stream is not managed.
            }

            data.fresh = this.fresh(data);
            if (!data.fresh) data.header["Last-Modified"] = data.header["Last-Modified"] || atime.toUTCString();

            let acceptEncoding = data.request.headers["accept-encoding"] || "";
            if (acceptEncoding.match(/\bgzip\b/)) data.header["Content-Encoding"] = "gzip";
            else if (acceptEncoding.match(/\bdeflate\b/)) data.header["Content-Encoding"] = "deflate";
        }
    };

    /* Promise ---------- */

    redirect(response, data) {
        try {
            if (!data) throw new DataError({ message: "No data." });
            if (!data.url) throw new DataError({ message: "No url." });

            data.header = data.header || {};
            data.statusCode = data.statusCode || 307;
            data.header["Content-Type"] = data.header["Content-Type"] || "text/html";
            data.header["Location"] = data.header["Location"] || data.url;

            response.writeHead(data.statusCode, data.header);
            response.end();
            return Promise.resolve(this);
        }
        catch(error) {
            return Promise.reject(error);
        }
    };

    compress(data) {
        try {
            if (data.fresh) return Promise.resolve({ header: data.header, statusCode: 304 });
            else if (data.header["Content-Encoding"] == "gzip") return this.compressGzip(data);
            else if (data.header["Content-Encoding"] == "deflate") return this.compressDeflate(data);
            else return Promise.resolve(data);
        } catch(error) {
            return Promise.reject(error);
        }
    };

    compressGzip(data) {
        return new Promise((resolve, reject) => {
            if (data.contentGzip) { //assets already gzipped
                resolve({ header: data.header, content: data.contentGzip, statusCode: data.statusCode });
            }
            else if (data.stream) { //stream
                let stream = data.stream.pipe(zlib.createGzip());
                resolve({ header: data.header, stream: stream, statusCode: data.statusCode });
            }
            else if (data.content) {
                zlib.gzip(data.content, (error, buffer) => {
                    if (error) reject(new DataError({ message: error.message, stack: error.stack }));
                    else resolve({ header: data.header, content: buffer, statusCode: data.statusCode });
                });
            }
            else resolve({ header: data.header, statusCode: data.statusCode });
        });
    };

    compressDeflate(data) {
        return new Promise((resolve, reject) => {
            if (data.contentDeflate) { //assets already deflated
                resolve({ header: data.header, content: data.contentDeflate, statusCode: data.statusCode });
            }
            else if (data.stream) { //stream
                let stream = data.stream.pipe(zlib.createDeflate());
                resolve({ header: data.header, stream: stream, statusCode: data.statusCode });
            }
            else if (data.content) {
                zlib.deflate(data.content, (error, buffer) => {
                    if (error) reject(new DataError({ message: error.message, stack: error.stack }));
                    else resolve({ header: data.header, content: buffer, statusCode: data.statusCode });
                });
            }
            else resolve({ header: data.header, statusCode: data.statusCode });
        });
    };

    send(response, data) {
        try {
            this.envelope(data);
            return this.compress(data).then(resp => {
                return new Promise((resolve, reject) => {
                    try {
                        response.writeHead(resp.statusCode, resp.header);
                        if (resp.stream) {
                            resp.stream
                                .on("error", error => {
                                    reject(new DataError({ message: error.message, stack: error.stack }));
                                }).pipe(response)
                                .on("error", error => {
                                    reject(new DataError({ message: error.message, stack: error.stack }));
                                }).on("finish", () => {
                                    resolve(resp);
                                });
                        }
                        else {
                            if (resp.content) response.end(resp.content);
                            else response.end();
                            resolve(resp);
                        }
                    }
                    catch (error) {
                        reject(new DataError({ message: error.message, stack: error.stack }));
                    }
                });
            });
        }
        catch(error) {
            return Promise.reject(error);
        }
    };
};

exports = module.exports = ResponseService;
<|endoftext|>


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

// "use strict"

var node = false;

if (typeof module === "undefined") {
  var module = function () {};
  var exports = this.preference = {};
  module.exports = exports;
}
if (typeof require !== "undefined") {
  var uuid = require('node-uuid');
}

module.exports = Preference;

Preference.KEY = 'Preference';

Preference.DEFAULT_LOGO = 'Misc';
Preference.DEFAULT_LOCATION = 'Random point in the space/time continuum';
Preference.DEFAULT_WIDTH = 1;
Preference.DEFAULT_ROWS = 2;
Preference.DEFAULT_COLUMNS = 2;
Preference.DEFAULT_TITLE = "ACME Rocket Powered Products, Inc";
Preference.DEFAULT_SUBTITLE = "A part of the ACME Group of companies";

Preference.MESSAGE_ADD_PREFERENCE = 'addPreference';
Preference.MESSAGE_UPDATE_PREFERENCE = 'updatePreference';
Preference.MESSAGE_DELETE_PREFERENCE = 'deletePreference';
Preference.MESSAGE_GET_PREFERENCES = 'getPreference';
Preference.MESSAGE_PREFERENCES = 'preference';

function Preference(options) {
  options = options || {};

  var uuidV1 = ((options.uuidV1 !== null && options.uuidV1 !== undefined) ? options.uuidV1 : false);

  this.id = ((options.id !== null && options.id !== undefined) ? options.id : uuidV1 ? uuid.v1() : uuid.v4());

  this.logo = ((options.logo !== null && options.logo !== undefined) ? options.logo : Preference.DEFAULT_LOGO);
  this.title = ((options.title !== null && options.title !== undefined) ? options.title : Preference.DEFAULT_TITLE);
  this.subTitle = ((options.subTitle !== null && options.subTitle !== undefined) ? options.subTitle : Preference.DEFAULT_SUBTITLE);

  this.location = ((options.location !== null && options.location !== undefined) ? options.location : Preference.DEFAULT_LOCATION);

  this.columns = ((options.columns !== null && options.columns !== undefined) ? options.columns : Preference.DEFAULT_COLUMNS);
  this.rows = ((options.rows !== null && options.rows !== undefined) ? options.rows : Preference.DEFAULT_ROWS);

  this.displayHeader = ((options.displayHeader !== null && options.displayHeader !== undefined) ? options.displayHeader : true);
  this.displayBanner = ((options.displayBanner !== null && options.displayBanner !== undefined) ? options.displayBanner : true);
}

/*
 * merge
 */
Preference.merge = function (d1, d2) {
  mergeAttribute(d1, d2, 'logo');
  mergeAttribute(d1, d2, 'title');
  mergeAttribute(d1, d2, 'subTitle');
  mergeAttribute(d1, d2, 'location');
  mergeAttribute(d1, d2, 'columns');
  mergeAttribute(d1, d2, 'rows');
  mergeAttribute(d1, d2, 'displayHeader');
  mergeAttribute(d1, d2, 'displayBanner');
};

function mergeAttribute(object, modifiedObject, attribute) {
  object[attribute] = ((modifiedObject[attribute] !== null && modifiedObject[attribute] !== undefined) ? modifiedObject[attribute] : object[attribute]);
}<commit_msg>initialise columns and rows as integers<commit_after>/*global window, require, console */
/*
 * preference.js
 *
 * Copyright (c) 2015 James G Jenner
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

// "use strict"

var node = false;

if (typeof module === "undefined") {
  var module = function () {};
  var exports = this.preference = {};
  module.exports = exports;
}
if (typeof require !== "undefined") {
  var uuid = require('node-uuid');
}

module.exports = Preference;

Preference.KEY = 'Preference';

Preference.DEFAULT_LOGO = 'Misc';
Preference.DEFAULT_LOCATION = 'Random point in the space/time continuum';
Preference.DEFAULT_WIDTH = 1;
Preference.DEFAULT_ROWS = 2;
Preference.DEFAULT_COLUMNS = 2;
Preference.DEFAULT_TITLE = "ACME Rocket Powered Products, Inc";
Preference.DEFAULT_SUBTITLE = "A part of the ACME Group of companies";

Preference.MESSAGE_ADD_PREFERENCE = 'addPreference';
Preference.MESSAGE_UPDATE_PREFERENCE = 'updatePreference';
Preference.MESSAGE_DELETE_PREFERENCE = 'deletePreference';
Preference.MESSAGE_GET_PREFERENCES = 'getPreference';
Preference.MESSAGE_PREFERENCES = 'preference';

function Preference(options) {
  options = options || {};

  var uuidV1 = ((options.uuidV1 !== null && options.uuidV1 !== undefined) ? options.uuidV1 : false);

  this.id = ((options.id !== null && options.id !== undefined) ? options.id : uuidV1 ? uuid.v1() : uuid.v4());

  this.logo = ((options.logo !== null && options.logo !== undefined) ? options.logo : Preference.DEFAULT_LOGO);
  this.title = ((options.title !== null && options.title !== undefined) ? options.title : Preference.DEFAULT_TITLE);
  this.subTitle = ((options.subTitle !== null && options.subTitle !== undefined) ? options.subTitle : Preference.DEFAULT_SUBTITLE);

  this.location = ((options.location !== null && options.location !== undefined) ? options.location : Preference.DEFAULT_LOCATION);

  this.columns = ((options.columns !== null && options.columns !== undefined) ? parseInt(options.columns) : Preference.DEFAULT_COLUMNS);
  this.rows = ((options.rows !== null && options.rows !== undefined) ? parseInt(options.rows) : Preference.DEFAULT_ROWS);

  this.displayHeader = ((options.displayHeader !== null && options.displayHeader !== undefined) ? options.displayHeader : true);
  this.displayBanner = ((options.displayBanner !== null && options.displayBanner !== undefined) ? options.displayBanner : true);
}

/*
 * merge
 */
Preference.merge = function (d1, d2) {
  mergeAttribute(d1, d2, 'logo');
  mergeAttribute(d1, d2, 'title');
  mergeAttribute(d1, d2, 'subTitle');
  mergeAttribute(d1, d2, 'location');
  mergeAttribute(d1, d2, 'columns');
  mergeAttribute(d1, d2, 'rows');
  mergeAttribute(d1, d2, 'displayHeader');
  mergeAttribute(d1, d2, 'displayBanner');
};

function mergeAttribute(object, modifiedObject, attribute) {
  object[attribute] = ((modifiedObject[attribute] !== null && modifiedObject[attribute] !== undefined) ? modifiedObject[attribute] : object[attribute]);
}<|endoftext|>


<commit_before>/*global define*/
define(['jquery', 'underscore', 'events'], function ($, _, Events) {
  'use strict';

  var validators = {
    required: function (fieldName, message) {
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' must have a value');
      return this.minLength(1, fieldName, message);
    },
    match: function (regex, fieldName, message) {
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' format is incorrect');
      return function ($e) {
        if (!regex.test($e.val())) {
          return message;
        }
      };
    },
    minLength: function (length, fieldName, message) {
      fieldName = fieldName || 'field';
      length = Number(length);
      message = message || (fieldName + ' has a minimum length of ' + length);
      return function ($e) {
        if ($e.val().length < length) {
          return message;
        }
      };
    },
    maxLength: function (length, fieldName, message) {
      fieldName = fieldName || 'field';
      length = Number(length);
      message = message || (fieldName + ' has a maximum length of ' + length);
      return function ($e) {
        if ($e.val().length > length) {
          return message;
        }
      };
    },
    any: function (options, fieldName, message) {
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' is not a valid choice');
      options = options || [];
      return function ($e) {
        if (options.length === 0) {
          return message;
        }
        if (!_.contains(options, $e.val())) {
          return message;
        }
      };
    },
    numeric: function (fieldName, message) {
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' must be numeric');
      return function ($e) {
        if (isNaN($e.val())) {
          return message;
        }
      };
    },
    numericRange: function (lower, upper, fieldName, message) {
      fieldName = fieldName || 'field';
      lower = Number(lower);
      upper = Number(upper);
      message = message || (fieldName + ' must be between ' + lower + ' and ' + upper);
      return function ($e) {
        var value = $e.val();
        if (isNaN(value)) {
          return message;
        }
        value = Number(value);
        if (value > upper || value < lower) {
          return message;
        }
      };
    },
    gt: function (number, fieldName, message) {
      fieldName = fieldName || 'field';
      number = Number(number);
      message = message || (fieldName + ' must be greater than ' + number);
      return function ($e) {
        var value = $e.val();
        if (isNaN(value)) {
          return message;
        }
        value = Number(value);
        if (value <= number) {
          return message;
        }
      };
    },
    gteq: function (number, fieldName, message) {
      fieldName = fieldName || 'field';
      number = Number(number);
      message = message || (fieldName + ' must be greater than or equal to ' + number);
      return function ($e) {
        var value = $e.val();
        if (isNaN(value)) {
          return message;
        }
        value = Number(value);
        if (value < number) {
          return message;
        }
      };
    },
    lt: function (number, fieldName, message) {
      fieldName = fieldName || 'field';
      number = Number(number);
      message = message || (fieldName + ' must be less than ' + number);
      return function ($e) {
        var value = $e.val();
        if (isNaN(value)) {
          return message;
        }
        value = Number(value);
        if (value >= number) {
          return message;
        }
      };
    },
    lteq: function (number, fieldName, message) {
      fieldName = fieldName || 'field';
      number = Number(number);
      message = message || (fieldName + ' must be less than or equal to ' + number);
      return function ($e) {
        var value = $e.val();
        if (isNaN(value)) {
          return message;
        }
        value = Number(value);
        if (value > number) {
          return message;
        }
      };
    },

    /**
     * Allows you to provide a function [getValue] that will be responsible for
     * providing the actual data value to [rule], which is a validation rule.
     *
     * var set = new ValidationSet(this._$el);
     * var any = validators.any(['none', 'few', 'many']);
     * var accessor = validators.accessor(function ($e) {
     *   //for some reason the value is missing; default to 'none'
     *   return $el.val() ? $el.val() : 'none';
     * }, any);
     * set.add('[name=howMany]', accessor);
     *
     * @param {Function} getValue
     * @param {Function} rule
     * @returns {Function}
     */
    accessor: function (getValue, rule) {
      return function ($e) {
        var value = getValue($e);
        return rule({
          val: function () {
            return value;
          }
        });
      };
    },

    /**
     * Composes multiple rules to be evaluated as a unit.
     *
     * var set = new ValidationSet(this._$el);
     * var composed = validators.compose(
     *   validators.numeric(),
     *   validators.gteq(10),
     *   validators.lt(100)
     * );
     * set.add('[name=score]', composed);
     *
     * The validation result will be returned as a single string, delimited by
     * the pipe character (or whatever delimiter is passed as the first argument
     * to `compose()`).
     *
     * @param {String} [delimiter]
     * @param {...Function} rules
     * @returns {Function}
     */
    compose: function (rules) {
      rules = Array.prototype.slice.call(arguments, 0);
      return function ($e) {
        var violations = [];
        _.each(rules, function (rule) {
          var violation = rule($e);
          if (violation) {
            violations.push(violation);
          }
        });
        return violations;
      };
    },

    /**
     * Applies a precondition to the validation rule; if the precondition
     * returns `true`, the rule will execute. If the precondition returns
     * `false`, the rule will be be ignored.
     * @param {Function} predicate
     * @param {Function} rule
     * @returns {Function}
     */
    precondition: function (predicate, rule) {
      return function ($e) {
        if (predicate($e)) {
          return rule($e);
        }
      };
    }
  };

  var vette = {
    add: function (selector, rule) {
      if (!_.has(this._rules, selector)) {
        this._rules[selector] = [];
      }
      this._rules[selector].push(rule);
    },
    remove: function (selector, rule) {
      if (!_.has(this._rules, selector)) {
        return;
      }
      this._rules[selector] = _.without(this._rules[selector], rule);
    },
    selectors: function () {
      return _.keys(this._rules);
    },
    _evaluate: function ($el, deferred) {
      this.trigger('evaluating', this.selectors());
      var self = this;
      /*
       * violations = {
       *   '[name=fullName]': ['field is required'], //1 violation
       *   '[name=phone]': [] //no violations
       * }
       */
      var violations = {};

      _.each(this._rules, function (rules, selector) {
        violations[selector] = [];

        _.each(rules, function (rule) {
          var violation = rule($el.find(selector));
          if (violation) {
            violations[selector].push(violation);
          }
        });

        /*
         * Some rules, like "compose", return an array of
         * violations, so we need to flatten everything.
         */
        violations[selector] = _.flatten(violations[selector]);

        if (violations[selector].length > 0) {
          self.trigger('validation-failed', selector, violations[selector]);
        }
      });

      var allViolations = _.values(violations);
      var hasViolations = _.flatten(allViolations).length > 0;

      if (!hasViolations) {
        deferred.resolve();
      } else {
        deferred.reject(violations);
      }

      this.trigger('evaluated');
    },
    evaluate: function ($el) {
      var deferred = new $.Deferred();
      var asyncEvaluation = _.bind(this._evaluate, this, $el, deferred);
      setTimeout(asyncEvaluation, 0);
      return deferred.promise();
    }
  };

  function Vette() {
    var instance = Object.create(new Events());
    instance._rules = {};
    return _.extend(instance, vette);
  }

  return _.extend(Vette, validators);
});<commit_msg>added addtl. validators<commit_after>/*global define*/
define(['jquery', 'underscore', 'moment', 'events'], function ($, _, moment, Events) {
  'use strict';

  function compare(inclusive) {
    var api = Object.create({
      btw: function (a, low, high) {
        return this.gt(high, a) &&
          this.lt(low, a);
      }
    });
    if (inclusive) {
      api.gt = function (a, b) { return a >= b; };
      api.lt = function (a, b) { return a <= b; };
    } else {
      api.gt = function (a, b) { return a > b; };
      api.lt = function (a, b) { return a < b; };
    }
    return api;
  }

  var numericValidators = {
    numeric: function (fieldName, message) {
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' must be numeric');
      return function ($e) {
        if (isNaN($e.val())) {
          return message;
        }
      };
    },
    range: function (lower, upper, inclusive, fieldName, message) {
      lower = Number(lower);
      upper = Number(upper);
      inclusive = inclusive || false;
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' must be between ' + lower + ' and ' + upper);
      return function ($e) {
        var value = Number($e.val());
        if (!compare(inclusive).btw(value, lower, upper)) {
          return message;
        }
      };
    },
    gt: function (number, inclusive, fieldName, message) {
      number = Number(number);
      inclusive = inclusive || false;
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' must be greater than ' + number);
      return function ($e) {
        var value = Number($e.val());
        if (!compare(inclusive).gt(value, number)) {
          return message;
        }
      };
    },
    gteq: function (number, fieldName, message) {
      number = Number(number);
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' must be greater than or equal to ' + number);
      return this.gt(number, true, fieldName, message);
    },
    lt: function (number, inclusive, fieldName, message) {
      number = Number(number);
      inclusive = inclusive || false;
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' must be less than ' + number);
      return function ($e) {
        var value = Number($e.val());
        if (!compare(inclusive).lt(value, number)) {
          return message;
        }
      };
    },
    lteq: function (number, fieldName, message) {
      number = Number(number);
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' must be less than or equal to ' + number);
      return this.lt(number, true, fieldName, message);
    }
  };

  var dateValidators = {
    before: function (selector, inclusive, fieldName, message) {
      selector = selector || '';
      inclusive = inclusive || false;
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' must occur before');
      return function ($e, $root) {
        var before = Date.parse($e.val());
        var after = Date.parse($root.find(selector).val());
        if (!compare(inclusive).lt(before, after)) {
          return message;
        }
      };
    },
    after: function (selector, inclusive, fieldName, message) {
      selector = selector || '';
      inclusive = inclusive || false;
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' must occur after');
      return function ($e, $root) {
        var after = Date.parse($e.val());
        var before = Date.parse($root.find(selector).val());
        if (!compare(inclusive).gt(after, before)) {
          return message;
        }
      };
    }
  };

  var genericValidators = {
    required: function (fieldName, message) {
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' must have a value');
      return this.minLength(1, fieldName, message);
    },
    match: function (regex, fieldName, message) {
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' format is incorrect');
      return function ($e) {
        if (!regex.test($e.val())) {
          return message;
        }
      };
    },
    minLength: function (length, fieldName, message) {
      fieldName = fieldName || 'field';
      length = Number(length);
      message = message || (fieldName + ' has a minimum length of ' + length);
      return function ($e) {
        if ($e.val().length < length) {
          return message;
        }
      };
    },
    maxLength: function (length, fieldName, message) {
      fieldName = fieldName || 'field';
      length = Number(length);
      message = message || (fieldName + ' has a maximum length of ' + length);
      return function ($e) {
        if ($e.val().length > length) {
          return message;
        }
      };
    },
    any: function (options, fieldName, message) {
      fieldName = fieldName || 'field';
      message = message || (fieldName + ' is not a valid choice');
      options = options || [];
      return function ($e) {
        if (options.length === 0) {
          return message;
        }
        if (!_.contains(options, $e.val())) {
          return message;
        }
      };
    },
    same: function (selector, fieldName, message) {
      fieldName = fieldName || 'field';
      selector = selector || '';
      message = message || (fieldName + ' is not the same');
      return function ($e, $root) {
        if($e.val() !== $root.find(selector).val()) {
          return message;
        }
      };
    },

    /**
     * Allows you to provide a function [getValue] that will be responsible for
     * providing the actual data value to [rule], which is a validation rule.
     *
     * var set = new ValidationSet(this._$el);
     * var any = validators.any(['none', 'few', 'many']);
     * var accessor = validators.accessor(function ($e) {
     *   //for some reason the value is missing; default to 'none'
     *   return $el.val() ? $el.val() : 'none';
     * }, any);
     * set.add('[name=howMany]', accessor);
     *
     * @param {Function} getValue
     * @param {Function} rule
     * @returns {Function}
     */
    accessor: function (getValue, rule) {
      return function ($e, $root) {
        var value = getValue($e, $root);
        return rule({
          val: function () {
            return value;
          }
        });
      };
    },

    /**
     * Composes multiple rules to be evaluated as a unit.
     *
     * var set = new ValidationSet(this._$el);
     * var composed = validators.compose(
     *   validators.numeric(),
     *   validators.gteq(10),
     *   validators.lt(100)
     * );
     * set.add('[name=score]', composed);
     *
     * The validation result will be returned as a single string, delimited by
     * the pipe character (or whatever delimiter is passed as the first argument
     * to `compose()`).
     *
     * @param {String} [delimiter]
     * @param {...Function} rules
     * @returns {Function}
     */
    compose: function (rules) {
      rules = Array.prototype.slice.call(arguments, 0);
      return function ($e, $root) {
        var violations = [];
        _.each(rules, function (rule) {
          var violation = rule($e, $root);
          if (violation) {
            violations.push(violation);
          }
        });
        return violations;
      };
    },

    /**
     * Applies a precondition to the validation rule; if the precondition
     * returns `true`, the rule will execute. If the precondition returns
     * `false`, the rule will be be ignored.
     * @param {Function} predicate
     * @param {...Function} rules
     * @returns {Function}
     */
    precondition: function (predicate, rules) {
      rules = Array.prototype.slice.call(arguments, 1);
      rules = this.compose.apply(this, rules);
      return function ($e, $root) {
        if (predicate($e, $root)) {
          return rules($e, $root);
        }
      };
    }
  };

  var validators = _.extend(
    genericValidators,
    dateValidators,
    numericValidators
  );

  var vette = {
    /**
     * Add one or more rules for the selector
     * @param {String} selector
     * @param {...Function} rules
     */
    add: function (selector, rules) {
      rules = Array.prototype.slice.call(arguments, 1) || [];
      if (!_.has(this._rules, selector)) {
        this._rules[selector] = [];
      }
      this._rules[selector] = _.union(this._rules[selector], rules);
    },
    /**
     * Remove one or more rules for the selector
     * @param {String} selector
     * @param {...Function} rules
     */
    remove: function (selector, rules) {
      if (!_.has(this._rules, selector)) {
        return;
      }
      if (arguments.length === 1) {
        delete this._rules[selector];
        return;
      }
      rules = Array.prototype.slice.call(arguments, 1) || [];
      this._rules[selector] = _.difference(this._rules[selector], rules);
    },
    selectors: function () {
      return _.keys(this._rules);
    },
    _evaluate: function ($el, deferred) {
      this.trigger('evaluating', this.selectors());
      var self = this;
      /*
       * violations = {
       *   '[name=fullName]': ['field is required'], //1 violation
       *   '[name=phone]': [] //no violations
       * }
       */
      var violations = {};

      _.each(this._rules, function (rules, selector) {
        violations[selector] = [];

        _.each(rules, function (rule) {
          var violation = rule($el.find(selector), $el);
          if (violation) {
            violations[selector].push(violation);
          }
        });

        /*
         * Some rules, like "compose", return an array of
         * violations, so we need to flatten everything.
         */
        violations[selector] = _.flatten(violations[selector]);

        if (violations[selector].length > 0) {
          self.trigger('validation-failed', selector, violations[selector]);
        }
      });

      var allViolations = _.values(violations);
      var hasViolations = _.flatten(allViolations).length > 0;

      if (!hasViolations) {
        deferred.resolve();
      } else {
        deferred.reject(violations);
      }

      this.trigger('evaluated');
    },
    evaluate: function ($el) {
      var deferred = new $.Deferred();
      var asyncEvaluation = _.bind(this._evaluate, this, $el, deferred);
      setTimeout(asyncEvaluation, 0);
      return deferred.promise();
    }
  };

  function Vette() {
    var instance = Object.create(new Events());
    instance._rules = {};
    return _.extend(instance, vette);
  }

  return _.extend(Vette, validators);
});<|endoftext|>


<commit_before>'use strict'

var mqemitter = require('mqemitter')
var EE = require('events').EventEmitter
var Client = require('./lib/client')
var util = require('util')
var memory = require('./lib/persistence')
var through = require('through2')
var parallel = require('fastparallel')
var series = require('fastseries')
var shortid = require('shortid')
var Packet = require('./lib/packet')
var bulk = require('bulk-write-stream')

module.exports = Aedes

function Aedes (opts) {
  var that = this

  if (!(this instanceof Aedes)) {
    return new Aedes(opts)
  }

  opts = opts || {}
  opts.concurrency = opts.concurrency || 100
  opts.heartbeatInterval = opts.heartbeatInterval || 60000

  this.id = shortid()
  this.counter = 0
  this.mq = opts.mq || mqemitter(opts)
  this.handle = function handle (conn) {
    // return, just to please standard
    // in theory we should store these
    // unconnected client somewhere,
    // and if they don't send a CONNECT
    // packet, kill them
    return new Client(that, conn)
  }
  this.persistence = opts.persistence || memory()
  this.persistence.broker = this
  this._parallel = parallel()
  this._series = series()

  this.clients = {}
  this.brokers = {}

  var hearbeatTopic = '$SYS/' + that.id + '/heartbeat'
  this._heartbeatInterval = setInterval(heartbeat, opts.hearbeatInterval)

  function heartbeat () {
    that.publish({
      topic: hearbeatTopic,
      payload: new Buffer(that.id)
    }, noop)
  }

  this._clearWillInterval = setInterval(function () {
    that.persistence
      .streamWill(that.brokers)
      .pipe(bulk.obj(receiveWills))
  }, opts.heartbeatInterval * 3)

  function receiveWills (chunks, done) {
    that._parallel(that, checkAndPublish, chunks, done)
  }

  function checkAndPublish (will, done) {
    var needsPublishing =
      !that.brokers[will.brokerId] ||
      that.brokers[will.brokerId] + 3 * opts.heartbeatInterval <
      Date.now()

    if (needsPublishing) {
      // randomize this, so that multiple brokers
      // do not publish the same wills at the same time
      that.publish(will, function (err) {
        if (err) {
          return done(err)
        }

        that.persistence.delWill({
          id: will.clientId
        }, done)
      })
    } else {
      done()
    }
  }

  this.mq.on('$SYS/+/hearbeat', function storeBroker (packet, done) {
    that.brokers[packet.payload.toString()] = Date.now()
  })
}

util.inherits(Aedes, EE)

function storeRetained (packet, done) {
  if (packet.retain) {
    this.persistence.storeRetained(packet, done)
  } else {
    done()
  }
}

function emitPacket (packet, done) {
  this.mq.emit(packet, done)
}

function enqueueOffline (packet, done) {
  var that = this

  if (packet.qos > 0) {
    this.persistence.subscriptionsByTopic(packet.topic, function (err, subs) {
      if (err) {
        // is this really recoverable?
        // let's just error the whole aedes
        that.emit('error', err)
      }
      // TODO remove callback

      doEnqueues(that, packet, subs, done)
    })
  } else {
    done()
  }
}

function EnqueuedStatus (packet, broker) {
  this.packet = packet
  this.broker = broker
}

function doEnqueues (broker, packet, subs, done) {
  if (subs.length === 0) {
    done()
  } else {
    broker._parallel(
      new EnqueuedStatus(packet, broker),
      doEnqueue, subs, done)
  }
}

function doEnqueue (sub, done) {
  this.broker.persistence.outgoingEnqueue(sub, this.packet, done)
}

var publishFuncs = [
  storeRetained,
  enqueueOffline,
  emitPacket
]
Aedes.prototype.publish = function (packet, done) {
  var p = new Packet(packet, this)
  this._series(this, publishFuncs, p, done)
}

Aedes.prototype.subscribe = function (topic, func, done) {
  var broker = this

  this.mq.on(topic, func, function subscribed () {
    if (done) {
      // first do a suback
      done()
    }

    var stream = broker.persistence.createRetainedStream(topic)

    stream.pipe(through.obj(function (packet, enc, cb) {
      func(packet, cb)
    }))
  })
}

Aedes.prototype.unsubscribe = function (topic, func, done) {
  this.mq.removeListener(topic, func, done)
}

Aedes.prototype.registerClient = function (client) {
  this.clients[client.id] = client
}

Aedes.prototype.unregisterClient = function (client) {
  delete this.clients[client.id]
}

function closeClient (client, cb) {
  this.clients[client].close(cb)
}

Aedes.prototype.close = function (cb) {
  clearInterval(this._heartbeatInterval)
  clearInterval(this._clearWillInterval)
  this._parallel(this, closeClient, Object.keys(this.clients), cb || noop)
}

function noop () {}
<commit_msg>Delete disconnected broker every once in a while.<commit_after>'use strict'

var mqemitter = require('mqemitter')
var EE = require('events').EventEmitter
var Client = require('./lib/client')
var util = require('util')
var memory = require('./lib/persistence')
var through = require('through2')
var parallel = require('fastparallel')
var series = require('fastseries')
var shortid = require('shortid')
var Packet = require('./lib/packet')
var bulk = require('bulk-write-stream')

module.exports = Aedes

function Aedes (opts) {
  var that = this

  if (!(this instanceof Aedes)) {
    return new Aedes(opts)
  }

  opts = opts || {}
  opts.concurrency = opts.concurrency || 100
  opts.heartbeatInterval = opts.heartbeatInterval || 60000

  this.id = shortid()
  this.counter = 0
  this.mq = opts.mq || mqemitter(opts)
  this.handle = function handle (conn) {
    // return, just to please standard
    // in theory we should store these
    // unconnected client somewhere,
    // and if they don't send a CONNECT
    // packet, kill them
    return new Client(that, conn)
  }
  this.persistence = opts.persistence || memory()
  this.persistence.broker = this
  this._parallel = parallel()
  this._series = series()

  this.clients = {}
  this.brokers = {}

  var hearbeatTopic = '$SYS/' + that.id + '/heartbeat'
  this._heartbeatInterval = setInterval(heartbeat, opts.hearbeatInterval)

  function heartbeat () {
    that.publish({
      topic: hearbeatTopic,
      payload: new Buffer(that.id)
    }, noop)
  }

  function deleteOldBrokers (broker) {
    if (that.brokers[broker] + 3 * opts.heartbeatInterval < Date.now()) {
      delete that.brokers[broker]
    }
  }

  this._clearWillInterval = setInterval(function () {
    Object.keys(that.brokers).forEach(deleteOldBrokers)

    that.persistence
      .streamWill(that.brokers)
      .pipe(bulk.obj(receiveWills))
  }, opts.heartbeatInterval * 4)

  function receiveWills (chunks, done) {
    that._parallel(that, checkAndPublish, chunks, done)
  }

  function checkAndPublish (will, done) {
    var needsPublishing =
      !that.brokers[will.brokerId] ||
      that.brokers[will.brokerId] + 3 * opts.heartbeatInterval <
      Date.now()

    if (needsPublishing) {
      // randomize this, so that multiple brokers
      // do not publish the same wills at the same time
      that.publish(will, function (err) {
        if (err) {
          return done(err)
        }

        that.persistence.delWill({
          id: will.clientId
        }, done)
      })
    } else {
      done()
    }
  }

  this.mq.on('$SYS/+/hearbeat', function storeBroker (packet, done) {
    that.brokers[packet.payload.toString()] = Date.now()
  })
}

util.inherits(Aedes, EE)

function storeRetained (packet, done) {
  if (packet.retain) {
    this.persistence.storeRetained(packet, done)
  } else {
    done()
  }
}

function emitPacket (packet, done) {
  this.mq.emit(packet, done)
}

function enqueueOffline (packet, done) {
  var that = this

  if (packet.qos > 0) {
    this.persistence.subscriptionsByTopic(packet.topic, function (err, subs) {
      if (err) {
        // is this really recoverable?
        // let's just error the whole aedes
        that.emit('error', err)
      }
      // TODO remove callback

      doEnqueues(that, packet, subs, done)
    })
  } else {
    done()
  }
}

function EnqueuedStatus (packet, broker) {
  this.packet = packet
  this.broker = broker
}

function doEnqueues (broker, packet, subs, done) {
  if (subs.length === 0) {
    done()
  } else {
    broker._parallel(
      new EnqueuedStatus(packet, broker),
      doEnqueue, subs, done)
  }
}

function doEnqueue (sub, done) {
  this.broker.persistence.outgoingEnqueue(sub, this.packet, done)
}

var publishFuncs = [
  storeRetained,
  enqueueOffline,
  emitPacket
]
Aedes.prototype.publish = function (packet, done) {
  var p = new Packet(packet, this)
  this._series(this, publishFuncs, p, done)
}

Aedes.prototype.subscribe = function (topic, func, done) {
  var broker = this

  this.mq.on(topic, func, function subscribed () {
    if (done) {
      // first do a suback
      done()
    }

    var stream = broker.persistence.createRetainedStream(topic)

    stream.pipe(through.obj(function (packet, enc, cb) {
      func(packet, cb)
    }))
  })
}

Aedes.prototype.unsubscribe = function (topic, func, done) {
  this.mq.removeListener(topic, func, done)
}

Aedes.prototype.registerClient = function (client) {
  this.clients[client.id] = client
}

Aedes.prototype.unregisterClient = function (client) {
  delete this.clients[client.id]
}

function closeClient (client, cb) {
  this.clients[client].close(cb)
}

Aedes.prototype.close = function (cb) {
  clearInterval(this._heartbeatInterval)
  clearInterval(this._clearWillInterval)
  this._parallel(this, closeClient, Object.keys(this.clients), cb || noop)
}

function noop () {}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015 Scott Bishop
 * BluJagu, LLC - www.blujagu.com
 * MIT License (MIT) - This header must remain intact.
 **/
define(['square', 'comparator', 'Select'], function (square, comparator, Select) {
    'use strict';

    var Table = function (db, tableName) {
        // set prototype on the instance when `new Table()`
        // set prototype on constructor on instantiation
        this.__proto__ = {
            '_db': db,
            '_event': db._event + '.' + tableName,
            'constructor': this,
            'columns': function () {
                var cols = [], prop;

                for (prop in this) {
                    if (this.hasOwnProperty(prop)) {
                        cols.push(prop);
                    }
                }

                return cols;
            },
            'count': function () {
                var len = this.indices().length,
                    db = this._db.prototype;

                if (db.dispatch) {
                    db.dispatch(this._event + '.count.read', {
                        value: len
                    });
                }

                return len;
            },
            'indices': function () {
                var indices = [],
                    col, prop, i = 0, len;

                for (prop in this) {
                    if (this.hasOwnProperty(prop)) {
                        col = this[prop];
                        for (len = col.length; i < len; ++i) {
                            if (col[i] !== null) {
                                indices.push(i);
                            }
                        }
                        return indices;
                    }
                }

                return indices;
            },
            'holes': function () {
                var holes = [],
                    col, prop, i = 0, len;

                for (prop in this) {
                    if (this.hasOwnProperty(prop)) {
                        col = this[prop];
                        for (len = col.length; i < len; ++i) {
                            if (col[i] === null) {
                                holes.push(i);
                            }
                        }
                        return holes;
                    }
                }

                return holes;
            }
        };

        if (!this.prototype) {
            Object.defineProperty(this, 'prototype', {
                enumerable: false,
                configurable: false,
                value: this.__proto__
            });
        }

        return this;
    };

    var Column = function (table, columnName) {
        this.__proto__ = {
            '_event': table && columnName && table._event + '.' + columnName,
            '_db': table && table._db,
            '_table': table,
            'push': function (x) {
                var db = this._db.prototype;

                if (db.dispatch) {
                    db.dispatch(this._event + '.create', {
                        value: x,
                        index: this.length - 1
                    });
                    this._table.count();
                }

                return Array.prototype.push.call(this, x);
            },
            'insert': function (x, ndx) {
                var exists = ndx in this,
                    db = this._db.prototype;

                this[ndx] = x;
                if (db.dispatch) {
                    db.dispatch(this._event + '.' + ndx + '.update', {
                        value: x,
                        index: ndx
                    });
                }

                if (!exists && x !== null) {
                    ++this.length;
                }
            }
        };

        if (!this.prototype) {
            Object.defineProperty(this, 'prototype', {
                enumerable: false,
                configurable: false,
                value: this.__proto__
            });

            this.prototype.__proto__ = Array.prototype;
        }

        return this;
    };

    var _memory = {},
        getColumnNames = function (/*columns*/) {
            var columnNames = Array.from(arguments);

            if (columnNames.length === 1 && columnNames[0].indexOf(',') !== -1) {
                columnNames = columnNames[0].split(',').map(function (el) {
                    return el.trim();
                });
            }

            return columnNames;
        },
        Where = function (table, column, operator, control) {
            this.validIndices = comparator(table[column], operator, control);
            this.AND = this.and = function (column, operator, control) {
                var newIndices = comparator(table[column], operator, control);

                this.validIndices = this.validIndices.filter(function (v) {
                    return newIndices.indexOf(v) !== -1;
                });

                return this;
            };
            this.OR = this.or = function (column, operator, control) {
                var cache = [];

                this.validIndices = this.validIndices.concat(comparator(table[column], operator, control));

                this.validIndices = this.validIndices.filter(function (v) {
                    if (cache.indexOf(v) === -1) {
                        cache.push(v);
                        return true;
                    }
                });

                return this;
            };
        };

    _memory.__proto__ = {
        'create': function (dbName) {
            var db = new DB(dbName);

            this[dbName] = db;

            return db;
        },
        'drop': function (dbName) {
            if (this[dbName]) {
                this[dbName] = null;
                delete this[dbName];

                return true;
            }

            return false;
        },
        'get': function (dbName) {
            return this[dbName];
        },
        'show': function () {
            var prop, arr = [];

            for (prop in this) {
                if (this.hasOwnProperty(prop)) {
                    arr.push(prop);
                }
            }

            return arr;
        }
    };

    var DB = function DB (dbName) {
        this.__proto__ = {
            '_event': dbName,
            '_tableCount': 0,
            '_countUp': function () {
                // todo: remove these...
                var count = ++this._tableCount,
                    db = this.prototype;

                if (db.dispatch) {
                    db.dispatch(this._event + '.count.update', {
                        value: count
                    });
                }
            },
            '_countDown': function () {
                var count = --this._tableCount,
                    db = this.prototype;

                if (db.dispatch) {
                    db.dispatch(this._event + '.count.update', {
                        value: count
                    });
                }
            },
            'count': function () {
                var count =  this._tableCount,
                    db = this.prototype;

                if (db.dispatch) {
                    db.dispatch(this._event + '.count.read', {
                        value: count
                    });
                }
                return count;
            },
            'COUNT': function () {
                return this.count.call(this);
            },
            'select': function (/*selects*/) {
                var selects = getColumnNames.apply(null, arguments);

                return new Select(this, selects);
            },
            'SELECT': function (/*selects*/) {
                return this.select.apply(this, arguments);
            },
            'createTable': function (tableName) {
                /**
                 * createTable adds a new Table Object <tableName> to the DB Object
                 * @param {String} tableName Name to assign to the new table
                 * @returns {Function} Returns a curried function waiting for the columns argument
                 */
                var db = this,
                    table = new Table(db, tableName);

                db[tableName] = table;

                if (db.prototype.dispatch) {
                    db.prototype.dispatch(this._event + '.create', {
                        value: table
                    });
                }

                this._countUp();

                return function (/*columns*/) {
                    var columns = getColumnNames.apply({}, arguments);

                    if (columns.length) {
                        db.alterTable(tableName).add.apply({}, arguments);
                    }

                    return table;
                };
            },
            'CREATE_TABLE': function (tableName) {
                return this.createTable.call(this, tableName);
            },
            'alterTable': function (tableName) {
                var table = this[tableName];

                return {
                    'add': function (/*columns*/) {
                        var cols = getColumnNames.apply(null, arguments),
                            col, i = 0, len = cols.length,
                            indices = table.indices(),
                            holes = table.holes(),
                            j = 0, jLen = indices.length,
                            newColumn, db = table._db.prototype;

                        for (i; i < len; ++i) {
                            col = cols[i];
                            newColumn = table[col] = new Column(table, col);
                            for (j = 0; j < jLen; ++j) {
                                newColumn.insert(undefined, indices[j]);
                            }
                            jLen = holes.length;
                            for (j = 0; j < jLen; ++j) {
                                newColumn.insert(null, holes[j]);
                            }
                            if (db.dispatch) {
                                db.dispatch(table._event + '.create', {
                                    value: newColumn
                                });
                            }
                        }

                        return table;
                    },
                    'ADD': function (/*columns*/) {
                        return this.add.apply(this, arguments);
                    },
                    'drop': function (/*columns*/) {
                        var cols = getColumnNames.apply(null, arguments),
                            col, i = 0, len, db = table._db.prototype;

                        if (cols.length === 0 || cols[0] === '*') {
                            cols = table.columns();
                        }

                        for (len = cols.length; i < len; ++i) {
                            col = cols[i];
                            table[col] = null;
                            delete table[col];
                            if (db.dispatch) {
                                db.dispatch(table._event + '.delete', {
                                    value: col
                                });
                            }
                        }

                        return table;
                    },
                    'DROP': function (/*columns*/) {
                        return this.drop.apply(this, arguments);
                    },
                    'modify': function () {
                        // only needed if I support data types on columns
                    }
                }
            },
            'ALTER_TABLE': function (tableName) {
                return this.alterTable.call(this, tableName);
            },
            'insertInto': function (tableName) {
                var table = this[tableName];

                return function (/*columns*/) {
                    var columns = getColumnNames.apply({}, arguments),
                        values = function (/*insertValues*/) {
                            var vals = Array.from(arguments),
                                column, columnName, val, i = 0, len = columns.length;

                            for (i; i < len; ++i) {
                                columnName = columns[i];
                                val = vals[i];
                                column = table[columnName];
                                column.push(val);
                            }

                            for (columnName in table) {
                                if (table.hasOwnProperty(columnName)) {
                                    if (columns.indexOf(columnName) === -1) {
                                        // all columns in the table that did not get a value set should be set to undefined
                                        table[columnName].push(undefined);
                                    }
                                }
                            }

                            return values;
                        };

                    return {
                        'values': values,
                        'VALUES': values
                    };
                };
            },
            'INSERT_INTO': function (tableName) {
                return this.insertInto.call(this, tableName);
            },
            'insertJsonInto': function (tableName) {
                var table = this[tableName],
                    db = this;

                return function (insertObjects /*[objects]*/) {
                    var prop, insert, columnNames, add, vals,
                        i =0, len = insertObjects.length,
                        tableName = table._event.substr(table._event.indexOf('.') + 1),
                        insertToColumns = db.insertInto(tableName);

                    for (i; i < len; ++i) {
                        insert = insertObjects[i];
                        columnNames = [];
                        vals = [];
                        for (prop in insert) {
                            if (insert.hasOwnProperty(prop)) {
                                if (!table[prop]) {
                                    db.alterTable(tableName).add(prop);
                                }
                                columnNames.push(prop);
                                vals.push(insert[prop]);
                            }
                        }
                        add = insertToColumns.apply(null, columnNames);
                        add.values.apply(null, vals);
                    }
                };
            },
            'INSERT_JSON_INTO': function (tableName) {
                this.insertJsonInto.call(this, tableName);
            },
            'update': function (tableName) {
                var table = this[tableName],
                    db = table._db.prototype,
                    updateMap = {},
                    set = function (column, value) {
                        updateMap[column] = value;

                        return set;
                    };

                set.WHERE = set.where = function (column, operator, control) {
                    var w = new Where(table, column, operator, control);

                    w.GO = w.go = function () {
                        var i = 0, len = this.validIndices.length, ndx, prop, val, crud = '.update' ;

                        for (i; i < len; ++i) {
                            ndx = this.validIndices[i];
                            for (prop in table) {
                                if (table.hasOwnProperty(prop) && updateMap[prop]) {
                                    val = updateMap[prop];
                                    table[prop][ndx] = val;
                                    if (db.dispatch) {
                                        if (val === null) {
                                            crud = '.delete';
                                        }
                                        db.dispatch(table._event + '.' + prop + crud, {
                                            value: val,
                                            index: ndx
                                        });
                                    }
                                }
                            }
                        }

                        return true;
                    };

                    return w;
                };

                return {
                    'set': set,
                    'SET': set
                }
            },
            'UPDATE': function (tableName) {
                return this.update.call(this, tableName);
            },
            'delete': function (/*columnNames*/) {
                var columns = getColumnNames.apply({}, arguments),
                    db = this,
                    table,
                    from = function (tableName) {
                        table = db[tableName];
                        if (columns.length === 0 || columns[0] === '*') {
                            columns = table.columns();
                        }

                        return {
                            'where': where,
                            'WHERE': where,
                            'go': go,
                            'GO': go
                        }
                    },
                    go = function () {
                        var matches = this.validIndices,
                            i = 0, len, ndx, j, colLen = columns.length, column;

                        if (matches === undefined) {
                            matches = table.indices();
                            // table.indices gives all possible matches
                        }

                        for (i, len = matches.length; i < len; ++i) {
                            ndx = matches[i];
                            for (j = 0; j < colLen; ++j) {
                                column = table[columns[j]];
                                column.insert(null, ndx);
                                if (db.prototype.dispatch) {
                                    db.prototype.dispatch(column._event + '.' + ndx + '.delete', {
                                        value: null,
                                        index: ndx
                                    });
                                    table.count();
                                }
                            }
                        }

                        return true;
                    },
                    where = function (column, operator, control) {
                        var w = new Where(table, column, operator, control);

                        w.GO = w.go = go.bind(w);

                        return w;
                    };

                return {
                    'from': from,
                    'FROM': from
                };
            },
            'DELETE': function (/*columnNames*/) {
                return this.delete.apply(this, arguments);
            },
            'createUnique': function () {
                var tsa = new Date().getTime().toString().split(''),
                    abc = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
                    i = 0, len = tsa.length, rtn = [], n, a;

                for (; i < len; ++i) {
                    n = tsa[i];
                    a = abc[n];
                    if (i % 2 === 0) {
                        if (i % 8 === 4) {
                            a = a.toUpperCase();
                        }
                        rtn.push(a);
                    } else {
                        rtn.push(n);
                    }
                }

                rtn = rtn.map(function (v) {
                    switch (v) {
                        case '0': return 'O';
                        case '1': return 'I';
                        case '2': return 'R';
                        case '3': return 'E';
                        case '4': return 'F';
                        case '5': return 'S';
                        case '6': return 'b';
                        case '7': return 'L';
                        case '8': return 'B';
                        case '9': return 'q';
                        default: return v;
                    }
                });

                return rtn.join('');
            }
        };

        if (!this.prototype) {
            Object.defineProperty(this, 'prototype', {
                enumerable: false,
                configurable: false,
                value: this.__proto__
            });
        }

        return this;
    };

    return {
        'createDB': _memory.create,
        'CREATE_DATABASE': _memory.create,
        'dropDB': _memory.drop,
        'DROP_DATABASE': _memory.drop,
        'use': _memory.get,
        'USE': _memory.get,
        'show': _memory.show,
        'SHOW_DATABASES': _memory.show
    };
});
<commit_msg>squaredb hardening<commit_after>/**
 * Copyright (c) 2015 Scott Bishop
 * BluJagu, LLC - www.blujagu.com
 * MIT License (MIT) - This header must remain intact.
 **/
define(['square', 'comparator', 'Select'], function (square, comparator, Select) {
    'use strict';

    var Table = function (db, tableName) {
        // set prototype on the instance when `new Table()`
        // set prototype on constructor on instantiation
        this.__proto__ = {
            '_db': db,
            '_event': db._event + '.' + tableName,
            'constructor': this,
            'columns': function () {
                var cols = [], prop;

                for (prop in this) {
                    if (this.hasOwnProperty(prop)) {
                        cols.push(prop);
                    }
                }

                return cols;
            },
            'count': function () {
                var len = this.indices().length,
                    db = this._db;

                if (db.dispatch) {
                    db.dispatch(this._event + '.count.read', {
                        value: len
                    });
                }

                return len;
            },
            'indices': function () {
                var indices = [],
                    col, prop, i = 0, len;

                for (prop in this) {
                    if (this.hasOwnProperty(prop)) {
                        col = this[prop];
                        for (len = col.length; i < len; ++i) {
                            if (col[i] !== null) {
                                indices.push(i);
                            }
                        }
                        return indices;
                    }
                }

                return indices;
            },
            'holes': function () {
                var holes = [],
                    col, prop, i = 0, len;

                for (prop in this) {
                    if (this.hasOwnProperty(prop)) {
                        col = this[prop];
                        for (len = col.length; i < len; ++i) {
                            if (col[i] === null) {
                                holes.push(i);
                            }
                        }
                        return holes;
                    }
                }

                return holes;
            }
        };

        if (!this.prototype) {
            Object.defineProperty(this, 'prototype', {
                enumerable: false,
                configurable: false,
                value: this.__proto__
            });
        }

        return this;
    };

    var Column = function (table, columnName) {
        this.__proto__ = {
            '_event': table && columnName && table._event + '.' + columnName,
            '_db': table && table._db,
            '_table': table,
            'push': function (x) {
                var db = this._db;

                if (db.dispatch) {
                    db.dispatch(this._event + '.create', {
                        value: x,
                        index: this.length - 1
                    });
                    this._table.count();
                }

                return Array.prototype.push.call(this, x);
            },
            'insert': function (x, ndx) {
                var exists = ndx in this,
                    db = this._db;

                this[ndx] = x;
                if (db.dispatch) {
                    db.dispatch(this._event + '.' + ndx + '.update', {
                        value: x,
                        index: ndx
                    });
                }

                if (!exists && x !== null) {
                    ++this.length;
                }
            }
        };

        if (!this.prototype) {
            Object.defineProperty(this, 'prototype', {
                enumerable: false,
                configurable: false,
                value: this.__proto__
            });

            this.prototype.__proto__ = Array.prototype;
        }

        return this;
    };

    var _memory = {},
        getColumnNames = function (/*columns*/) {
            var columnNames = Array.from(arguments);

            if (columnNames.length === 1 && columnNames[0].indexOf(',') !== -1) {
                columnNames = columnNames[0].split(',').map(function (el) {
                    return el.trim();
                });
            }

            return columnNames;
        },
        Where = function (table, column, operator, control) {
            this.validIndices = comparator(table[column], operator, control);
            this.AND = this.and = function (column, operator, control) {
                var newIndices = comparator(table[column], operator, control);

                this.validIndices = this.validIndices.filter(function (v) {
                    return newIndices.indexOf(v) !== -1;
                });

                return this;
            };
            this.OR = this.or = function (column, operator, control) {
                var cache = [];

                this.validIndices = this.validIndices.concat(comparator(table[column], operator, control));

                this.validIndices = this.validIndices.filter(function (v) {
                    if (cache.indexOf(v) === -1) {
                        cache.push(v);
                        return true;
                    }
                });

                return this;
            };
        };

    _memory.__proto__ = {
        'create': function (dbName) {
            var db = new DB(dbName);

            this[dbName] = db;

            return db;
        },
        'drop': function (dbName) {
            if (this[dbName]) {
                this[dbName] = null;
                delete this[dbName];

                return true;
            }

            return false;
        },
        'get': function (dbName) {
            return this[dbName];
        },
        'show': function () {
            var prop, arr = [];

            for (prop in this) {
                if (this.hasOwnProperty(prop)) {
                    arr.push(prop);
                }
            }

            return arr;
        }
    };

    var DB = function DB (dbName) {
        this.__proto__ = {
            '_event': dbName,
            '_tableCount': 0,
            'count': function () {
                var count =  this._tableCount;

                if (this.dispatch) {
                    this.dispatch(this._event + '.count.read', {
                        value: count
                    });
                }
                return count;
            },
            'COUNT': function () {
                return this.count.call(this);
            },
            'select': function (/*selects*/) {
                var selects = getColumnNames.apply(null, arguments);

                return new Select(this, selects);
            },
            'SELECT': function (/*selects*/) {
                return this.select.apply(this, arguments);
            },
            'createTable': function (tableName) {
                /**
                 * createTable adds a new Table Object <tableName> to the DB Object
                 * @param {String} tableName Name to assign to the new table
                 * @returns {Function} Returns a curried function waiting for the columns argument
                 */
                var db = this,
                    table = new Table(db, tableName);

                db[tableName] = table;

                if (db.dispatch) {
                    db.dispatch(this._event + '.create', {
                        value: table
                    });
                }

                ++this._tableCount;
                this.count();

                return function (/*columns*/) {
                    var columns = getColumnNames.apply({}, arguments);

                    if (columns.length) {
                        db.alterTable(tableName).add.apply({}, arguments);
                    }

                    return table;
                };
            },
            'CREATE_TABLE': function (tableName) {
                return this.createTable.call(this, tableName);
            },
            'alterTable': function (tableName) {
                var table = this[tableName];

                return {
                    'add': function (/*columns*/) {
                        var cols = getColumnNames.apply(null, arguments),
                            col, i = 0, len = cols.length,
                            indices = table.indices(),
                            holes = table.holes(),
                            j = 0, jLen = indices.length,
                            newColumn, db = table._db;

                        for (i; i < len; ++i) {
                            col = cols[i];
                            newColumn = table[col] = new Column(table, col);
                            for (j = 0; j < jLen; ++j) {
                                newColumn.insert(undefined, indices[j]);
                            }
                            jLen = holes.length;
                            for (j = 0; j < jLen; ++j) {
                                newColumn.insert(null, holes[j]);
                            }
                            if (db.dispatch) {
                                db.dispatch(table._event + '.create', {
                                    value: newColumn
                                });
                            }
                        }

                        return table;
                    },
                    'ADD': function (/*columns*/) {
                        return this.add.apply(this, arguments);
                    },
                    'drop': function (/*columns*/) {
                        var cols = getColumnNames.apply(null, arguments),
                            col, i = 0, len, db = table._db;

                        if (cols.length === 0 || cols[0] === '*') {
                            cols = table.columns();
                        }

                        for (len = cols.length; i < len; ++i) {
                            col = cols[i];
                            table[col] = null;
                            delete table[col];
                            if (db.dispatch) {
                                db.dispatch(table._event + '.delete', {
                                    value: col
                                });
                            }
                        }

                        return table;
                    },
                    'DROP': function (/*columns*/) {
                        return this.drop.apply(this, arguments);
                    },
                    'modify': function () {
                        // only needed if I support data types on columns
                    }
                }
            },
            'ALTER_TABLE': function (tableName) {
                return this.alterTable.call(this, tableName);
            },
            'insertInto': function (tableName) {
                var table = this[tableName];

                return function (/*columns*/) {
                    var columns = getColumnNames.apply({}, arguments),
                        values = function (/*insertValues*/) {
                            var vals = Array.from(arguments),
                                column, columnName, val, i = 0, len = columns.length;

                            for (i; i < len; ++i) {
                                columnName = columns[i];
                                val = vals[i];
                                column = table[columnName];
                                column.push(val);
                            }

                            for (columnName in table) {
                                if (table.hasOwnProperty(columnName)) {
                                    if (columns.indexOf(columnName) === -1) {
                                        // all columns in the table that did not get a value set should be set to undefined
                                        table[columnName].push(undefined);
                                    }
                                }
                            }

                            return values;
                        };

                    return {
                        'values': values,
                        'VALUES': values
                    };
                };
            },
            'INSERT_INTO': function (tableName) {
                return this.insertInto.call(this, tableName);
            },
            'insertJsonInto': function (tableName) {
                var table = this[tableName],
                    db = this;

                return function (insertObjects /*[objects]*/) {
                    var prop, insert, columnNames, add, vals,
                        i =0, len = insertObjects.length,
                        tableName = table._event.substr(table._event.indexOf('.') + 1),
                        insertToColumns = db.insertInto(tableName);

                    for (i; i < len; ++i) {
                        insert = insertObjects[i];
                        columnNames = [];
                        vals = [];
                        for (prop in insert) {
                            if (insert.hasOwnProperty(prop)) {
                                if (!table[prop]) {
                                    db.alterTable(tableName).add(prop);
                                }
                                columnNames.push(prop);
                                vals.push(insert[prop]);
                            }
                        }
                        add = insertToColumns.apply(null, columnNames);
                        add.values.apply(null, vals);
                    }
                };
            },
            'INSERT_JSON_INTO': function (tableName) {
                this.insertJsonInto.call(this, tableName);
            },
            'update': function (tableName) {
                var table = this[tableName],
                    db = table._db,
                    updateMap = {},
                    set = function (column, value) {
                        updateMap[column] = value;

                        return set;
                    };

                set.WHERE = set.where = function (column, operator, control) {
                    var w = new Where(table, column, operator, control);

                    w.GO = w.go = function () {
                        var i = 0, len = this.validIndices.length, ndx, prop, val, crud = '.update' ;

                        for (i; i < len; ++i) {
                            ndx = this.validIndices[i];
                            for (prop in table) {
                                if (table.hasOwnProperty(prop) && updateMap[prop]) {
                                    val = updateMap[prop];
                                    table[prop][ndx] = val;
                                    if (db.dispatch) {
                                        if (val === null) {
                                            crud = '.delete';
                                        }
                                        db.dispatch(table._event + '.' + prop + crud, {
                                            value: val,
                                            index: ndx
                                        });
                                    }
                                }
                            }
                        }

                        return true;
                    };

                    return w;
                };

                return {
                    'set': set,
                    'SET': set
                }
            },
            'UPDATE': function (tableName) {
                return this.update.call(this, tableName);
            },
            'delete': function (/*columnNames*/) {
                var columns = getColumnNames.apply({}, arguments),
                    db = this,
                    table,
                    from = function (tableName) {
                        table = db[tableName];
                        if (columns.length === 0 || columns[0] === '*') {
                            columns = table.columns();
                        }

                        return {
                            'where': where,
                            'WHERE': where,
                            'go': go,
                            'GO': go
                        }
                    },
                    go = function () {
                        var matches = this.validIndices,
                            i = 0, len, ndx, j, colLen = columns.length, column;

                        if (matches === undefined) {
                            matches = table.indices();
                            // table.indices gives all possible matches
                        }

                        for (i, len = matches.length; i < len; ++i) {
                            ndx = matches[i];
                            for (j = 0; j < colLen; ++j) {
                                column = table[columns[j]];
                                column.insert(null, ndx);
                                if (db.dispatch) {
                                    db.dispatch(column._event + '.' + ndx + '.delete', {
                                        value: null,
                                        index: ndx
                                    });
                                    --table._tableCount;
                                    table.count();
                                }
                            }
                        }

                        return true;
                    },
                    where = function (column, operator, control) {
                        var w = new Where(table, column, operator, control);

                        w.GO = w.go = go.bind(w);

                        return w;
                    };

                return {
                    'from': from,
                    'FROM': from
                };
            },
            'DELETE': function (/*columnNames*/) {
                return this.delete.apply(this, arguments);
            },
            'createUnique': function () {
                var tsa = new Date().getTime().toString().split(''),
                    abc = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
                    i = 0, len = tsa.length, rtn = [], n, a;

                for (; i < len; ++i) {
                    n = tsa[i];
                    a = abc[n];
                    if (i % 2 === 0) {
                        if (i % 8 === 4) {
                            a = a.toUpperCase();
                        }
                        rtn.push(a);
                    } else {
                        rtn.push(n);
                    }
                }

                rtn = rtn.map(function (v) {
                    switch (v) {
                        case '0': return 'O';
                        case '1': return 'I';
                        case '2': return 'R';
                        case '3': return 'E';
                        case '4': return 'F';
                        case '5': return 'S';
                        case '6': return 'b';
                        case '7': return 'L';
                        case '8': return 'B';
                        case '9': return 'q';
                        default: return v;
                    }
                });

                return rtn.join('');
            }
        };

        if (!this.prototype) {
            Object.defineProperty(this, 'prototype', {
                enumerable: false,
                configurable: false,
                value: this.__proto__
            });
        }

        return this;
    };

    return {
        'createDB': _memory.create,
        'CREATE_DATABASE': _memory.create,
        'dropDB': _memory.drop,
        'DROP_DATABASE': _memory.drop,
        'use': _memory.get,
        'USE': _memory.get,
        'show': _memory.show,
        'SHOW_DATABASES': _memory.show
    };
});
<|endoftext|>


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

var tele = require("./index.js");
var fs = require("fs");
var path = require("path");
var argv = require("optimist")
  .default("id", "./seed.json")
  .default("port", 42424)
  .default("bridge", true)
  .boolean("v").describe("v", "verbose")
  .boolean("nolan").describe("nolan", "disable lan usage")
  .argv;

if(argv.v) tele.debug(console.log);
tele.info(function(){console.log.apply(console,arguments)});

if(argv.port == 42420)
{
  console.log("that port is reserved");
  process.exit(1);
}

// localize our id file
argv.id = path.resolve(argv.id);
if(argv.seeds) argv.seeds = path.resolve(argv.seeds);

tele.init(argv, function(err, seed){
  if(!seed) return console.log("something went wrong :(",err) || process.exit(1);
  console.log("PATHS",seed.paths);
  var ip4 = seed.paths.pub4 || seed.paths.lan4;
  var ip6 = seed.paths.pub6 || seed.paths.lan6;
  var info = {paths:[], parts:seed.parts, keys:seed.keys};
  info.paths.push({type:"ipv4",ip:ip4.ip,port:ip4.port});
  if(ip6) info.paths.push({type:"ipv6",ip:ip6.ip,port:ip6.port});
  if(seed.paths.http.http) info.paths.push({type:"http",http:seed.paths.http.http});
  else info.paths.push({type:"http",http:"http://"+ip4.ip+":"+seed.paths.http.port});

  var seeds = {};
  seeds[seed.hashname] = info;
  console.log(JSON.stringify(seeds,null,2));
  console.log("connected to "+Object.keys(seed.lines).length+" mesh seed peers");
});
<commit_msg>local path information is now managed by thjs<commit_after>#!/usr/bin/env node

var tele = require("./index.js");
var fs = require("fs");
var path = require("path");
var argv = require("optimist")
  .default("id", "./seed.json")
  .default("port", 42424)
  .default("bridge", true)
  .boolean("v").describe("v", "verbose")
  .boolean("nolan").describe("nolan", "disable lan usage")
  .argv;

if(argv.v) tele.debug(console.log);
tele.info(function(){console.log.apply(console,arguments)});

if(argv.port == 42420)
{
  console.log("that port is reserved");
  process.exit(1);
}

// localize our id file
argv.id = path.resolve(argv.id);
if(argv.seeds) argv.seeds = path.resolve(argv.seeds);

tele.init(argv, function(err, seed){
  if(!seed) return console.log("something went wrong :(",err) || process.exit(1);
  var info = {paths:seed.paths, parts:seed.parts, keys:seed.keys};

  var seeds = {};
  seeds[seed.hashname] = info;
  console.log(JSON.stringify(seeds,null,2));
  console.log("connected to "+Object.keys(seed.lines).length+" mesh seed peers");
});
<|endoftext|>