<commit_before>import rp from 'request-promise';
import DataLoader from 'dataloader';

import {
  identity,
  range,
  forOwn,
  isArray,
} from 'lodash';

// Encapsulates session management, dataloader caching, and pagination
export class DiscourseContext {
  COOKIE_KEY = '_forum_session';
  TOKEN_KEY = '_t';

  constructor({ loginToken, apiRoot }) {
    this.apiRoot = apiRoot;
    this.loginToken = loginToken;

    this.urlDataLoader = new DataLoader((urls) => {
      console.log('Fetching batch:', urls);
      // XXX we probably shouldn't batch requests to the backend for REST.

      const options = {
        json: true,
      };

      if (this.loginToken) {
        options.headers = {
          'Cookie': this.TOKEN_KEY + '=' + this.loginToken,
        };
      }

      return Promise.all(urls.map((url) => {
        return rp({
          uri: url,
          ...options,
        }).catch((err) => {
          console.log(err);
          throw err;
        });
      }));
    });
  }

  getPagesWithParams(url, { page = 0, numPages = 1 }, params = {}) {
    const pageNumbers = range(page, page + numPages);

    const urls = pageNumbers.map((pageNumber) => {
      const myParams = {
        page: pageNumber,
        ...params,
      };

      return `${url}?${serializeParamsForRails(myParams)}`;
    });
    const requestPromises = urls.map(myUrl => this.get(myUrl));
    return Promise.all(requestPromises).then((results) => {
      return {
        pages: results.map((result) => {
          return result.topic_list;
        }),
      };
    });
  }

  _fetchEndpoint(endpoint, args) {
    if (endpoint.fetch) {
      return endpoint.fetch(args, this);
    }

    return this.urlDataLoader.load(this.apiRoot + endpoint.url(args))
      .then(endpoint.map || identity);
  }

  get(url) {
    return this.urlDataLoader.load(this.apiRoot + url);
  }

  getLoginToken(username, password) {
    return this.getCSRFAndCookieThen((csrf, cookie) => {
      return rp({
        method: 'POST',
        uri: `${this.apiRoot}/session.json`,
        form: {
          login: username,
          password,
        },
        headers: {
          'X-CSRF-Token': csrf,
          Cookie: `${this.COOKIE_KEY}=${cookie}`,
        },
        json: true,
        resolveWithFullResponse: true,
      });
    }).then((res) => {
      if (res.body.error) {
        throw new Error(res.body.error);
      }

      const token = this.getForumToken(res);
      return token;
    }).catch((err) => {
      throw err;
    });
  }

  getForumCookie(res) {
    return res.headers['set-cookie'].filter((cookie) => {
      return cookie.startsWith(this.COOKIE_KEY);
    })[0].split(' ')[0].split('=')[1].split(';')[0];
  }

  getForumToken(res) {
    return res.headers['set-cookie'].filter((cookie) => {
      return cookie.startsWith(this.TOKEN_KEY);
    })[0].split(' ')[0].split('=')[1].split(';')[0];
  }

  // XXX why not just chain the promises?
  getCSRFAndCookieThen(callback) {
    return rp({
      uri: this.apiRoot + '/session/csrf.json',
      json: true,
      resolveWithFullResponse: true,
    }).then((res) => {
      const cookie = this.getForumCookie(res);
      const csrf = res.body.csrf;

      return callback(csrf, cookie);
    });
  }
}

function serializeParamsForRails(paramsObj) {
  const segments = [];

  forOwn(paramsObj, (value, key) => {
    if (isArray(value)) {
      value.forEach((arrayItem) => {
        segments.push(`${encodeURIComponent(key)}[]=${encodeURIComponent(arrayItem)}`);
      });
      return;
    }

    segments.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
  });

  return segments.join('&');
}
<commit_msg>linting<commit_after>import rp from 'request-promise';
import DataLoader from 'dataloader';

import {
  identity,
  range,
  forOwn,
  isArray,
} from 'lodash';

// Encapsulates session management, dataloader caching, and pagination
export class DiscourseContext {
  COOKIE_KEY = '_forum_session';
  TOKEN_KEY = '_t';

  constructor({ loginToken, apiRoot }) {
    this.apiRoot = apiRoot;
    this.loginToken = loginToken;

    this.urlDataLoader = new DataLoader((urls) => {
      console.log('Fetching batch:', urls);
      // XXX we probably shouldn't batch requests to the backend for REST.

      const options = {
        json: true,
      };

      if (this.loginToken) {
        options.headers = {
          Cookie: `${this.TOKEN_KEY}=${this.loginToken}`,
        };
      }

      return Promise.all(urls.map((url) => {
        return rp({
          uri: url,
          ...options,
        }).catch((err) => {
          console.log(err);
          throw err;
        });
      }));
    });
  }

  getPagesWithParams(url, { page = 0, numPages = 1 }, params = {}) {
    const pageNumbers = range(page, page + numPages);

    const urls = pageNumbers.map((pageNumber) => {
      const myParams = {
        page: pageNumber,
        ...params,
      };

      return `${url}?${serializeParamsForRails(myParams)}`;
    });
    const requestPromises = urls.map(myUrl => this.get(myUrl));
    return Promise.all(requestPromises).then((results) => {
      return {
        pages: results.map((result) => {
          return result.topic_list;
        }),
      };
    });
  }

  _fetchEndpoint(endpoint, args) {
    if (endpoint.fetch) {
      return endpoint.fetch(args, this);
    }

    return this.urlDataLoader.load(this.apiRoot + endpoint.url(args))
      .then(endpoint.map || identity);
  }

  get(url) {
    return this.urlDataLoader.load(this.apiRoot + url);
  }

  getLoginToken(username, password) {
    return this.getCSRFAndCookieThen((csrf, cookie) => {
      return rp({
        method: 'POST',
        uri: `${this.apiRoot}/session.json`,
        form: {
          login: username,
          password,
        },
        headers: {
          'X-CSRF-Token': csrf,
          Cookie: `${this.COOKIE_KEY}=${cookie}`,
        },
        json: true,
        resolveWithFullResponse: true,
      });
    }).then((res) => {
      if (res.body.error) {
        throw new Error(res.body.error);
      }

      const token = this.getForumToken(res);
      return token;
    }).catch((err) => {
      throw err;
    });
  }

  getForumCookie(res) {
    return res.headers['set-cookie'].filter((cookie) => {
      return cookie.startsWith(this.COOKIE_KEY);
    })[0].split(' ')[0].split('=')[1].split(';')[0];
  }

  getForumToken(res) {
    return res.headers['set-cookie'].filter((cookie) => {
      return cookie.startsWith(this.TOKEN_KEY);
    })[0].split(' ')[0].split('=')[1].split(';')[0];
  }

  // XXX why not just chain the promises?
  getCSRFAndCookieThen(callback) {
    return rp({
      uri: `${this.apiRoot}/session/csrf.json`,
      json: true,
      resolveWithFullResponse: true,
    }).then((res) => {
      const cookie = this.getForumCookie(res);
      const csrf = res.body.csrf;

      return callback(csrf, cookie);
    });
  }
}

function serializeParamsForRails(paramsObj) {
  const segments = [];

  forOwn(paramsObj, (value, key) => {
    if (isArray(value)) {
      value.forEach((arrayItem) => {
        segments.push(`${encodeURIComponent(key)}[]=${encodeURIComponent(arrayItem)}`);
      });
      return;
    }

    segments.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
  });

  return segments.join('&');
}
<|endoftext|>


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

var _ = require('lodash');
var HevEmitter = require('hevemitter').EventEmitter;
var inherits = require('util').inherits;
var Promise = require('bluebird');
var uid = require('./uid');

var MessageContext = function (options) {
    var _this = this;
    _.extend(_this, _.defaults(_.pick(options, 'domain', 'to', 'from', 'body', 'options')
                              , {
                                  to: []
                                  , from: []
                                  , options: {}
                              }));
};

_.extend(MessageContext.prototype, {
    send: function (to, from, body, options) {
        return this.domain.send(to, from, body, options);
    }
    , get: function (to, body, options) {
        var _this = this;
        return _this.domain.get(to, body, options);
    }
    , request: function (to, body, options) {
        return this.domain.request(to, body, options);
    }
    , proxy: function (to, options) {
        var _this = this;
        return _this.get(to, _this.body, _.extend({}, _this.options, options));
    }
    , reply: function (body, options) {
        options = _.defaults({}, options, { statusCode: '200' });
        var _this = this;
        return _this.send(_this.from, _this.to, body, options);
    }
    , replyPromise: function (p) {
        var _this = this;
        return Promise.resolve(p)
            .then(function (msg) {
                return _this.reply(msg.message || msg, { statusCode: msg.statusCode || '200' });
            })
            .catch(function (msg) {
                return _this.reply(msg.message || msg, { statusCode: msg.statusCode || '500' });
            });

    }
    , forward: function (to, options) {
        var _this = this;
        return _this.send(to, _this.from, _this.body, _.extend({}, _this.options, options));
    }
    , transfer: function (mount, socket, options) {
        var _this = this;
        socket.emit('dual', {
            to: _this.to.slice(mount.length)
            , from: _this.from
            , body: _this.body
            , options: _.extend({}, _this.options, options)
        });
    }
    , error: function (message) {
        var _this = this;
        _this.send(['error'].concat(_this.to), [], {
            message: message
            , ctxt: {
                to: _this.to
                , from: _this.from
                , body: _this.body
                , options: _this.options
            }
        });
    }
    , toJSON: function () {
        return _.pick(this, 'to', 'from', 'body', 'options');
    }
    , parent: function (n) {
        if (n !== 0) {
            n = n || 1;
        }
        var _this = this;
        if (n > _this.to.length) {
            throw new Error('Invalid parent slice ' + n + ' for point ' + _this.to.join('/'));
        }
        else {
            return _this.to.slice(0, _this.to.length - n);
        }
    }
});

var mountParametrized = function (domain, point, host) {
    var params = [];
    var tailparams = [];
    if (!(_.isArray(point) && point.length > 0)) {
        throw new Error('Unable to mount empty point');
    }
    point = _.map(point, function (name, index) {
        if (_.isString(name)
            && name[0] === ':') {
            if (name[1] === ':') {
                tailparams.push([name.slice(2), index]);
                return '**';
            }
            else {
                params.push([name.slice(1), index]);
                return '*';
            }
        }
        else {
            return name;
        }
    });
    if (params.length !== 0
        || tailparams.length !== 0) {
        var parseParams = function (msg) {
            msg.params = {};
            _.each(params, function (param) {
                msg.params[param[0]] = msg.to[param[1]];
            });
            _.each(tailparams, function (tailparam) {
                msg.params[tailparam[0]] = msg.to.slice(tailparam[1]);
            });
        };
        f = function (msg) {
            parseParams(msg);
            return host(msg);
        };
        f.listener = host;
        host = f;
    }
    domain.on(point, host);
};

var Domain = function (options) {
    var _this = this;
    _this.hosts = {};
    HevEmitter.call(_this);
    _this.options = options || {};
};

inherits(Domain, HevEmitter);

_.extend(Domain.prototype, {
    mount: function (point, host) {
        var _this = this;

        if (arguments.length < 2)
        {
            host = point;
            point = [];
        }

        if (_.isString(point)) {
            point = [point];
        }

        if (_.isFunction(host)) {
            mountParametrized(_this, point, host);
        }
        else if (_.isArray(host)) {
            _.each(host, function (f) {
                if (_.isFunction(f)) {
                    mountParametrized(_this, point, f);
                }
                else {
                    _this.mount(point, f);
                }
            });
        }
        else if (_.isObject(host)) {
            _.each(host, function (f, n) {
                if (_.isObject(f)) {
                    _this.mount(point.concat(n), f);
                }
                else {
                    mountParametrized(_this, point.concat(n), f);
                }
            });
        }
        return _this;
    }
    , unmount: function (point) {
        var _this = this;
        _this.removeAllListeners(point);
        _this.removeAllListeners(point.concat('**'));
    }
    , send: function (to, from, body, options) {
        var _this = this;
        if (!to || to.length < 1) {
            return;
        }
        return _this.emit(to, body, new MessageContext({
            domain: _this
            , to: to
            , from: from
            , body: body
            , options: options
        }));
    }
    , uid: uid
    , request: function (to, body, options) {
        var _this = this;
        return _this.get(to, body, options)
        .then(function (ctxt) {
            return [ctxt.body, ctxt.options, ctxt];
        });
    }
    , get: function (to, body, options) {
        var _this = this;
        var domain = _this;
        options = _.defaults({}, options, {
            timeout: 120
        });
        return uid()
            .then(function (requestid) {
                return new Promise(function (resolve) {
                    var from = [requestid + 'request'];
                    var timer;
                    var receiver;
                    if (options.timeout > 0) {
                        timer = setTimeout(function () {
                            domain.removeListener(from, receiver);
                            resolve(new MessageContext({
                                options: {
                                    statusCode: '408'
                                }
                            }));
                        }, 1000 * options.timeout);
                    }
                    receiver = function (ctxt) {
                        if (timer) {
                            clearTimeout(timer);
                        }
                        resolve(new MessageContext(ctxt));
                    };
                    domain.once(from, receiver);
                    return domain.send(to, from, body, options)
                        .then(function (called) {
                            if (!called) {
                                return resolve(new MessageContext({
                                    options: {
                                        statusCode: '503'
                                    }
                                }));
                            }
                        });
                });
            });
    }
    , open: function (mount, socket, firewall) {
        var _this = this;
        _this.mount(mount.concat('**'), function (ctxt) {
            return ctxt.transfer(mount, socket);
        });
        var transferToDomain;
        var openTransfer = function (ctxt) {
            return _this.send(ctxt.to, mount.concat(ctxt.from), ctxt.body, ctxt.options);
        };
        if (firewall) {
            transferToDomain = function (ctxt) {
                var to = _.clone(ctxt.to);
                var from = _.clone(ctxt.from);
                firewall(ctxt, function (ok, options) {
                    if (ok) {
                        openTransfer(_.extend(ctxt, {
                            to: to
                            , from: from
                            , options: options || {}
                        }));
                    }
                });
            };
        }
        else {
            transferToDomain = openTransfer;
        }
        socket.on('dual', transferToDomain);

        var onDisconnect = function () {
            _this.unmount(mount.concat('**'));
            socket.removeListener('dual', transferToDomain);
            socket.removeListener('disconnect', onDisconnect);
        };
        socket.on('disconnect', onDisconnect);
    }
    , bridge: function (remote, routes, fromRoutes) {
        var _this = this;
        _.each(routes, function (route) {
            _this.mount(route.concat('**'), function (ctxt) {
                remote.send(ctxt.to, ctxt.from, ctxt.body, ctxt.options);
            });
        });
        if (fromRoutes) {
            remote.bridge(_this, fromRoutes);
        }
    }
    , waitFor: function (route, options) {
        var _this = this;
        var domain = _this;
        options = _.defaults({}, options, {
            timeout: 0
        });
        return new Promise(function (resolve, reject) {
            var timer;
            var receiver = function (ctxt) {
                if (timer) {
                    clearTimeout(timer);
                }
                resolve(new MessageContext(ctxt));
            };
            domain.once(route, receiver);
            if (options.timeout > 0) {
                var timer = setTimeout(function () {
                    domain.removeListener(route, receiver);
                    reject(false);
                }, 1000 * options.timeout);
            }
        });
    }
});

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

_.extend(module.exports, {
    MessageContext: MessageContext
    , synchOption: function (name, fetch) {
        var cache = {};
        return function (ctxt, next) {
            var k = ctxt.params[name];
            if (cache.hasOwnProperty(k)) {
                ctxt.options[name] = cache[k];
                next();
            }
            else {
                return fetch(ctxt, function (err, val) {
                    if (!err) {
                        if (!cache.hasOwnProperty(k)) {
                            cache[k] = val;
                        }
                        else {
                            val = cache[k];
                        }
                        ctxt.options[name] = val;
                    }
                    next(err);
                });
            }
        };
    }
});

<commit_msg>Simplify params implementation.<commit_after>/*jslint node: true */
/* global -Promise */
"use strict";

var _ = require('lodash');
var HevEmitter = require('hevemitter').EventEmitter;
var inherits = require('util').inherits;
var Promise = require('bluebird');
var uid = require('./uid');

var MessageContext = function (options) {
    var _this = this;
    _.extend(_this, _.defaults(_.pick(options, 'domain', 'to', 'from', 'body', 'options')
                              , {
                                  to: []
                                  , from: []
                                  , options: {}
                              }));
};

_.extend(MessageContext.prototype, {
    send: function (to, from, body, options) {
        return this.domain.send(to, from, body, options);
    }
    , get: function (to, body, options) {
        var _this = this;
        return _this.domain.get(to, body, options);
    }
    , request: function (to, body, options) {
        return this.domain.request(to, body, options);
    }
    , proxy: function (to, options) {
        var _this = this;
        return _this.get(to, _this.body, _.extend({}, _this.options, options));
    }
    , reply: function (body, options) {
        options = _.defaults({}, options, { statusCode: '200' });
        var _this = this;
        return _this.send(_this.from, _this.to, body, options);
    }
    , replyPromise: function (p) {
        var _this = this;
        return Promise.resolve(p)
            .then(function (msg) {
                return _this.reply(msg.message || msg, { statusCode: msg.statusCode || '200' });
            })
            .catch(function (msg) {
                return _this.reply(msg.message || msg, { statusCode: msg.statusCode || '500' });
            });

    }
    , forward: function (to, options) {
        var _this = this;
        return _this.send(to, _this.from, _this.body, _.extend({}, _this.options, options));
    }
    , transfer: function (mount, socket, options) {
        var _this = this;
        socket.emit('dual', {
            to: _this.to.slice(mount.length)
            , from: _this.from
            , body: _this.body
            , options: _.extend({}, _this.options, options)
        });
    }
    , error: function (message) {
        var _this = this;
        _this.send(['error'].concat(_this.to), [], {
            message: message
            , ctxt: {
                to: _this.to
                , from: _this.from
                , body: _this.body
                , options: _this.options
            }
        });
    }
    , toJSON: function () {
        return _.pick(this, 'to', 'from', 'body', 'options');
    }
    , parent: function (n) {
        if (n !== 0) {
            n = n || 1;
        }
        var _this = this;
        if (n > _this.to.length) {
            throw new Error('Invalid parent slice ' + n + ' for point ' + _this.to.join('/'));
        }
        else {
            return _this.to.slice(0, _this.to.length - n);
        }
    }
});

var mountParametrized = function (domain, point, host) {
    var params = [];
    var tailparams = [];
    if (!(_.isArray(point) && point.length > 0)) {
        throw new Error('Unable to mount empty point');
    }
    point = _.map(point, function (name, index) {
        if (_.isString(name)
            && name[0] === ':') {
            if (name[1] === ':') {
                tailparams.push([name.slice(2), index]);
                return '**';
            }
            else {
                params.push([name.slice(1), index]);
                return '*';
            }
        }
        else {
            return name;
        }
    });
    var f = host;
    if (params.length !== 0
        || tailparams.length !== 0) {
        f = function (body, ctxt) {
            ctxt.params = {};
            _.each(params, function (param) {
                ctxt.params[param[0]] = ctxt.to[param[1]];
            });
            _.each(tailparams, function (tailparam) {
                ctxt.params[tailparam[0]] = ctxt.to.slice(tailparam[1]);
            });
            return host(body, ctxt);
        };
        f.listener = host;
    }
    domain.on(point, f);
};

var Domain = function (options) {
    var _this = this;
    _this.hosts = {};
    HevEmitter.call(_this);
    _this.options = options || {};
};

inherits(Domain, HevEmitter);

_.extend(Domain.prototype, {
    mount: function (point, host) {
        var _this = this;

        if (arguments.length < 2)
        {
            host = point;
            point = [];
        }

        if (_.isString(point)) {
            point = [point];
        }

        if (_.isFunction(host)) {
            mountParametrized(_this, point, host);
        }
        else if (_.isArray(host)) {
            _.each(host, function (f) {
                if (_.isFunction(f)) {
                    mountParametrized(_this, point, f);
                }
                else {
                    _this.mount(point, f);
                }
            });
        }
        else if (_.isObject(host)) {
            _.each(host, function (f, n) {
                if (_.isObject(f)) {
                    _this.mount(point.concat(n), f);
                }
                else {
                    mountParametrized(_this, point.concat(n), f);
                }
            });
        }
        return _this;
    }
    , unmount: function (point) {
        var _this = this;
        _this.removeAllListeners(point);
        _this.removeAllListeners(point.concat('**'));
    }
    , send: function (to, from, body, options) {
        var _this = this;
        if (!to || to.length < 1) {
            return;
        }
        return _this.emit(to, body, new MessageContext({
            domain: _this
            , to: to
            , from: from
            , body: body
            , options: options
        }));
    }
    , uid: uid
    , request: function (to, body, options) {
        var _this = this;
        return _this.get(to, body, options)
        .then(function (ctxt) {
            return [ctxt.body, ctxt.options, ctxt];
        });
    }
    , get: function (to, body, options) {
        var _this = this;
        var domain = _this;
        options = _.defaults({}, options, {
            timeout: 120
        });
        return uid()
            .then(function (requestid) {
                return new Promise(function (resolve) {
                    var from = [requestid + 'request'];
                    var timer;
                    var receiver;
                    if (options.timeout > 0) {
                        timer = setTimeout(function () {
                            domain.removeListener(from, receiver);
                            resolve(new MessageContext({
                                options: {
                                    statusCode: '408'
                                }
                            }));
                        }, 1000 * options.timeout);
                    }
                    receiver = function (ctxt) {
                        if (timer) {
                            clearTimeout(timer);
                        }
                        resolve(new MessageContext(ctxt));
                    };
                    domain.once(from, receiver);
                    return domain.send(to, from, body, options)
                        .then(function (called) {
                            if (!called) {
                                return resolve(new MessageContext({
                                    options: {
                                        statusCode: '503'
                                    }
                                }));
                            }
                        });
                });
            });
    }
    , open: function (mount, socket, firewall) {
        var _this = this;
        _this.mount(mount.concat('**'), function (ctxt) {
            return ctxt.transfer(mount, socket);
        });
        var transferToDomain;
        var openTransfer = function (ctxt) {
            return _this.send(ctxt.to, mount.concat(ctxt.from), ctxt.body, ctxt.options);
        };
        if (firewall) {
            transferToDomain = function (ctxt) {
                var to = _.clone(ctxt.to);
                var from = _.clone(ctxt.from);
                firewall(ctxt, function (ok, options) {
                    if (ok) {
                        openTransfer(_.extend(ctxt, {
                            to: to
                            , from: from
                            , options: options || {}
                        }));
                    }
                });
            };
        }
        else {
            transferToDomain = openTransfer;
        }
        socket.on('dual', transferToDomain);

        var onDisconnect = function () {
            _this.unmount(mount.concat('**'));
            socket.removeListener('dual', transferToDomain);
            socket.removeListener('disconnect', onDisconnect);
        };
        socket.on('disconnect', onDisconnect);
    }
    , bridge: function (remote, routes, fromRoutes) {
        var _this = this;
        _.each(routes, function (route) {
            _this.mount(route.concat('**'), function (ctxt) {
                remote.send(ctxt.to, ctxt.from, ctxt.body, ctxt.options);
            });
        });
        if (fromRoutes) {
            remote.bridge(_this, fromRoutes);
        }
    }
    , waitFor: function (route, options) {
        var _this = this;
        var domain = _this;
        options = _.defaults({}, options, {
            timeout: 0
        });
        return new Promise(function (resolve, reject) {
            var timer;
            var receiver = function (ctxt) {
                if (timer) {
                    clearTimeout(timer);
                }
                resolve(new MessageContext(ctxt));
            };
            domain.once(route, receiver);
            if (options.timeout > 0) {
                var timer = setTimeout(function () {
                    domain.removeListener(route, receiver);
                    reject(false);
                }, 1000 * options.timeout);
            }
        });
    }
});

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

_.extend(module.exports, {
    MessageContext: MessageContext
    , synchOption: function (name, fetch) {
        var cache = {};
        return function (ctxt, next) {
            var k = ctxt.params[name];
            if (cache.hasOwnProperty(k)) {
                ctxt.options[name] = cache[k];
                next();
            }
            else {
                return fetch(ctxt, function (err, val) {
                    if (!err) {
                        if (!cache.hasOwnProperty(k)) {
                            cache[k] = val;
                        }
                        else {
                            val = cache[k];
                        }
                        ctxt.options[name] = val;
                    }
                    next(err);
                });
            }
        };
    }
});

<|endoftext|>


<commit_before>import { Kinvey } from 'kinvey-javascript-sdk-core';
import { NetworkRack } from 'kinvey-javascript-sdk-core/build/rack/rack';
import { SerializeMiddleware } from 'kinvey-javascript-sdk-core/build/rack/middleware/serialize';
import { HttpMiddleware } from './http';
import { Push } from './push';

export class KinveyProvider {
  constructor() {
    // Use Http middleware after the Serialize middleware
    const networkRack = NetworkRack.sharedInstance();
    networkRack.useAfter(SerializeMiddleware, new HttpMiddleware());

    // Add Push module to Kinvey
    Kinvey.Push = Push;
  }

  init(options) {
    // Initialize Kinvey
    return Kinvey.init(options);
  }

  $get() {
    return Kinvey;
  }
}
<commit_msg>Add Push module during SDK init<commit_after>import { Kinvey } from 'kinvey-javascript-sdk-core';
import { NetworkRack } from 'kinvey-javascript-sdk-core/build/rack/rack';
import { SerializeMiddleware } from 'kinvey-javascript-sdk-core/build/rack/middleware/serialize';
import { HttpMiddleware } from './http';
import { Push } from './push';

export class KinveyProvider {
  constructor() {
    // Use Http middleware after the Serialize middleware
    const networkRack = NetworkRack.sharedInstance();
    networkRack.useAfter(SerializeMiddleware, new HttpMiddleware());
  }

  init(options) {
    // Initialize Kinvey
    const client = Kinvey.init(options);

    // Add Push module to Kinvey
    Kinvey.Push = new Push();

    // Return the client
    return client;
  }

  $get() {
    return Kinvey;
  }
}
<|endoftext|>


<commit_before>var rethinkdb = require( 'rethinkdb' ),
	Search = require( './search' ),
	DeepstreamClient = require( 'deepstream.io-client-js' ),
	EventEmitter = require( 'events' ).EventEmitter,
	util = require( 'util' );

var Provider = function( config ) {
	this.isReady = false;
	this._config = config;
	this._rethinkDbConnection = null;
	this._deepstreamClient = null;
	this._listName = config.listName || 'search';
	this._searches = {};

	this._initialiseDbConnection();
};

util.inherits( Provider, EventEmitter );

Provider.prototype._initialiseDbConnection = function() {
	this._log( 'Initialising RethinkDb Connection' );

	if( this._config.rethinkDbConnection ) {
		this._rethinkDbConnection = this._config.rethinkDbConnection;
		this._initialiseDeepstreamClient();
	} else {
		if( !this._config.rethinkdbConnectionParams ) {
			throw new Error( 'Can\'t connect to rethinkdb, neither connection nor connection parameters provided' );
		}

		rethinkdb.connect( this._config.rethinkdbConnectionParams, this._onRethinkdbConnection.bind( this ) );
	}
};

Provider.prototype._onRethinkdbConnection = function( error, connection ) {
	if( error ) {
		throw new Error( 'Error while connecting to RethinkDb: ' + error.toString() );
	} else {
		this._log( 'RethinkDb connection established' );
		this._rethinkDbConnection = connection;
		this._initialiseDeepstreamClient();
	}
};

Provider.prototype._initialiseDeepstreamClient = function() {
	this._log( 'Initialising Deepstream connection' );

	if( this._config.deepstreamClient ) {
		this._deepstreamClient = this._config.deepstreamClient;
		this._log( 'Deepstream connection established' );
		this._ready();
	} else {
		if( !this._config.deepstreamUrl ) {
			throw new Error( 'Can\'t connect to deepstream, neither deepstreamClient nor deepstreamUrl where provided' );
		}

		if( !this._config.deepstreamCredentials ) {
			throw new Error( 'Missing configuration parameter deepstreamCredentials' );
		}

		this._deepstreamClient = new DeepstreamClient( this._config.deepstreamUrl );
		this._deepstreamClient.login( this._config.deepstreamCredentials, this._onDeepstreamLogin.bind( this ) );
	}
};

Provider.prototype._onDeepstreamLogin = function( success, error, message ) {
	if( success ) {
		this._log( 'Connection to deepstream established' );
		this._ready();
	} else {
		this._log( 'Can\'t connect to deepstream: ' + message );
	}
};

Provider.prototype._onSubscription = function( name, subscribed ) {
	var parsedInput = this._parseInput( name ),
		query;

	// don't process invalid queries
	if( parsedInput === null ) {
		return;
	}

	query = this._createQuery( parsedInput );

	if( subscribed === true ) {
		if( !this._searches[ name ] ) {
			this._searches[ name ] = new Search( query, name, this._rethinkDbConnection, this._deepstreamClient );
		}

		this._searches[ name ].subscriptions++;
	} else {
		if( this._searches[ name ] ) {
			this._searches[ name ].subscriptions--;

			if( this._searches[ name ].subscriptions === 0 ) {
				this._searches[ name ].destroy();
				delete this._searches[ name ];
			}
		}
	}
};

/**
 * Parses the query string, queries are expected to
 * be send as JSON. The full name would look like this
 *
 * search?{ "table": "people", "query": [[ "name", "ma", "Wolf" ], [ "age", "gt", "25" ] ] }
 *
 * The structure is an array of filter conditions. Each filter condition
 * is expresses as [ "<field>", "<operator>", "value" ]
 *
 * Supported operators are
 *
 * "eq" (equals)
 * "match" (RegEx match)
 * "gt" (greater than)
 * "lt" (lesser than)
 * "ne" (not equal)
 *
 * @param   {String} name The recordName for the list, including search parameters
 *
 * @returns {Object} query
 */
Provider.prototype._createQuery = function( parsedInput ) {
	var row,
		condition,
		query = null,
		i;

	for( i = 0; i < parsedInput.query.length; i++ ) {
		condition = parsedInput.query[ i ];

		row = rethinkdb.row( '_d' )( condition[ 0 ] )[ condition[ 1 ] ]( condition[ 2 ] );

		if( query === null ) {
			query = row;
		} else {
			query.and( row );
		}
	}

	return { table: parsedInput.table, filter: query };
};

Provider.prototype._parseInput = function( input ) {

	var operators = [ 'eq', 'match', 'gt', 'lt', 'ne'],
		search,
		parsedInput,
		condition,
		i;

	if( input.indexOf( '?' ) === -1 ) {
		return this._queryError( input, 'Missing ?' );
	}

	search = input.split( '?' )[ 1 ];

	try{
		parsedInput = JSON.parse( search );
	} catch( e ) {
		return this._queryError( input, 'Invalid JSON' );
	}

	if( !parsedInput.table ) {
		return this._queryError( input, 'Missing parameter "table"' );
	}

	if( !parsedInput.query ) {
		return this._queryError( input, 'Missing parameter "query"' );
	}

	for( i = 0; i < parsedInput.query.length; i++ ) {
		condition = parsedInput.query[ i ];

		if( condition.length !== 3 ) {
			return this._queryError( input, 'Too few parameters' );
		}

		if( operators.indexOf( condition[ 1 ] ) === -1 ) {
			return this._queryError( input, 'Unknown operator ' + condition[ 1 ] );
		}
	}

	return parsedInput;
};

Provider.prototype._queryError = function( name, error ) {
	this._log( name );
	this._log( 'QUERY ERROR | ' + error );
	return null;
};

Provider.prototype._ready = function() {
	this._deepstreamClient.record.listen( this._listName + '\\?*', this._onSubscription.bind( this ) );
	this._log( 'rethinkdb search provider ready' );
	this.isReady = true;
	this.emit( 'ready' );
};

Provider.prototype._log = function( message ) {
	var date = new Date(),
		time = date.toLocaleTimeString() + ':' + date.getMilliseconds();

	console.log( time + ' | ' + message );
};

module.exports = Provider;<commit_msg>Improved regExp and added logging<commit_after>var rethinkdb = require( 'rethinkdb' ),
	Search = require( './search' ),
	DeepstreamClient = require( 'deepstream.io-client-js' ),
	EventEmitter = require( 'events' ).EventEmitter,
	util = require( 'util' );

var Provider = function( config ) {
	this.isReady = false;
	this._config = config;
	this._rethinkDbConnection = null;
	this._deepstreamClient = null;
	this._listName = config.listName || 'search';
	this._searches = {};
};

util.inherits( Provider, EventEmitter );

Provider.prototype.start = function() {
	this._initialiseDbConnection();
};

Provider.prototype.stop = function() {
	this._deepstreamClient.close();
	this._rethinkDbConnection.close();
};

Provider.prototype._initialiseDbConnection = function() {
	this._log( 'Initialising RethinkDb Connection' );

	if( this._config.rethinkDbConnection ) {
		this._rethinkDbConnection = this._config.rethinkDbConnection;
		this._initialiseDeepstreamClient();
	} else {
		if( !this._config.rethinkdbConnectionParams ) {
			throw new Error( 'Can\'t connect to rethinkdb, neither connection nor connection parameters provided' );
		}

		rethinkdb.connect( this._config.rethinkdbConnectionParams, this._onRethinkdbConnection.bind( this ) );
	}
};

Provider.prototype._onRethinkdbConnection = function( error, connection ) {
	if( error ) {
		throw new Error( 'Error while connecting to RethinkDb: ' + error.toString() );
	} else {
		this._log( 'RethinkDb connection established' );
		this._rethinkDbConnection = connection;
		this._initialiseDeepstreamClient();
	}
};

Provider.prototype._initialiseDeepstreamClient = function() {
	this._log( 'Initialising Deepstream connection' );

	if( this._config.deepstreamClient ) {
		this._deepstreamClient = this._config.deepstreamClient;
		this._log( 'Deepstream connection established' );
		this._ready();
	} else {
		if( !this._config.deepstreamUrl ) {
			throw new Error( 'Can\'t connect to deepstream, neither deepstreamClient nor deepstreamUrl where provided' );
		}

		if( !this._config.deepstreamCredentials ) {
			throw new Error( 'Missing configuration parameter deepstreamCredentials' );
		}

		this._deepstreamClient = new DeepstreamClient( this._config.deepstreamUrl );
		this._deepstreamClient.login( this._config.deepstreamCredentials, this._onDeepstreamLogin.bind( this ) );
	}
};

Provider.prototype._onDeepstreamLogin = function( success, error, message ) {
	if( success ) {
		this._log( 'Connection to deepstream established' );
		this._ready();
	} else {
		this._log( 'Can\'t connect to deepstream: ' + message );
	}
};

Provider.prototype._onSubscription = function( name, subscribed ) {
	this._log( 'received subscription for ' + name );

	var parsedInput = this._parseInput( name ),
		query;

	// don't process invalid queries
	if( parsedInput === null ) {
		return;
	}

	query = this._createQuery( parsedInput );

	if( subscribed === true ) {
		if( !this._searches[ name ] ) {
			this._searches[ name ] = new Search( query, name, this._rethinkDbConnection, this._deepstreamClient );
		}

		this._searches[ name ].subscriptions++;
	} else {
		if( this._searches[ name ] ) {
			this._searches[ name ].subscriptions--;

			if( this._searches[ name ].subscriptions === 0 ) {
				this._searches[ name ].destroy();
				delete this._searches[ name ];
			}
		}
	}
};

/**
 * Parses the query string, queries are expected to
 * be send as JSON. The full name would look like this
 *
 * search?{ "table": "people", "query": [[ "name", "ma", "Wolf" ], [ "age", "gt", "25" ] ] }
 *
 * The structure is an array of filter conditions. Each filter condition
 * is expresses as [ "<field>", "<operator>", "value" ]
 *
 * Supported operators are
 *
 * "eq" (equals)
 * "match" (RegEx match)
 * "gt" (greater than)
 * "lt" (lesser than)
 * "ne" (not equal)
 *
 * @param   {String} name The recordName for the list, including search parameters
 *
 * @returns {Object} query
 */
Provider.prototype._createQuery = function( parsedInput ) {
	var row,
		condition,
		query = null,
		i;

	for( i = 0; i < parsedInput.query.length; i++ ) {
		condition = parsedInput.query[ i ];

		row = rethinkdb.row( '_d' )( condition[ 0 ] )[ condition[ 1 ] ]( condition[ 2 ] );

		if( query === null ) {
			query = row;
		} else {
			query.and( row );
		}
	}

	return { table: parsedInput.table, filter: query };
};

Provider.prototype._parseInput = function( input ) {

	var operators = [ 'eq', 'match', 'gt', 'lt', 'ne'],
		search,
		parsedInput,
		condition,
		i;

	if( input.indexOf( '?' ) === -1 ) {
		return this._queryError( input, 'Missing ?' );
	}

	search = input.split( '?' )[ 1 ];

	try{
		parsedInput = JSON.parse( search );
	} catch( e ) {
		return this._queryError( input, 'Invalid JSON' );
	}

	if( !parsedInput.table ) {
		return this._queryError( input, 'Missing parameter "table"' );
	}

	if( !parsedInput.query ) {
		return this._queryError( input, 'Missing parameter "query"' );
	}

	for( i = 0; i < parsedInput.query.length; i++ ) {
		condition = parsedInput.query[ i ];

		if( condition.length !== 3 ) {
			return this._queryError( input, 'Too few parameters' );
		}

		if( operators.indexOf( condition[ 1 ] ) === -1 ) {
			return this._queryError( input, 'Unknown operator ' + condition[ 1 ] );
		}
	}

	return parsedInput;
};

Provider.prototype._queryError = function( name, error ) {
	this._log( name );
	this._log( 'QUERY ERROR | ' + error );
	return null;
};

Provider.prototype._ready = function() {
	var pattern = this._listName + '[\\?].*';
	this._log( 'listening for ' + pattern );
	this._deepstreamClient.record.listen( pattern, this._onSubscription.bind( this ) );
	this._log( 'rethinkdb search provider ready' );
	this.isReady = true;
	this.emit( 'ready' );
};

Provider.prototype._log = function( message ) {
	var date = new Date(),
		time = date.toLocaleTimeString() + ':' + date.getMilliseconds();

	console.log( time + ' | ' + message );
};

module.exports = Provider;<|endoftext|>


<commit_before>  var request = require('request');
  var path = require('path');
  var os = require('os');
  var fs = require('fs');
  var exec = require('child_process').exec;
  var execFile = require('child_process').execFile;
  var spawn = require('child_process').spawn;
  var ncp = require('ncp');

  var platform = process.platform;
  platform = /^win/.test(platform)? 'win' : /^darwin/.test(platform)? 'mac' : 'linux' + (process.arch == 'ia32' ? '32' : '64');

  /**
   * Creates new instance of updater. Manifest could be a `package.json` of project.
   *
   * Note that compressed apps are assumed to be downloaded in the format produced by [node-webkit-builder](https://github.com/mllrsohn/node-webkit-builder) (or [grunt-node-webkit-builder](https://github.com/mllrsohn/grunt-node-webkit-builder)).
   *
   * @constructor
   * @param {object} manifest - See the [manifest schema](#manifest-schema) below.
   */
  function updater(manifest){
    this.manifest = manifest;
  }

  /**
   * Will check the latest available version of the application by requesting the manifest specified in `manufestUrl`.
   * The callback will be executed if the version was changed.
   * @param {function} cb - Callback arguments: error, remote version
   */
  updater.prototype.checkNewVersion = function(cb){
    request.get(this.manifest.manifestUrl, gotManifest.bind(this)); //get manifest from url

    /**
     * @private
     */
    function gotManifest(err, req, data){
      if(err) {
        return cb(err);
      }

      if(req.statusCode < 200 || req.statusCode > 299){
        return cb(new Error(req.statusCode));
      }

      try{
        data = JSON.parse(data);
      } catch(e){
        return cb(e)
      }
      if(data.version !== this.manifest.version){
        cb(null, data);
      }
    }
  };

  /**
   * Downloads the new app to a template folder
   * @param  {Function} cb - called when download completes. Callback arguments: error, downloaded filepath
   * @param  {Object} newManifest - see [manifest schema](#manifest-schema) below
   * @return {Request} Request - stream, the stream contains `manifest` property with new manifest
   */
  updater.prototype.download = function(cb, newManifest){
    var manifest = newManifest || this.manifest;
    var url = manifest.packages[platform].url;
    var pkg = request(url, function(err, response){
        if(err){
            cb(err);
        }

        if(response.statusCode < 200 || response.statusCode > 299){
            return cb(new Error(response.statusCode));
        }
    });
    var filename = path.basename(url),
        destinationPath = path.join(os.tmpdir(), filename);
    // download the package to template folder
    //fs.unlink(path.join(os.tmpdir(), filename), function(){
      pkg.pipe(fs.createWriteStream(destinationPath));
    //});

    pkg.on('error', cb);
    pkg.on('end', appDownloaded);

    function appDownloaded(){
      process.nextTick(function(){
        cb(null, destinationPath)
      });
    }
    return pkg;
  };

  /**
   * Returns executed application path
   * @returns {string}
   */
  updater.prototype.getAppPath = function(){
    var appPath = {
      mac: path.join(process.cwd(),'../../..'),
      win: path.dirname(process.execPath)
    };
    appPath.linux32 = appPath.win;
    appPath.linux64 = appPath.win;
    return appPath[platform];
  };

  /**
   * Returns current application executable
   * @returns {string}
   */
  updater.prototype.getAppExec = function(){
    var execFolder = this.getAppPath();
    var exec = {
      mac: '',
      win: path.basename(process.execPath),
      linux32: path.basename(process.execPath),
      linux64: path.basename(process.execPath)
    };
    return path.join(execFolder, exec[platform]);
  };

  /**
   * Will unpack the `filename` in temporary folder.
   * For Windows, [unzip](https://www.mkssoftware.com/docs/man1/unzip.1.asp) is used.
   *
   * @param {string} filename
   * @param {function} cb - Callback arguments: error, unpacked directory
   * @param {object} manifest
   */
  updater.prototype.unpack = function(filename, cb, manifest){
    pUnpack[platform].apply(this, arguments);
  };

  /**
   * @private
   * @param {string} zipPath
   * @return {string}
   */
  var getZipDestinationDirectory = function(zipPath){
      return path.join(os.tmpdir(), path.basename(zipPath, path.extname(zipPath)));
    },
    /**
     * @private
     * @param {object} manifest
     * @return {string}
     */
    getExecPathRelativeToPackage = function(manifest){
      var execPath = manifest.packages[platform] && manifest.packages[platform].execPath;

      if(execPath){
        return execPath;
      }
      else {
        var suffix = {
          win: '.exe',
          mac: '.app'
        };
        return manifest.name + (suffix[platform] || '');
      }
    };

  var pUnpack = {
    /**
     * @private
     */
    mac: function(filename, cb, manifest){
      var args = arguments,
          extension = path.extname(filename);

      if(extension === ".zip"){
        exec('unzip -xo ' + filename,{cwd: os.tmpdir()}, function(err){
          if(err){
            console.log(err);
            return cb(err);
          }
          var appPath = path.join(os.tmpdir(), getExecPathRelativeToPackage(manifest));
          cb(null, appPath);
        })

      }
      else if(extension === ".dmg"){
        // just in case if something was wrong during previous mount
        exec('hdiutil unmount /Volumes/'+path.basename(filename, '.dmg'), function(err){
          exec('hdiutil attach ' + filename + ' -nobrowse', function(err){
            if(err) {
              if(err.code == 1){
                pUnpack.mac.apply(this, args);
              }
              return cb(err);
            }
            findMountPoint(path.basename(filename, '.dmg'), cb);
          });
        });

        function findMountPoint(dmg_name, callback) {
          exec('hdiutil info', function(err, stdout){
            if (err) return callback(err);
            var results = stdout.split("\n");
            var dmgExp = new RegExp(dmg_name + '$');
            for (var i=0,l=results.length;i<l;i++) {
              if (results[i].match(dmgExp)) {
                var mountPoint = results[i].split("\t").pop();
                var fileToRun = path.join(mountPoint, dmg_name + ".app");
                return callback(null, fileToRun);
              }
            }
            callback(Error("Mount point not found"));
          })
        }
      }
    },
    /**
     * @private
     */
    win: function(filename, cb, manifest){
      var destinationDirectory = getZipDestinationDirectory(filename);

      // unzip by C. Spieler (docs: https://www.mkssoftware.com/docs/man1/unzip.1.asp, issues: http://www.info-zip.org/)
      exec(path.resolve(__dirname, 'tools/unzip.exe') + " -u -o " +
        filename + " -d " + destinationDirectory, function(err){
          if(err){
            return cb(err);
          }

          cb(null, path.join(destinationDirectory, getExecPathRelativeToPackage(manifest)));
        });
    },
    /**
     * @private
     */
    linux32: function(filename, cb, manifest){
      //filename fix
      console.log('starting');
      exec('tar -zxvf ' + filename,{cwd: os.tmpdir()}, function(err){
        console.log(arguments);
        if(err){
          console.log(err);
          return cb(err);
        }
        cb(null,path.join(os.tmpdir(), getExecPathRelativeToPackage(manifest)));
      })
     }
  };
  pUnpack.linux64 = pUnpack.linux32;

  /**
   * Runs installer
   * @param {string} appPath
   * @param {array} args - Arguments which will be passed when running the new app
   * @param {object} options - Optional
   * @returns {function}
   */
  updater.prototype.runInstaller = function(appPath, args, options){
    return pRun[platform].apply(this, arguments);
  };

  var pRun = {
    /**
     * @private
     */
    mac: function(appPath, args, options){
      //spawn
      if(args && args.length) {
        args = [appPath].concat('--args', args);
      } else {
        args = [appPath];
      }
      return run('open', args, options);
    },
    /**
     * @private
     */
    win: function(appPath, args, options, cb){
      return run(appPath, args, options, cb);
    },
    /**
     * @private
     */
    linux32: function(appPath, args, options, cb){
      fs.chmodSync(appPath, 0755);
      if(!options) options = {};
      options.cwd = path.dirname(appPath);
      return run(appPath, args, options, cb);
    }
  };

  pRun.linux64 = pRun.linux32;

  /**
   * @private
   */
  function run(path, args, options){
    var opts = {
      detached: true
    };
    for(var key in options){
      opts[key] = options[key];
    }
    var sp = spawn(path, args, opts);
    sp.unref();
    return sp;
  }

  /**
   * Installs the app (copies current application to `copyPath`)
   * @param {string} copyPath
   * @param {function} cb - Callback arguments: error
   */
  updater.prototype.install = function(copyPath, cb){
    pInstall[platform].apply(this, arguments);
  };

  var pInstall = {
    /**
     * @private
     */
    mac: function(to, cb){
      ncp(this.getAppPath(), to, cb);
    },
    /**
     * @private
     */
    win: function(to, cb){
      deleteApp(appDeleted.bind(this));
      function appDeleted(err){
        ncp(this.getAppPath(), to, appCopied.bind(this));
      }
      function deleteApp(cb){
        exec('rd ' + to + '/s /q', cb)
      }
      function appCopied(err){
        if(err){
          setTimeout(function(){deleteApp(appDeleted.bind(this))}.bind(this), 100);
          return
        }
        cb();
      }
    },
    /**
     * @private
     */
    linux32: function(to, cb){
      ncp(this.getAppPath(), to, cb);
    }
  };
  pInstall.linux64 = pInstall.linux32;

  /**
   * Runs the app from original path.
   * @param {string} execPath
   * @param {array} args - Arguments based to the app being ran
   * @param {object} options - Optional
   */
  updater.prototype.run = function(execPath, args, options){
    pRun[platform].apply(this, arguments);
  };

  module.exports = updater;<commit_msg>Custom app names; unpack dest is cleaned on Windows<commit_after>  var request = require('request');
  var path = require('path');
  var os = require('os');
  var fs = require('fs');
  var exec = require('child_process').exec;
  var execFile = require('child_process').execFile;
  var spawn = require('child_process').spawn;
  var ncp = require('ncp');

  var platform = process.platform;
  platform = /^win/.test(platform)? 'win' : /^darwin/.test(platform)? 'mac' : 'linux' + (process.arch == 'ia32' ? '32' : '64');

  /**
   * Creates new instance of updater. Manifest could be a `package.json` of project.
   *
   * Note that compressed apps are assumed to be downloaded in the format produced by [node-webkit-builder](https://github.com/mllrsohn/node-webkit-builder) (or [grunt-node-webkit-builder](https://github.com/mllrsohn/grunt-node-webkit-builder)).
   *
   * @constructor
   * @param {object} manifest - See the [manifest schema](#manifest-schema) below.
   */
  function updater(manifest){
    this.manifest = manifest;
  }

  /**
   * Will check the latest available version of the application by requesting the manifest specified in `manufestUrl`.
   * The callback will be executed if the version was changed.
   * @param {function} cb - Callback arguments: error, remote version
   */
  updater.prototype.checkNewVersion = function(cb){
    request.get(this.manifest.manifestUrl, gotManifest.bind(this)); //get manifest from url

    /**
     * @private
     */
    function gotManifest(err, req, data){
      if(err) {
        return cb(err);
      }

      if(req.statusCode < 200 || req.statusCode > 299){
        return cb(new Error(req.statusCode));
      }

      try{
        data = JSON.parse(data);
      } catch(e){
        return cb(e)
      }
      if(data.version !== this.manifest.version){
        cb(null, data);
      }
    }
  };

  /**
   * Downloads the new app to a template folder
   * @param  {Function} cb - called when download completes. Callback arguments: error, downloaded filepath
   * @param  {Object} newManifest - see [manifest schema](#manifest-schema) below
   * @return {Request} Request - stream, the stream contains `manifest` property with new manifest
   */
  updater.prototype.download = function(cb, newManifest){
    var manifest = newManifest || this.manifest;
    var url = manifest.packages[platform].url;
    var pkg = request(url, function(err, response){
        if(err){
            cb(err);
        }

        if(response.statusCode < 200 || response.statusCode > 299){
            return cb(new Error(response.statusCode));
        }
    });
    var filename = path.basename(url),
        destinationPath = path.join(os.tmpdir(), filename);
    // download the package to template folder
    //fs.unlink(path.join(os.tmpdir(), filename), function(){
      pkg.pipe(fs.createWriteStream(destinationPath));
    //});

    pkg.on('error', cb);
    pkg.on('end', appDownloaded);

    function appDownloaded(){
      process.nextTick(function(){
        cb(null, destinationPath)
      });
    }
    return pkg;
  };

  /**
   * Returns executed application path
   * @returns {string}
   */
  updater.prototype.getAppPath = function(){
    var appPath = {
      mac: path.join(process.cwd(),'../../..'),
      win: path.dirname(process.execPath)
    };
    appPath.linux32 = appPath.win;
    appPath.linux64 = appPath.win;
    return appPath[platform];
  };

  /**
   * Returns current application executable
   * @returns {string}
   */
  updater.prototype.getAppExec = function(){
    var execFolder = this.getAppPath();
    var exec = {
      mac: '',
      win: path.basename(process.execPath),
      linux32: path.basename(process.execPath),
      linux64: path.basename(process.execPath)
    };
    return path.join(execFolder, exec[platform]);
  };

  /**
   * Will unpack the `filename` in temporary folder.
   * For Windows, [unzip](https://www.mkssoftware.com/docs/man1/unzip.1.asp) is used.
   *
   * @param {string} filename
   * @param {function} cb - Callback arguments: error, unpacked directory
   * @param {object} manifest
   */
  updater.prototype.unpack = function(filename, cb, manifest){
    pUnpack[platform].apply(this, arguments);
  };

  /**
   * @private
   * @param {string} zipPath
   * @return {string}
   */
  var getZipDestinationDirectory = function(zipPath){
      return path.join(os.tmpdir(), path.basename(zipPath, path.extname(zipPath)));
    },
    /**
     * @private
     * @param {object} manifest
     * @return {string}
     */
    getExecPathRelativeToPackage = function(manifest){
      var execPath = manifest.packages[platform] && manifest.packages[platform].execPath;

      if(execPath){
        return execPath;
      }
      else {
        var suffix = {
          win: '.exe',
          mac: '.app'
        };
        return manifest.name + (suffix[platform] || '');
      }
    };

  var pUnpack = {
    /**
     * @private
     */
    mac: function(filename, cb, manifest){
      var args = arguments,
          extension = path.extname(filename);

      if(extension === ".zip"){
        exec('unzip -xo ' + filename,{cwd: os.tmpdir()}, function(err){
          if(err){
            console.log(err);
            return cb(err);
          }
          var appPath = path.join(os.tmpdir(), getExecPathRelativeToPackage(manifest));
          cb(null, appPath);
        })

      }
      else if(extension === ".dmg"){
        // just in case if something was wrong during previous mount
        exec('hdiutil unmount /Volumes/'+path.basename(filename, '.dmg'), function(err){
          exec('hdiutil attach ' + filename + ' -nobrowse', function(err){
            if(err) {
              if(err.code == 1){
                pUnpack.mac.apply(this, args);
              }
              return cb(err);
            }
            findMountPoint(path.basename(filename, '.dmg'), cb);
          });
        });

        function findMountPoint(dmg_name, callback) {
          exec('hdiutil info', function(err, stdout){
            if (err) return callback(err);
            var results = stdout.split("\n");
            var dmgExp = new RegExp(dmg_name + '$');
            for (var i=0,l=results.length;i<l;i++) {
              if (results[i].match(dmgExp)) {
                var mountPoint = results[i].split("\t").pop();
                var fileToRun = path.join(mountPoint, dmg_name + ".app");
                return callback(null, fileToRun);
              }
            }
            callback(Error("Mount point not found"));
          })
        }
      }
    },
    /**
     * @private
     */
    win: function(filename, cb, manifest){
      var destinationDirectory = getZipDestinationDirectory(filename);

      fs.unlink(destinationDirectory, function(err){
        if(err){
          cb(err);
        }
        else {
          // unzip by C. Spieler (docs: https://www.mkssoftware.com/docs/man1/unzip.1.asp, issues: http://www.info-zip.org/)
          exec(path.resolve(__dirname, 'tools/unzip.exe') + " -u -o " +
              filename + " -d " + destinationDirectory, function(err){
            if(err){
              return cb(err);
            }

            cb(null, path.join(destinationDirectory, getExecPathRelativeToPackage(manifest)));
          });
        }
      });
    },
    /**
     * @private
     */
    linux32: function(filename, cb, manifest){
      //filename fix
      console.log('starting');
      exec('tar -zxvf ' + filename,{cwd: os.tmpdir()}, function(err){
        console.log(arguments);
        if(err){
          console.log(err);
          return cb(err);
        }
        cb(null,path.join(os.tmpdir(), getExecPathRelativeToPackage(manifest)));
      })
     }
  };
  pUnpack.linux64 = pUnpack.linux32;

  /**
   * Runs installer
   * @param {string} appPath
   * @param {array} args - Arguments which will be passed when running the new app
   * @param {object} options - Optional
   * @returns {function}
   */
  updater.prototype.runInstaller = function(appPath, args, options){
    return pRun[platform].apply(this, arguments);
  };

  var pRun = {
    /**
     * @private
     */
    mac: function(appPath, args, options){
      //spawn
      if(args && args.length) {
        args = [appPath].concat('--args', args);
      } else {
        args = [appPath];
      }
      return run('open', args, options);
    },
    /**
     * @private
     */
    win: function(appPath, args, options, cb){
      return run(appPath, args, options, cb);
    },
    /**
     * @private
     */
    linux32: function(appPath, args, options, cb){
      fs.chmodSync(appPath, 0755);
      if(!options) options = {};
      options.cwd = path.dirname(appPath);
      return run(appPath, args, options, cb);
    }
  };

  pRun.linux64 = pRun.linux32;

  /**
   * @private
   */
  function run(path, args, options){
    var opts = {
      detached: true
    };
    for(var key in options){
      opts[key] = options[key];
    }
    var sp = spawn(path, args, opts);
    sp.unref();
    return sp;
  }

  /**
   * Installs the app (copies current application to `copyPath`)
   * @param {string} copyPath
   * @param {function} cb - Callback arguments: error
   */
  updater.prototype.install = function(copyPath, cb){
    pInstall[platform].apply(this, arguments);
  };

  var pInstall = {
    /**
     * @private
     */
    mac: function(to, cb){
      ncp(this.getAppPath(), to, cb);
    },
    /**
     * @private
     */
    win: function(to, cb){
      deleteApp(appDeleted.bind(this));
      function appDeleted(err){
        ncp(this.getAppPath(), to, appCopied.bind(this));
      }
      function deleteApp(cb){
        exec('rd ' + to + '/s /q', cb)
      }
      function appCopied(err){
        if(err){
          setTimeout(function(){deleteApp(appDeleted.bind(this))}.bind(this), 100);
          return
        }
        cb();
      }
    },
    /**
     * @private
     */
    linux32: function(to, cb){
      ncp(this.getAppPath(), to, cb);
    }
  };
  pInstall.linux64 = pInstall.linux32;

  /**
   * Runs the app from original path.
   * @param {string} execPath
   * @param {array} args - Arguments based to the app being ran
   * @param {object} options - Optional
   */
  updater.prototype.run = function(execPath, args, options){
    pRun[platform].apply(this, arguments);
  };

  module.exports = updater;<|endoftext|>


<commit_before>
'use strict';

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

var supertest = require('supertest');
var expect = require('thehelp-test').expect;
var util = require('./util');

describe('thehelp-cluster', function() {
  var agent, child;

  before(function(done) {
    agent = supertest.agent('http://localhost:3000');

    util.emptyDir(util.logsDir, function(err) {
      if (err) {
        throw err;
      }

      child = util.startProcess(path.join(__dirname, '../../../test/start_cluster.js'));
      setTimeout(done, 1000);
    });
  });

  after(function(done) {
    child.on('close', function() {
      done();
    });

    child.kill();
  });

  it('creates two log files on startup', function(done) {
    fs.readdir(util.logsDir, function(err, files) {
      if (err) {
        throw err;
      }

      expect(files).to.have.length(2);

      done();
    });
  });

  it('root returns', function(done) {
    agent
      .get('/')
      .expect('X-Worker', '1')
      .expect(200, done);
  });

  it('on async error, gets response with \'close connection\' header', function(done) {
    agent
      .get('/error')
      .expect('Connection', 'Connection: close')
      .expect('Content-Type', /text\/plain/)
      .expect('X-Worker', '1')
      .expect(/^error\!/)
      .expect(500, done);
  });

  it('starts up another node', function(done) {
    this.timeout(5000);

    agent
      .get('/')
      .expect('X-Worker', '2')
      .expect(200, done);
  });

  it('three log files now in directory', function(done) {
    fs.readdir(util.logsDir, function(err, files) {
      if (err) {
        throw err;
      }

      expect(files).to.have.length(3);

      done();
    });
  });

  it('async error only takes down process after long task is complete', function(done) {
    this.timeout(5000);

    var delayComplete = false;

    agent
      .get('/delay')
      .expect('X-Worker', '2')
      .expect(200, function(err) {
        if (err) {
          throw err;
        }

        delayComplete = true;
      });

    agent
      .get('/error')
      .expect('Connection', 'Connection: close')
      .expect('X-Worker', '2')
      .expect(500, function(err) {
        if (err) {
          throw err;
        }

        expect(delayComplete).to.equal(false);

        // this request should hang until the next process comes up
        agent
          .get('/')
          .expect('X-Worker', '3')
          .expect(200, function(err) {
            if (err) {
              throw err;
            }

            expect(delayComplete).to.equal(true);

            done();
          });
      });
  });

  it('four total log files', function(done) {
    fs.readdir(util.logsDir, function(err, files) {
      if (err) {
        throw err;
      }

      expect(files).to.have.length(4);

      done();
    });
  });

});

<commit_msg>integration test: Validate log files more closely<commit_after>
'use strict';

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

var supertest = require('supertest');
var expect = require('thehelp-test').expect;
var util = require('./util');

describe('thehelp-cluster', function() {
  var agent, child, logFiles;

  before(function(done) {
    agent = supertest.agent('http://localhost:3000');

    util.emptyDir(util.logsDir, function(err) {
      if (err) {
        throw err;
      }

      child = util.startProcess(path.join(__dirname, '../../../test/start_cluster.js'));
      setTimeout(done, 1000);
    });
  });

  after(function(done) {
    child.on('close', function() {
      done();
    });

    child.kill();
  });

  it('creates two log files on startup', function(done) {
    fs.readdir(util.logsDir, function(err, files) {
      if (err) {
        throw err;
      }

      expect(files).to.have.length(2);

      files = files.sort();
      expect(files).to.have.deep.property('0').that.match(/master/);
      expect(files).to.have.deep.property('1').that.match(/worker/);

      logFiles = files;

      done();
    });
  });

  it('root returns', function(done) {
    agent
      .get('/')
      .expect('X-Worker', '1')
      .expect(200, done);
  });

  it('on async error, gets response with \'close connection\' header', function(done) {
    agent
      .get('/error')
      .expect('Connection', 'Connection: close')
      .expect('Content-Type', /text\/plain/)
      .expect('X-Worker', '1')
      .expect(/^error\!/)
      .expect(500, done);
  });

  it('starts up another node', function(done) {
    this.timeout(5000);

    agent
      .get('/')
      .expect('X-Worker', '2')
      .expect(200, done);
  });

  it('three log files now in directory', function(done) {
    fs.readdir(util.logsDir, function(err, files) {
      if (err) {
        throw err;
      }

      expect(files).to.have.length(3);

      files = files.sort();
      expect(files).to.have.deep.property('0', logFiles[0]);
      expect(files).to.have.deep.property('1', logFiles[1]);
      expect(files).to.have.deep.property('2').that.match(/worker/);

      logFiles = files;

      done();
    });
  });

  it('async error only takes down process after long task is complete', function(done) {
    this.timeout(5000);

    var delayComplete = false;

    agent
      .get('/delay')
      .expect('X-Worker', '2')
      .expect(200, function(err) {
        if (err) {
          throw err;
        }

        delayComplete = true;
      });

    agent
      .get('/error')
      .expect('Connection', 'Connection: close')
      .expect('X-Worker', '2')
      .expect(500, function(err) {
        if (err) {
          throw err;
        }

        expect(delayComplete).to.equal(false);

        // this request should hang until the next process comes up
        agent
          .get('/')
          .expect('X-Worker', '3')
          .expect(200, function(err) {
            if (err) {
              throw err;
            }

            expect(delayComplete).to.equal(true);

            done();
          });
      });
  });

  it('four total log files', function(done) {
    fs.readdir(util.logsDir, function(err, files) {
      if (err) {
        throw err;
      }

      expect(files).to.have.length(4);

      files = files.sort();
      expect(files).to.have.deep.property('0', logFiles[0]);
      expect(files).to.have.deep.property('1', logFiles[1]);
      expect(files).to.have.deep.property('2', logFiles[2]);
      expect(files).to.have.deep.property('3').that.match(/worker/);

      done();
    });
  });

});

<|endoftext|>


<commit_before>var mbaasApi = require('fh-mbaas-api');
var express = require('express');
var mbaasExpress = mbaasApi.mbaasExpress();
var cors = require('cors');
var mediator = require('fh-wfm-mediator/lib/mediator');
var bodyParser = require('body-parser');
var raincatcherUser = require('fh-wfm-user/lib/router/mbaas');

// list the endpoints which you want to make securable here
var securableEndpoints;
securableEndpoints = ['/hello'];

var app = express();

// Enable CORS for all requests
app.use(cors());

// Note: the order which we add middleware to Express here is important!
app.use('/sys', mbaasExpress.sys(securableEndpoints));
app.use('/mbaas', mbaasExpress.mbaas);

// allow serving of static files from the public directory
app.use(express.static(__dirname + '/public'));

// Note: important that this is added just before your own Routes
app.use(mbaasExpress.fhmiddleware());

app.use('/hello', require('./lib/hello.js')());
app.use('/api', bodyParser.json({limit: '10mb'}));

// Session and Cookie configuration
// This is being consumed in the raincatcher-user mbaas router.
var sessionOptions = {
  store: 'mongo',
  config: {
    secret: process.env.FH_COOKIE_SECRET || 'raincatcher',
    host: '127.0.0.1',
    port: '27017',
    db: 'session',
    url: 'mongodb://localhost:27017/raincatcher-demo-auth-session-store',
    resave: false,
    saveUninitialized: true,
    cookie: {
      secure: process.env.NODE_ENV !== 'development',
      httpOnly: true,
      path: '/'
    }
  }
};

// List the user fields which you don't want appearing in the authentication response.
// This is being consumed in the raincatcher-user mbaas router.
var authResponseExclusionList = ['password'];
raincatcherUser.init(mediator, app, authResponseExclusionList, sessionOptions, function(err) {
  if (err) {
    return console.error(err);
  }
  require('./lib/user')(mediator);

  // Important that this is last!
  app.use(mbaasExpress.errorHandler());

  var port = process.env.FH_PORT || process.env.OPENSHIFT_NODEJS_PORT || 8001;
  var host = process.env.OPENSHIFT_NODEJS_IP || '0.0.0.0';
  app.listen(port, host, function() {
    console.log("App started at: " + new Date() + " on port: " + port);
  });
});
<commit_msg>Get connection string from $fh.db<commit_after>var $fh = require('fh-mbaas-api');
var express = require('express');
var mbaasExpress = $fh.mbaasExpress();
var cors = require('cors');
var mediator = require('fh-wfm-mediator/lib/mediator');
var bodyParser = require('body-parser');
var raincatcherUser = require('fh-wfm-user/lib/router/mbaas');

// list the endpoints which you want to make securable here
var securableEndpoints;
securableEndpoints = ['/hello'];

var app = express();

// Enable CORS for all requests
app.use(cors());

// Note: the order which we add middleware to Express here is important!
app.use('/sys', mbaasExpress.sys(securableEndpoints));
app.use('/mbaas', mbaasExpress.mbaas);

// allow serving of static files from the public directory
app.use(express.static(__dirname + '/public'));

// Note: important that this is added just before your own Routes
app.use(mbaasExpress.fhmiddleware());

app.use('/hello', require('./lib/hello.js')());
app.use('/api', bodyParser.json({limit: '10mb'}));

// Session and Cookie configuration
// This is being consumed in the raincatcher-user mbaas router.
var sessionOptions = {
  store: 'mongo',
  config: {
    secret: process.env.FH_COOKIE_SECRET || 'raincatcher',
    host: '127.0.0.1',
    port: '27017',
    db: 'session',
    url: 'mongodb://localhost:27017/raincatcher-demo-auth-session-store',
    resave: false,
    saveUninitialized: true,
    cookie: {
      secure: process.env.NODE_ENV !== 'development',
      httpOnly: true,
      path: '/'
    }
  }
};

// find out mongodb connection string from $fh.db
$fh.db({
  act: 'connectionString'
}, function(err, connectionString) {
  if (err || !connectionString) {
    console.log('$fh.db connectionString not found, assuming database on localhost');
  } else {
    sessionOptions.url = connectionString;
  }
  // List the user fields which you don't want appearing in the authentication response.
  // This is being consumed in the raincatcher-user mbaas router.
  var authResponseExclusionList = ['password'];
  raincatcherUser.init(mediator, app, authResponseExclusionList, sessionOptions, function(err) {
    if (err) {
      return console.error(err);
    }
    require('./lib/user')(mediator);

    // Important that this is last!
    app.use(mbaasExpress.errorHandler());

    var port = process.env.FH_PORT || process.env.OPENSHIFT_NODEJS_PORT || 8001;
    var host = process.env.OPENSHIFT_NODEJS_IP || '0.0.0.0';
    app.listen(port, host, function() {
      console.log("App started at: " + new Date() + " on port: " + port);
    });
  });
});
<|endoftext|>


<commit_before>import axios from 'axios'
import express from 'express'
import sharify from 'sharify'

import CONFIG from 'config.coffee'

const app = express()

app.post('/graphql', (req, res) => {
  const X_AUTH_TOKEN =
    req.headers['x-auth-token'] ||
    (req.user && req.user.get('authentication_token'))

  const X_APP_TOKEN = req.headers['x-app-token'] || CONFIG.X_APP_TOKEN

  const X_SHARE_TOKEN =
    req.headers['x-share-token'] || sharify.data.X_SHARE_TOKEN

  const headers = {
    ...(X_AUTH_TOKEN && { 'X-AUTH-TOKEN': X_AUTH_TOKEN }),
    ...(X_APP_TOKEN && { 'X-APP-TOKEN': X_APP_TOKEN }),
    ...(X_SHARE_TOKEN && { 'X-SHARE-TOKEN': X_SHARE_TOKEN }),
  }

  return axios({
    method: 'post',
    url: CONFIG.GRAPHQL_ENDPOINT,
    data: req.body,
    headers,
  })
    .then(({ data }) => res.json(data))
    .catch(err =>
      res.json({
        code: err.status || 500,
        message: err.message,
        stack: err.stack,
      })
    )
})

app.post('/graphql/contentful', (req, res) => {
  const { CONTENTFUL_TOKEN } = CONFIG
  const headers = {
    ...(CONTENTFUL_TOKEN && { Authorization: `Bearer ${CONTENTFUL_TOKEN}` }),
  }

  return axios({
    method: 'post',
    url: CONFIG.CONTENTFUL_GRAPHQL_ENDPOINT,
    data: req.body,
    headers,
  })
    .then(({ data }) => {
      return res.json(data)
    })
    .catch(err => {
      console.log({ err })
      return res.json({
        code: err.status || 500,
        message: err.message,
        stack: err.stack,
      })
    })
})

module.exports = app
<commit_msg>Remove log on contenful route<commit_after>import axios from 'axios'
import express from 'express'
import sharify from 'sharify'

import CONFIG from 'config.coffee'

const app = express()

app.post('/graphql', (req, res) => {
  const X_AUTH_TOKEN =
    req.headers['x-auth-token'] ||
    (req.user && req.user.get('authentication_token'))

  const X_APP_TOKEN = req.headers['x-app-token'] || CONFIG.X_APP_TOKEN

  const X_SHARE_TOKEN =
    req.headers['x-share-token'] || sharify.data.X_SHARE_TOKEN

  const headers = {
    ...(X_AUTH_TOKEN && { 'X-AUTH-TOKEN': X_AUTH_TOKEN }),
    ...(X_APP_TOKEN && { 'X-APP-TOKEN': X_APP_TOKEN }),
    ...(X_SHARE_TOKEN && { 'X-SHARE-TOKEN': X_SHARE_TOKEN }),
  }

  return axios({
    method: 'post',
    url: CONFIG.GRAPHQL_ENDPOINT,
    data: req.body,
    headers,
  })
    .then(({ data }) => res.json(data))
    .catch(err =>
      res.json({
        code: err.status || 500,
        message: err.message,
        stack: err.stack,
      })
    )
})

app.post('/graphql/contentful', (req, res) => {
  const { CONTENTFUL_TOKEN } = CONFIG
  const headers = {
    ...(CONTENTFUL_TOKEN && { Authorization: `Bearer ${CONTENTFUL_TOKEN}` }),
  }

  return axios({
    method: 'post',
    url: CONFIG.CONTENTFUL_GRAPHQL_ENDPOINT,
    data: req.body,
    headers,
  })
    .then(({ data }) => {
      return res.json(data)
    })
    .catch(err => {
      return res.json({
        code: err.status || 500,
        message: err.message,
        stack: err.stack,
      })
    })
})

module.exports = app
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Button from 'material-ui/Button';
import AddIcon from 'material-ui-icons/Add';

import CategoryEditor from '../CategoryEditor/CategoryEditor.js';

/*
 * CategoryCreator has two states: default and create.
 *   default: Displays an "add" fab.
 *   create:  Displays a CategoryEditor widget in place of the fab.
 */

const STATES = {
  default: "default",
  create: "create"
}

class CategoryCreator extends Component {
  constructor(props) {
    super(props);
    this.state = {
      view: STATES.default
    };
    this.toggleState = this.toggleState.bind(this);
  }

  toggleState(e) {
    this.setState((prevState) => {
      let nextView = prevState.view === STATES.default ? STATES.create : STATES.default;
      return {view: nextView}
    });
  }

  render() {
    let display = null;
    if (this.state.view === STATES.default) {  //TODO enum of states.
      display = (
        <Button fab mini color="primary" aria-label="add" onClick={this.toggleState}>
          <AddIcon />
        </Button>
      )
    } else if (this.state.view === STATES.create) {
      display = (
        <CategoryEditor
          handleClose={this.toggleState}
          handleSave={this.props.handleCreate}
          ariaLabel="Create a new category."
        />
      )
    }
    return display;
  }
}

CategoryCreator.propTypes = {
  // Passed through to CategoryEditor
  handleCreate: PropTypes.func.isRequired
}

export default CategoryCreator;
<commit_msg>breaking changes v0.32 update<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Button from 'material-ui/Button';
import AddIcon from 'material-ui-icons/Add';

import CategoryEditor from '../CategoryEditor/CategoryEditor.js';

/*
 * CategoryCreator has two states: default and create.
 *   default: Displays an "add" fab.
 *   create:  Displays a CategoryEditor widget in place of the fab.
 */

const STATES = {
  default: "default",
  create: "create"
}

class CategoryCreator extends Component {
  constructor(props) {
    super(props);
    this.state = {
      view: STATES.default
    };
    this.toggleState = this.toggleState.bind(this);
  }

  toggleState(e) {
    this.setState((prevState) => {
      let nextView = prevState.view === STATES.default ? STATES.create : STATES.default;
      return {view: nextView}
    });
  }

  render() {
    let display = null;
    if (this.state.view === STATES.default) {  //TODO enum of states.
      display = (
        <Button variant="fab" mini color="primary" aria-label="add" onClick={this.toggleState}>
          <AddIcon />
        </Button>
      )
    } else if (this.state.view === STATES.create) {
      display = (
        <CategoryEditor
          handleClose={this.toggleState}
          handleSave={this.props.handleCreate}
          ariaLabel="Create a new category."
        />
      )
    }
    return display;
  }
}

CategoryCreator.propTypes = {
  // Passed through to CategoryEditor
  handleCreate: PropTypes.func.isRequired
}

export default CategoryCreator;
<|endoftext|>


<commit_before>var Helper = require('../helper');
var definitions = require('./definitions');
var sys = require('sys');

exports.first_name = function(){

  return definitions.first_name[0];
  //Math.floor(Math.random()*10);

};

exports.findName = function() {
	var r = Helper.randomNumber(8);
	sys.puts('random is: ' + r);
	switch(r)
	{
	case 0:
	 return Helper.randomize(definitions.name_prefix) + " " + Helper.randomize(definitions.first_name) + " " +  Helper.randomize(definitions.last_name);
	 break;
	case 1:
	 return Helper.randomize(definitions.first_name) + " " + Helper.randomize(definitions.last_name); + " " + Helper.randomize(definitions.name_suffix);
	  break;
	}

	return Helper.randomize(definitions.first_name) + Helper.randomize(definitions.last_name);

};
    <commit_msg>fixed marak commit for findName<commit_after>var Helper = require('../helper');
var definitions = require('./definitions');

exports.first_name = function(){

  return definitions.first_name[0];
  //Math.floor(Math.random()*10);

};

exports.findName = function() {
	var r = Helper.randomNumber(8);
	switch(r)
	{
	case 0:
	 return Helper.randomize(definitions.name_prefix) + " " + Helper.randomize(definitions.first_name) + " " +  Helper.randomize(definitions.last_name);
	 break;
	case 1:
	 return Helper.randomize(definitions.first_name) + " " + Helper.randomize(definitions.last_name); + " " + Helper.randomize(definitions.name_suffix);
	  break;
	}

	return Helper.randomize(definitions.first_name) + " " + Helper.randomize(definitions.last_name);

};
    <|endoftext|>


<commit_before><commit_msg>Ongoing changes<commit_after><|endoftext|>


<commit_before>var DataColumnsDao = require('../../../lib/dataColumns').DataColumnsDao
  , DataColumns = require('../../../lib/dataColumns').DataColumns
  , DataColumnConstraintsDao = require('../../../lib/dataColumnConstraints').DataColumnConstraintsDao
  , DataColumnConstraints = require('../../../lib/dataColumnConstraints').DataColumnConstraints
  , GeoPackageConnection = require('../../../lib/db/geoPackageConnection')
  , TableCreator = require('../../../lib/db/tableCreator')
  , path = require('path')
  , fs = require('fs')
  , should = require('chai').should();

describe('Data Columns tests', function() {

  var connection;

  var originalFilename = path.join(__dirname, '..', '..', 'fixtures', 'rivers.gpkg');
  var filename = path.join(__dirname, '..', '..', 'fixtures', 'tmp', 'rivers.gpkg');

  function copyGeopackage(orignal, copy, callback) {
    if (typeof(process) !== 'undefined' && process.version) {
      var fsExtra = require('fs-extra');
      fsExtra.copy(originalFilename, filename, callback);
    } else {
      filename = originalFilename;
      callback();
    }
  }

  beforeEach('create the GeoPackage connection', function(done) {
    copyGeopackage(originalFilename, filename, function(err) {
      GeoPackageConnection.connect(filename, function(err, geoPackageConnection) {
        connection = geoPackageConnection;
        should.exist(connection);
        done();
      });
    });
  });

  afterEach('should close the geopackage', function(done) {
    connection.close();
    if (typeof(process) !== 'undefined' && process.version) {
      fs.unlink(filename, done);
    } else {
      done();
    }
  });

  it('should get the data column for property_0', function(done) {
    var dc = new DataColumnsDao(connection);
    dc.getDataColumns('FEATURESriversds', 'property_0', function(err, dataColumn) {
      dataColumn.should.be.deep.equal({
        table_name: 'FEATURESriversds',
        column_name: 'property_0',
        name: 'Scalerank',
        title: 'Scalerank',
        description: 'Scalerank',
        mime_type: null,
        constraint_name: null
      });
      done();
    });
  });

  it('should get the contents for the data column for property_0', function(done) {
    var dc = new DataColumnsDao(connection);
    dc.getDataColumns('FEATURESriversds', 'property_0', function(err, dataColumn) {
      dc.getContents(dataColumn, function(err, contents) {
        contents.should.be.deep.equal({
          table_name: 'FEATURESriversds',
          data_type: 'features',
          identifier: 'FEATURESriversds',
          description: null,
          last_change: '2015-12-04T15:28:59.122Z',
          min_x: -20037508.342789244,
          min_y: -19971868.88040857,
          max_x: 20037508.342789244,
          max_y: 19971868.880408563,
          srs_id: 3857
        });
        done();
      });
    });
  });

  it('should get the data column for geom', function(done) {
    var dc = new DataColumnsDao(connection);
    dc.getDataColumns('FEATURESriversds', 'geom', function(err, dataColumn) {
      should.not.exist(err);
      should.not.exist(dataColumn);
      done();
    });
  });

  it('should create a data column', function(done) {
    var dao = new DataColumnsDao(connection);
    var dc = new DataColumns();
    dc.table_name = 'FEATURESriversds';
    dc.column_name = 'test';
    dc.name = 'Test Name';
    dc.title = 'Test';
    dc.description = 'Test Description';
    dc.mime_type = 'text/html';
    dc.constraint_name = 'test constraint';
    dao.create(dc, function(err, result){
      dao.getDataColumns('FEATURESriversds', 'test', function(err, dataColumn) {
        dataColumn.should.be.deep.equal({
          table_name: 'FEATURESriversds',
          column_name: 'test',
          name: 'Test Name',
          title: 'Test',
          description: 'Test Description',
          mime_type: 'text/html',
          constraint_name: 'test constraint'
        });
        done();
      });
    });
  });

  it('should query by the constraint name to retrieve a data column', function(done) {
    var dao = new DataColumnsDao(connection);
    var dc = new DataColumns();
    dc.table_name = 'FEATURESriversds';
    dc.column_name = 'test';
    dc.name = 'Test Name';
    dc.title = 'Test';
    dc.description = 'Test Description';
    dc.mime_type = 'text/html';
    dc.constraint_name = 'test constraint';
    dao.create(dc, function(err, result){
      dao.queryByConstraintName('test constraint', function(err, dataColumn, rowDone) {
        dataColumn.should.be.deep.equal({
          table_name: 'FEATURESriversds',
          column_name: 'test',
          name: 'Test Name',
          title: 'Test',
          description: 'Test Description',
          mime_type: 'text/html',
          constraint_name: 'test constraint'
        });
        rowDone();
      }, done);
    });
  });

  it('should create a data column constraint', function(done) {
    var tc = new TableCreator(connection);
    tc.createDataColumnConstraints(function() {
      var dao = new DataColumnConstraintsDao(connection);
      var dc = new DataColumnConstraints();
      dc.constraint_name = 'test constraint';
      dc.constraint_type = 'range';
      dc.value = 'NULL';
      dc.min = 5;
      dc.min_is_inclusive = true;
      dc.max = 6;
      dc.max_is_inclusive = true;
      dc.description = 'constraint description';

      dao.create(dc, function(err, result) {
        console.log('err', err);
        console.log('result', result);
        dao.queryByConstraintName('test constraint', function(err, dataColumnConstraint, rowDone) {
          console.log('constraint name err', err);
          dataColumnConstraint.should.be.deep.equal({
            constraint_name: 'test constraint',
            constraint_type: 'range',
            value: 'NULL',
            min: 5,
            min_is_inclusive: 1,
            max: 6,
            max_is_inclusive: 1,
            description: 'constraint description'
          });
          rowDone();
        }, done);
      });
    });
  });

  it('should create a data column constraint and query unique', function(done) {
    var tc = new TableCreator(connection);
    tc.createDataColumnConstraints(function() {
      var dao = new DataColumnConstraintsDao(connection);
      var dc = new DataColumnConstraints();
      dc.constraint_name = 'test constraint';
      dc.constraint_type = 'range';
      dc.value = 'NULL';
      dc.min = 5;
      dc.min_is_inclusive = true;
      dc.max = 6;
      dc.max_is_inclusive = true;
      dc.description = 'constraint description';

      dao.create(dc, function(err, result) {
        dao.queryUnique('test constraint', 'range', 'NULL', function(err, dataColumnConstraint) {
          dataColumnConstraint.should.be.deep.equal({
            constraint_name: 'test constraint',
            constraint_type: 'range',
            value: 'NULL',
            min: 5,
            min_is_inclusive: 1,
            max: 6,
            max_is_inclusive: 1,
            description: 'constraint description'
          });
          done();
        });
      });
    });
  });

});
<commit_msg>if error fail test<commit_after>var DataColumnsDao = require('../../../lib/dataColumns').DataColumnsDao
  , DataColumns = require('../../../lib/dataColumns').DataColumns
  , DataColumnConstraintsDao = require('../../../lib/dataColumnConstraints').DataColumnConstraintsDao
  , DataColumnConstraints = require('../../../lib/dataColumnConstraints').DataColumnConstraints
  , GeoPackageConnection = require('../../../lib/db/geoPackageConnection')
  , TableCreator = require('../../../lib/db/tableCreator')
  , path = require('path')
  , fs = require('fs')
  , should = require('chai').should();

describe('Data Columns tests', function() {

  var connection;

  var originalFilename = path.join(__dirname, '..', '..', 'fixtures', 'rivers.gpkg');
  var filename = path.join(__dirname, '..', '..', 'fixtures', 'tmp', 'rivers.gpkg');

  function copyGeopackage(orignal, copy, callback) {
    if (typeof(process) !== 'undefined' && process.version) {
      var fsExtra = require('fs-extra');
      fsExtra.copy(originalFilename, filename, callback);
    } else {
      filename = originalFilename;
      callback();
    }
  }

  beforeEach('create the GeoPackage connection', function(done) {
    copyGeopackage(originalFilename, filename, function(err) {
      GeoPackageConnection.connect(filename, function(err, geoPackageConnection) {
        connection = geoPackageConnection;
        should.exist(connection);
        done();
      });
    });
  });

  afterEach('should close the geopackage', function(done) {
    connection.close();
    if (typeof(process) !== 'undefined' && process.version) {
      fs.unlink(filename, done);
    } else {
      done();
    }
  });

  it('should get the data column for property_0', function(done) {
    var dc = new DataColumnsDao(connection);
    dc.getDataColumns('FEATURESriversds', 'property_0', function(err, dataColumn) {
      dataColumn.should.be.deep.equal({
        table_name: 'FEATURESriversds',
        column_name: 'property_0',
        name: 'Scalerank',
        title: 'Scalerank',
        description: 'Scalerank',
        mime_type: null,
        constraint_name: null
      });
      done();
    });
  });

  it('should get the contents for the data column for property_0', function(done) {
    var dc = new DataColumnsDao(connection);
    dc.getDataColumns('FEATURESriversds', 'property_0', function(err, dataColumn) {
      dc.getContents(dataColumn, function(err, contents) {
        contents.should.be.deep.equal({
          table_name: 'FEATURESriversds',
          data_type: 'features',
          identifier: 'FEATURESriversds',
          description: null,
          last_change: '2015-12-04T15:28:59.122Z',
          min_x: -20037508.342789244,
          min_y: -19971868.88040857,
          max_x: 20037508.342789244,
          max_y: 19971868.880408563,
          srs_id: 3857
        });
        done();
      });
    });
  });

  it('should get the data column for geom', function(done) {
    var dc = new DataColumnsDao(connection);
    dc.getDataColumns('FEATURESriversds', 'geom', function(err, dataColumn) {
      should.not.exist(err);
      should.not.exist(dataColumn);
      done();
    });
  });

  it('should create a data column', function(done) {
    var dao = new DataColumnsDao(connection);
    var dc = new DataColumns();
    dc.table_name = 'FEATURESriversds';
    dc.column_name = 'test';
    dc.name = 'Test Name';
    dc.title = 'Test';
    dc.description = 'Test Description';
    dc.mime_type = 'text/html';
    dc.constraint_name = 'test constraint';
    dao.create(dc, function(err, result){
      if (err) return done(err);
      dao.getDataColumns('FEATURESriversds', 'test', function(err, dataColumn) {
        dataColumn.should.be.deep.equal({
          table_name: 'FEATURESriversds',
          column_name: 'test',
          name: 'Test Name',
          title: 'Test',
          description: 'Test Description',
          mime_type: 'text/html',
          constraint_name: 'test constraint'
        });
        done();
      });
    });
  });

  it('should query by the constraint name to retrieve a data column', function(done) {
    var dao = new DataColumnsDao(connection);
    var dc = new DataColumns();
    dc.table_name = 'FEATURESriversds';
    dc.column_name = 'test';
    dc.name = 'Test Name';
    dc.title = 'Test';
    dc.description = 'Test Description';
    dc.mime_type = 'text/html';
    dc.constraint_name = 'test constraint';
    dao.create(dc, function(err, result){
      if (err) return done(err);
      dao.queryByConstraintName('test constraint', function(err, dataColumn, rowDone) {
        dataColumn.should.be.deep.equal({
          table_name: 'FEATURESriversds',
          column_name: 'test',
          name: 'Test Name',
          title: 'Test',
          description: 'Test Description',
          mime_type: 'text/html',
          constraint_name: 'test constraint'
        });
        rowDone();
      }, done);
    });
  });

  it('should create a data column constraint', function(done) {
    var tc = new TableCreator(connection);
    tc.createDataColumnConstraints(function() {
      var dao = new DataColumnConstraintsDao(connection);
      var dc = new DataColumnConstraints();
      dc.constraint_name = 'test constraint';
      dc.constraint_type = 'range';
      dc.value = 'NULL';
      dc.min = 5;
      dc.min_is_inclusive = true;
      dc.max = 6;
      dc.max_is_inclusive = true;
      dc.description = 'constraint description';

      dao.create(dc, function(err, result) {
        console.log('err', err);
        console.log('result', result);
        dao.queryByConstraintName('test constraint', function(err, dataColumnConstraint, rowDone) {
          console.log('constraint name err', err);
          dataColumnConstraint.should.be.deep.equal({
            constraint_name: 'test constraint',
            constraint_type: 'range',
            value: 'NULL',
            min: 5,
            min_is_inclusive: 1,
            max: 6,
            max_is_inclusive: 1,
            description: 'constraint description'
          });
          rowDone();
        }, done);
      });
    });
  });

  it('should create a data column constraint and query unique', function(done) {
    var tc = new TableCreator(connection);
    tc.createDataColumnConstraints(function() {
      var dao = new DataColumnConstraintsDao(connection);
      var dc = new DataColumnConstraints();
      dc.constraint_name = 'test constraint';
      dc.constraint_type = 'range';
      dc.value = 'NULL';
      dc.min = 5;
      dc.min_is_inclusive = true;
      dc.max = 6;
      dc.max_is_inclusive = true;
      dc.description = 'constraint description';

      dao.create(dc, function(err, result) {
        dao.queryUnique('test constraint', 'range', 'NULL', function(err, dataColumnConstraint) {
          dataColumnConstraint.should.be.deep.equal({
            constraint_name: 'test constraint',
            constraint_type: 'range',
            value: 'NULL',
            min: 5,
            min_is_inclusive: 1,
            max: 6,
            max_is_inclusive: 1,
            description: 'constraint description'
          });
          done();
        });
      });
    });
  });

});
<|endoftext|>