<commit_before>/* global describe, context, it, before, after, afterEach */
'use strict';

const path = require('path');
const lint = require('mocha-eslint');
const expect = require('chai').expect;
const session = require('express-session');
const firebase = require('firebase');
const FirebaseStore = require(path.normalize(`${__dirname}/../lib/connect-session-firebase.js`))(session);

require('dotenv').config({ silent: true });

describe('Code Standards', function () {
  this.slow(1000);

  lint(['index.js', 'lib/connect-session-firebase.js', 'test/test.js']);
});

describe('FirebaseStore', function () {
  this.timeout(10000);
  this.slow(5000);

  before('set up', function (done) {
    const config = {
      serviceAccount: process.env.FIREBASE_SERVICE_ACCOUNT,
      databaseURL: process.env.FIREBASE_DATABASE_URL
    };

    this.firebase = firebase.initializeApp(config);

    this.store = new FirebaseStore({
      database: this.firebase.database()
    });

    done();
  });

  afterEach('clear', function (done) {
    this.store.clear()
      .then(done);
  });

  after('tear down', function (done) {
    this.firebase.delete();
    done();
  });

  context('when passed a valid firebase app', function () {
    it('should be an instance of FirebaseStore', function (done) {
      const store = new FirebaseStore({ database: this.firebase });

      expect(store).to.be.instanceof(FirebaseStore);
      done();
    });
  });

  context('when passed a valid firebase database', function () {
    it('should be an instance of FirebaseStore', function (done) {
      const store = new FirebaseStore({ database: this.firebase.database() });

      expect(store).to.be.instanceof(FirebaseStore);
      done();
    });
  });

  context('when passed valid arguments', function () {
    it('should be an instance of FirebaseStore', function (done) {
      expect(this.store).to.be.instanceof(FirebaseStore);
      done();
    });
  });

  context('when passed an invalid database', function () {
    const tests = [
      { key: 'object', args: { database: {} } },
      { key: 'array', args: { database: [] } },
      { key: 'string', args: { database: '' } }
    ];

    tests.forEach(function (test) {
      it(`${JSON.stringify(test.key)} should throw an error`, function (done) {
        expect(() => new FirebaseStore(test.args)).to.throw(Error);
        done();
      });
    });
  });

  context('when passed invalid arguments', function () {
    const tests = [
      { key: 'object', args: {} },
      { key: 'array', args: [] },
      { key: 'string', args: '' }
    ];

    tests.forEach(function (test) {
      it(`${JSON.stringify(test.key)} should throw an error`, function (done) {
        expect(() => new FirebaseStore(test.args)).to.throw(Error);
        done();
      });
    });
  });

  describe('.set()', function () {
    it('should save a session', function (done) {

      Promise.all([
        this.store.set('1', { name: 'tj', cookie: { maxAge: 1000 } }),
        this.store.set('2', { name: 'tj', cookie: { maxAge: 2000 } })
      ])
      .then(() => {
        done();
      });

    });
  });

  describe('.get()', function () {
    before('save a session', function (done) {

      Promise.all([
        this.store.set('1', { name: 'tj', cookie: { maxAge: 1000 } }, (err, first) => first),
        this.store.set('2', { name: 'tj', cookie: { maxAge: 2000 } }, (err, second) => second)
      ])
      .then(() => {
        done();
      });

    });

    it('should fetch a session', function (done) {

      Promise.all([
        this.store.get('1', (err, first) => first)
      ])
      .then(sessions => {
        const first = sessions[0];
        const second = sessions[1];

        expect(first).to.exist.and.to.have.property('cookie').and.to.have.property('maxAge').and.to.eql(1000);
        expect(second).to.not.exist;

        done();
      });

    });
  });

  describe('.destroy()', function () {
    before('save sessions', function (done) {

      Promise.all([
        this.store.set('1', { name: 'tj', cookie: { maxAge: 1000 } }),
        this.store.set('2', { name: 'tj', cookie: { maxAge: 2000 } })
      ])
      .then(sessions => {
        done();
      });

    });

    it('should remove a session', function (done) {
      this.store.destroy('1')
        .then((err, sessions) => {

          Promise.all([
            this.store.get('1', (err, first) => first),
            this.store.get('2', (err, second) => second)
          ])
          .then(sessions => {
            const first = sessions[0];
            const second = sessions[1];

            expect(first).to.not.exist;
            expect(second).to.exist.and.to.have.property('cookie').and.to.have.property('maxAge').and.to.eql(2000);

            done();
          });

        });
    });
  });

  describe('.clear()', function () {
    before('save sessions', function (done) {

      Promise.all([
        this.store.set('1', { name: 'tj', cookie: { maxAge: 1000 } }),
        this.store.set('2', { name: 'tj', cookie: { maxAge: 2000 } })
      ])
      .then(() => done());

    });

    it('should remove all sessions', function (done) {
      this.store.clear()
        .then(() => {

          Promise.all([
            this.store.get('1', (err, first) => first),
            this.store.get('2', (err, second) => second)
          ])
          .then(sessions => {
            const first = sessions[0];
            const second = sessions[1];

            expect(first).to.not.exist;
            expect(second).to.not.exist;

            done();
          });

        });
    });
  });

  describe('.reap()', function () {
    before('save sessions', function (done) {

      Promise.all([
        this.store.set('1', { name: 'tj', cookie: { maxAge: -1000 } }),
        this.store.set('2', { name: 'tj', cookie: { maxAge: 2000 } }),
        this.store.set('3', { name: 'tj', cookie: { maxAge: -3000 } })
      ])
      .then(() => done());

    });

    it('should remove expired sessions', function (done) {
      this.store.reap()
        .then(() => {

          Promise.all([
            this.store.get('1', (err, first) => first),
            this.store.get('2', (err, second) => second),
            this.store.get('3', (err, third) => third)
          ])
          .then(sessions => {
            const first = sessions[0];
            const second = sessions[1];
            const third = sessions[2];

            expect(first).to.not.exist;
            expect(second).to.exist.and.to.have.property('cookie').and.to.have.property('maxAge').and.to.eql(2000);
            expect(third).to.not.exist;

            done();
          });

      });
    });
  });

  describe('.touch()', function () {
    before('save sessions', function (done) {

      Promise.all([
        this.store.set('1', { name: 'tj', cookie: { maxAge: 1000 } }),
        this.store.set('2', { name: 'tj', cookie: { maxAge: 2000 } })
      ])
      .then(() => done());

    });

    it('should update a session', function (done) {

      this.store.touch('1', { name: 'bn', cookie: { maxAge: 3000 } })
        .then(() => {

          Promise.all([
            this.store.get('1', (err, first) => first),
            this.store.get('2', (err, second) => second)
          ])
          .then(sessions => {
            const first = sessions[0];
            const second = sessions[1];

            expect(first).to.exist.and.to.have.property('name').and.to.eql('tj');
            expect(first).to.exist.and.to.have.property('cookie').and.to.have.property('maxAge').and.to.eql(3000);

            expect(second).to.exist.and.to.have.property('name').and.to.eql('tj');
            expect(second).to.exist.and.to.have.property('cookie').and.to.have.property('maxAge').and.to.eql(2000);

            done();
          });

        });

    });
  });
});
<commit_msg>Improvements to Promises in all test cases<commit_after>/* global describe, context, it, before, after */
'use strict';

const path = require('path');
const lint = require('mocha-eslint');
const expect = require('chai').expect;
const session = require('express-session');
const firebase = require('firebase');
const FirebaseStore = require(path.normalize(`${__dirname}/../lib/connect-session-firebase.js`))(session);

require('dotenv').config({ silent: true });

describe('Code Standards', function () {
  this.slow(1000);

  lint(['index.js', 'lib/connect-session-firebase.js', 'test/test.js']);
});

describe('FirebaseStore', function () {
  this.timeout(10000);
  this.slow(5000);

  before('set up', function (done) {
    const config = {
      serviceAccount: process.env.FIREBASE_SERVICE_ACCOUNT,
      databaseURL: process.env.FIREBASE_DATABASE_URL
    };

    this.firebase = firebase.initializeApp(config);

    this.store = new FirebaseStore({
      database: this.firebase.database()
    });

    done();
  });

  after('tear down', function (done) {
    this.firebase.delete();
    done();
  });

  context('when passed a valid firebase app', function () {
    it('should be an instance of FirebaseStore', function (done) {
      const store = new FirebaseStore({ database: this.firebase });

      expect(store).to.be.instanceof(FirebaseStore);
      done();
    });
  });

  context('when passed a valid firebase database', function () {
    it('should be an instance of FirebaseStore', function (done) {
      const store = new FirebaseStore({ database: this.firebase.database() });

      expect(store).to.be.instanceof(FirebaseStore);
      done();
    });
  });

  context('when passed valid arguments', function () {
    it('should be an instance of FirebaseStore', function (done) {
      expect(this.store).to.be.instanceof(FirebaseStore);
      done();
    });
  });

  context('when passed an invalid database', function () {
    const tests = [
      { key: 'object', args: { database: {} } },
      { key: 'array', args: { database: [] } },
      { key: 'string', args: { database: '' } }
    ];

    tests.forEach(function (test) {
      it(`${JSON.stringify(test.key)} should throw an error`, function (done) {
        expect(() => new FirebaseStore(test.args)).to.throw(Error);
        done();
      });
    });
  });

  context('when passed invalid arguments', function () {
    const tests = [
      { key: 'object', args: {} },
      { key: 'array', args: [] },
      { key: 'string', args: '' }
    ];

    tests.forEach(function (test) {
      it(`${JSON.stringify(test.key)} should throw an error`, function (done) {
        expect(() => new FirebaseStore(test.args)).to.throw(Error);
        done();
      });
    });
  });

  describe('.set()', function () {
    it('should save a session', function (done) {

      Promise.all([
        this.store.set('set-1', { name: 'tj', maxAge: 10000 }),
        this.store.set('set-2', { name: 'tj', maxAge: 20000 })
      ])
      .then(() => done());

    });
  });

  describe('.get()', function () {
    before('save sessions', function (done) {

      Promise.all([
        this.store.set('get-1', { name: 'tj', cookie: { maxAge: 10000 } }, (err, first) => first),
        this.store.set('get-2', { name: 'tj', cookie: { maxAge: -20000 } }, (err, second) => second)
      ])
      .then(() => done());

    });

    it('should fetch a session', function (done) {

      Promise.all([
        this.store.get('get-1', (err, first) => first)
      ])
      .then(sessions => {
        const first = sessions[0];

        expect(first).to.exist.and.to.have.property('cookie').and.to.have.property('maxAge').and.to.eql(10000);

      })
      .then(() => done());

    });

    it('should remove an expired session', function (done) {

      Promise.all([
        this.store.get('get-2', (err, second) => second)
      ])
      .then(sessions => {
        const second = sessions[0];

        expect(second).to.not.exist;
      })
      .then(() => done());

    });
  });

  describe('.destroy()', function () {
    before('save sessions', function (done) {

      Promise.all([
        this.store.set('destroy-1', { name: 'tj', cookie: { maxAge: 10000 } }),
        this.store.set('destroy-2', { name: 'tj', cookie: { maxAge: 20000 } })
      ])
      .then(() => done());

    });

    it('should remove a session', function (done) {
      this.store.destroy('destroy-1')
        .then(() => {

          Promise.all([
            this.store.get('destroy-1', (err, first) => first),
            this.store.get('destroy-2', (err, second) => second)
          ])
          .then(sessions => {
            const first = sessions[0];
            const second = sessions[1];

            expect(first).to.not.exist;
            expect(second).to.exist.and.to.have.property('cookie').and.to.have.property('maxAge').and.to.eql(20000);
          })
          .then(() => done());

        });
    });
  });

  describe('.reap()', function () {
    before('save sessions', function (done) {

      Promise.all([
        this.store.set('reap-1', { name: 'tj', cookie: { maxAge: -10000 } }),
        this.store.set('reap-2', { name: 'tj', cookie: { maxAge: 20000 } }),
        this.store.set('reap-3', { name: 'tj', cookie: { maxAge: -30000 } })
      ])
      .then(() => done());

    });

    it('should remove expired sessions', function (done) {
      this.store.reap()
        .then(() => {

          Promise.all([
            this.store.get('reap-1', (err, first) => first),
            this.store.get('reap-2', (err, second) => second),
            this.store.get('reap-3', (err, third) => third)
          ])
          .then(sessions => {
            const first = sessions[0];
            const second = sessions[1];
            const third = sessions[2];

            expect(first).to.not.exist;
            expect(second).to.exist.and.to.have.property('cookie').and.to.have.property('maxAge').and.to.eql(20000);
            expect(third).to.not.exist;
          })
          .then(() => done());

      });
    });
  });

  describe('.touch()', function () {
    before('save sessions', function (done) {

      Promise.all([
        this.store.set('touch-1', { name: 'tj', cookie: { maxAge: 10000 } }),
        this.store.set('touch-2', { name: 'tj', cookie: { maxAge: 20000 } })
      ])
      .then(() => done());

    });

    it('should update a session', function (done) {

      this.store.touch('touch-1', { name: 'bn', cookie: { maxAge: 30000 } })
        .then(() => {

          Promise.all([
            this.store.get('touch-1', (err, first) => first),
            this.store.get('touch-2', (err, second) => second)
          ])
          .then(sessions => {
            const first = sessions[0];
            const second = sessions[1];

            expect(first).to.exist.and.to.have.property('name').and.to.eql('tj');
            expect(first).to.exist.and.to.have.property('cookie').and.to.have.property('maxAge').and.to.eql(30000);

            expect(second).to.exist.and.to.have.property('name').and.to.eql('tj');
            expect(second).to.exist.and.to.have.property('cookie').and.to.have.property('maxAge').and.to.eql(20000);
          })
          .then(() => done());

        });

    });
  });

  describe('.clear()', function () {
    before('save sessions', function (done) {

      Promise.all([
        this.store.set('clear-1', { name: 'tj', cookie: { maxAge: 10000 } }),
        this.store.set('clear-2', { name: 'tj', cookie: { maxAge: 20000 } })
      ])
      .then(() => done());

    });

    it('should remove all sessions', function (done) {
      this.store.clear()
        .then(() => {

          Promise.all([
            this.store.get('clear-1', (err, first) => first),
            this.store.get('clear-2', (err, second) => second)
          ])
          .then(sessions => {
            const first = sessions[0];
            const second = sessions[1];

            expect(first).to.not.exist;
            expect(second).to.not.exist;
          })
          .then(() => done());

        });
    });
  });
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Background, { backgroundPropTypes } from '../../style/background/windows';
import { hiddenPropTypes } from '../../style/hidden';
import { ColorContext, colorPropTypes } from '../../style/color/windows';
import { ThemeContext, themePropTypes, themeContextTypes } from '../../style/theme/windows';
import WindowFocus from '../../windowFocus';
import Controls from './controls/controls';
import styles from './styles/windows10';

@Background((nextProps, prevProps, background) => ({ ...nextProps, hasBackground: background }))
@WindowFocus()
@ThemeContext()
@ColorContext()
class TitleBar extends Component {
  static propTypes = {
    ...hiddenPropTypes,
    ...themePropTypes,
    ...colorPropTypes,
    ...backgroundPropTypes,
    title: PropTypes.string,
    controls: PropTypes.bool,
    isMaximized: PropTypes.bool,
    onCloseClick: PropTypes.func,
    onMinimizeClick: PropTypes.func,
    onMaximizeClick: PropTypes.func,
    onRestoreDownClick: PropTypes.func
  };

  static childContextTypes = {
    isMaximized: PropTypes.bool
  };

  static contextTypes = {
    ...themeContextTypes
  };

  getChildContext() {
    return {
      isMaximized: this.props.isMaximized
    };
  }

  render() {
    const { children, style, controls, title, isWindowFocused, hasBackground, hidden, ...props } = this.props;

    delete props.isMaximized;
    delete props.onCloseClick;
    delete props.onMinimizeClick;
    delete props.onMaximizeClick;
    delete props.onRestoreDownClick;

    let componentStyle = { ...styles.titleBar, ...style };
    let titleStyle = styles.title;

    if (!isWindowFocused && this.context.theme !== 'dark') {
      titleStyle = { ...titleStyle, ...styles.unfocusedTitle };
    }

    if (this.context.theme === 'dark') {
      titleStyle = { ...titleStyle, ...styles.titleDark };
    }

    componentStyle = {
      ...componentStyle,
      visibility: !hidden ? 'visible' : 'hidden',
      display: !hidden ? 'flex' : 'none'
    };

    if (this.context.theme === 'dark') {
      componentStyle = { ...componentStyle, ...styles.titleBarDark };
    }

    const controlsComponent = !controls || <Controls {...this.props}/>;
    const titleComponent = !title ||

        {this.props.title}

;

    if (hasBackground) delete componentStyle.backgroundColor;

    return (

        {titleComponent}
        {controlsComponent}
        {children}

    );
  }
}

export default TitleBar;
<commit_msg>title  of  TitleBar  supports  element   node <commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Background, { backgroundPropTypes } from '../../style/background/windows';
import { hiddenPropTypes } from '../../style/hidden';
import { ColorContext, colorPropTypes } from '../../style/color/windows';
import { ThemeContext, themePropTypes, themeContextTypes } from '../../style/theme/windows';
import WindowFocus from '../../windowFocus';
import Controls from './controls/controls';
import styles from './styles/windows10';

@Background((nextProps, prevProps, background) => ({ ...nextProps, hasBackground: background }))
@WindowFocus()
@ThemeContext()
@ColorContext()
class TitleBar extends Component {
  static propTypes = {
    ...hiddenPropTypes,
    ...themePropTypes,
    ...colorPropTypes,
    ...backgroundPropTypes,
    title: PropTypes.object,
    controls: PropTypes.bool,
    isMaximized: PropTypes.bool,
    onCloseClick: PropTypes.func,
    onMinimizeClick: PropTypes.func,
    onMaximizeClick: PropTypes.func,
    onRestoreDownClick: PropTypes.func
  };

  static childContextTypes = {
    isMaximized: PropTypes.bool
  };

  static contextTypes = {
    ...themeContextTypes
  };

  getChildContext() {
    return {
      isMaximized: this.props.isMaximized
    };
  }

  render() {
    const { children, style, controls, title, isWindowFocused, hasBackground, hidden, ...props } = this.props;

    delete props.isMaximized;
    delete props.onCloseClick;
    delete props.onMinimizeClick;
    delete props.onMaximizeClick;
    delete props.onRestoreDownClick;

    let componentStyle = { ...styles.titleBar, ...style };
    let titleStyle = styles.title;

    if (!isWindowFocused && this.context.theme !== 'dark') {
      titleStyle = { ...titleStyle, ...styles.unfocusedTitle };
    }

    if (this.context.theme === 'dark') {
      titleStyle = { ...titleStyle, ...styles.titleDark };
    }

    componentStyle = {
      ...componentStyle,
      visibility: !hidden ? 'visible' : 'hidden',
      display: !hidden ? 'flex' : 'none'
    };

    if (this.context.theme === 'dark') {
      componentStyle = { ...componentStyle, ...styles.titleBarDark };
    }

    const controlsComponent = !controls || <Controls {...this.props}/>;
    const titleComponent = !title ||

        {this.props.title}

;

    if (hasBackground) delete componentStyle.backgroundColor;

    return (

        {titleComponent}
        {controlsComponent}
        {children}

    );
  }
}

export default TitleBar;
<|endoftext|>


<commit_before>'use strict';

const Promise = require('bluebird').Promise;
const Path = require('path');
const logger = require('./logger.js');

class Job {

  constructor(client, config) {
    this.client = client;
    this.config = config;

    // Shared between all Job classes
    this.jid = config.jid;
    this.priority = config.priority;
    this.klassName = config.klass;
    this.queueName = config.queue;
    this.tags = config.tags;
    this.data = JSON.parse(config.data);

    // Specific to non-recurring jobs
    this.state = config.state;
    this.tracked = config.tracked;
    this.failure = config.failure;
    this.history = config.history;
    this.dependents = config.dependents;
    this.dependencies = config.dependencies;
    this.expiresAt = config.expires;
    this.originalRetries = config.retries;
    this.retriesLeft = config.remaining;
    this.workerName = config.worker;
  }

  /**
   * Given a string name of a class, return the corresponding class
   *
   * Split the provided name by `/`, and import the longest working prefix. The
   * remaining components will be treated as attributes off of the import.
   *
   * For example, consider 'some/package/file.js/property/class'. We would
   * traverse this as:
   *
   *  - import 'some/package/file.js/property/class' (failed)
   *  - import 'some/package/file.js/property', get 'class' attribute (failed)
   *  - import 'some/package/file.js', get 'property.class' attribute (success)
   */
  static import(name) {
    const segments = name.split(Path.sep);
    const attributes = [];
    const getter = (obj, key) => obj[key];
    while (segments.length) {
      const joined = segments.join(Path.sep);
      let result = null;
      try {
        logger.debug('Trying to import %s...', joined);
        // eslint-disable-next-line global-require, import/no-dynamic-require
        result = require(joined);
      } catch (err) {
        attributes.push(segments.pop());
      }

      if (result) {
        try {
          logger.debug('Getting attributes [%s] of %s', attributes.join(', '), joined);
          result = attributes.reduce(getter, result);
        } catch (err) {
          break;
        }

        // If there's no such attribute, break out of the loop and throw
        if (!result) break;

        logger.debug('Found "%s"', result.name);
        return result;
      }
    }
    throw Error(`Could not find ${name}`);
  }

  setPriority(priority) {
    return this.client.call('priority', this.jid, priority)
      .then(() => {
        this.priority = priority;
        return this.priority;
      });
  }

  getQueue() {
    return this.client.queue(this.queueName);
  }

  /**
   * Get the class that corresponds to this klassName.
   *
   * A note on security -- abolute paths or those starting with a . are not
   * allowed. By disallowing them, we require that the job must be available in
   * node_modules, which allows for some amount of sandboxing. This, of course,
   * does not preclude the possibility of job code importing arbitrary modules.
   * It merely means that only job modules that have been installed in this
   * environment are available.
   *
   * If the `allowPaths` option is provided, any `require` is accepted.
   */
  getKlass(options) {
    const allowPaths = options && options.allowPaths;
    const name = Path.normalize(this.klassName);
    if (!allowPaths && (name.startsWith('.') || name.startsWith('/'))) {
      throw Error('Absolute and . paths are are not allowed.');
    }
    return Job.import(name);
  }

  cancel() {
    return this.client.call('cancel', this.jid);
  }

  tag() {
    return this.client.call.apply(
      this.client, ['tag', 'add', this.jid].concat(Array.from(arguments)));
  }

  untag() {
    return this.client.call.apply(
      this.client, ['tag', 'remove', this.jid].concat(Array.from(arguments)));
  }

  getTtl() {
    const now = (new Date()).getTime() / 1000.0;
    return this.expiresAt - now;
  }

  /**
   * Process this job.
   *
   * The function that's ultimately called _must_ return a Promise.
   *
   * The function that's called depends on what's available. It will first try to
   * see if there is a method `queueName` on the class itself. Failing that, it
   * will look for a method called 'process' on the class.
   *
   * Options may be provided, which are passed to `getKlass`.
   */
  process(options) {
    return Promise
      .try(() => {
        const klass = this.getKlass(options);
        const method = klass[this.queueName] || klass.process;
        if (method) {
          return method(this);
        } else {
          throw Error(`No method ${this.queueName} or process`);
        }
      })
      .catch((error) => {
        const group = `${this.queueName}-${error.name}`;
        const message = error.stack;
        logger.error('Job %s failed in group %s', this.jid, group, error);
        return this.fail(group, message);
      });
  }

  /**
   * Move this job out of its existing state and into another queue. If a worker
   * has been given this job, then that worker's attempts to heartbeat that job
   * will fail. Like `Queue.put`, this accepts a delay, and dependencies.
   */
  move(queue, options) {
    const opts = {
      jid: this.jid,
      klass: this.klassName,
      data: this.data,
      priority: this.priority,
      delay: (options && options.delay) || 0,
      tags: this.tags,
      retries: this.originalRetries,
      depends: (options && options.depends) || [],
    };
    logger.info('Moving job %s to %s', this.jid, queue);
    return this.client.queue(queue).put(opts);
  }

  complete(next, options) {
    const args = [
      'complete', this.jid, this.client.workerName, this.queueName,
      JSON.stringify(this.data),
    ];
    if (next) {
      args.push(
        'next', next,
        'delay', (options && options.delay) || 0,
        'depends', JSON.stringify((options && options.depends) || []));
      logger.info('Advancing job %s to %s', this.jid, next);
    } else {
      logger.info('Completing job %s', this.jid);
    }
    return this.client.call.apply(this.client, args);
  }

  heartbeat() {
    return this.client
      .call('heartbeat', this.jid, this.client.workerName, JSON.stringify(this.data))
      .then((expiration) => {
        logger.info('Heartbeated job %s, ttl=%s', this.jid, this.getTtl());
        this.expiresAt = expiration;
        return expiration;
      });
  }

  /**
   * Heartbeat as needed, until a promise resolves.
   *
   * Before the job lock is lost, the heartbeat is run. The padding controls how long
   * (in seconds) before the job lock loss to run the heartbeat. The default value is
   * 10, meaning that the heartbeat will run 10 seconds before the lock is set to
   * expire.
   */
  heartbeatUntilPromise(promise, padding) {
    // The promise is wrapped in Bluebird to ensure it adheres to the expected API
    const wrappedPromise = Promise.resolve(promise);
    // Default to 10 seconds
    padding = padding || 10;

    const poll = () => {
      // Heartbeat when `padding` seconds remain (converted to milliseconds)
      const interval = (this.getTtl() - padding) * 1000;
      return wrappedPromise.timeout(interval).catch(() => {
        if (wrappedPromise.isPending()) {
          return this.heartbeat().then(poll);
        }
        return wrappedPromise;
      });
    };

    return poll();
  }

  fail(group, message) {
    logger.info('Failing job %s in group %s', this.jid, group);
    return this.client.call(
      'fail', this.jid, this.client.workerName, group, message, JSON.stringify(this.data));
  }

  track() {
    return this.client.call('track', 'track', this.jid);
  }

  untrack() {
    return this.client.call('track', 'untrack', this.jid);
  }

  /**
   * Retry a job, providing an optional group and message.
   *
   * If provided, the group and message will be used should the retries be
   * exhausted and the job failed as a result. Optionally, a delay may also be
   * provided to implement backoff.
   *
   * Optional:
   *  - group (a string)
   *  - message (a string)
   *  - delay (a number)
   */
  retry(options) {
    options = options || {};
    const args = [
      'retry', this.jid, this.queueName, this.client.workerName, options.delay || 0,
    ];
    if (options.group && options.message) {
      args.push(options.group, options.message);
    }
    logger.info('Retrying job %s', this.jid);
    return this.client.call.apply(this.client, args);
  }

  depend() {
    return this.client.call.apply(
      this.client, ['depends', this.jid, 'on'].concat(Array.from(arguments)));
  }

  undepend() {
    return this.client.call.apply(
      this.client, ['depends', this.jid, 'off'].concat(Array.from(arguments)));
  }

  undependAll() {
    return this.undepend('all');
  }

  timeout() {
    logger.info('Timing out job %s', this.jid);
    return this.client.call('timeout', this.jid);
  }

}

module.exports = Job;
<commit_msg>Passing test about gracefully ignoring failures in job.process<commit_after>'use strict';

const Promise = require('bluebird').Promise;
const Path = require('path');
const logger = require('./logger.js');

class Job {

  constructor(client, config) {
    this.client = client;
    this.config = config;

    // Shared between all Job classes
    this.jid = config.jid;
    this.priority = config.priority;
    this.klassName = config.klass;
    this.queueName = config.queue;
    this.tags = config.tags;
    this.data = JSON.parse(config.data);

    // Specific to non-recurring jobs
    this.state = config.state;
    this.tracked = config.tracked;
    this.failure = config.failure;
    this.history = config.history;
    this.dependents = config.dependents;
    this.dependencies = config.dependencies;
    this.expiresAt = config.expires;
    this.originalRetries = config.retries;
    this.retriesLeft = config.remaining;
    this.workerName = config.worker;
  }

  /**
   * Given a string name of a class, return the corresponding class
   *
   * Split the provided name by `/`, and import the longest working prefix. The
   * remaining components will be treated as attributes off of the import.
   *
   * For example, consider 'some/package/file.js/property/class'. We would
   * traverse this as:
   *
   *  - import 'some/package/file.js/property/class' (failed)
   *  - import 'some/package/file.js/property', get 'class' attribute (failed)
   *  - import 'some/package/file.js', get 'property.class' attribute (success)
   */
  static import(name) {
    const segments = name.split(Path.sep);
    const attributes = [];
    const getter = (obj, key) => obj[key];
    while (segments.length) {
      const joined = segments.join(Path.sep);
      let result = null;
      try {
        logger.debug('Trying to import %s...', joined);
        // eslint-disable-next-line global-require, import/no-dynamic-require
        result = require(joined);
      } catch (err) {
        attributes.push(segments.pop());
      }

      if (result) {
        try {
          logger.debug('Getting attributes [%s] of %s', attributes.join(', '), joined);
          result = attributes.reduce(getter, result);
        } catch (err) {
          break;
        }

        // If there's no such attribute, break out of the loop and throw
        if (!result) break;

        logger.debug('Found "%s"', result.name);
        return result;
      }
    }
    throw Error(`Could not find ${name}`);
  }

  setPriority(priority) {
    return this.client.call('priority', this.jid, priority)
      .then(() => {
        this.priority = priority;
        return this.priority;
      });
  }

  getQueue() {
    return this.client.queue(this.queueName);
  }

  /**
   * Get the class that corresponds to this klassName.
   *
   * A note on security -- abolute paths or those starting with a . are not
   * allowed. By disallowing them, we require that the job must be available in
   * node_modules, which allows for some amount of sandboxing. This, of course,
   * does not preclude the possibility of job code importing arbitrary modules.
   * It merely means that only job modules that have been installed in this
   * environment are available.
   *
   * If the `allowPaths` option is provided, any `require` is accepted.
   */
  getKlass(options) {
    const allowPaths = options && options.allowPaths;
    const name = Path.normalize(this.klassName);
    if (!allowPaths && (name.startsWith('.') || name.startsWith('/'))) {
      throw Error('Absolute and . paths are are not allowed.');
    }
    return Job.import(name);
  }

  cancel() {
    return this.client.call('cancel', this.jid);
  }

  tag() {
    return this.client.call.apply(
      this.client, ['tag', 'add', this.jid].concat(Array.from(arguments)));
  }

  untag() {
    return this.client.call.apply(
      this.client, ['tag', 'remove', this.jid].concat(Array.from(arguments)));
  }

  getTtl() {
    const now = (new Date()).getTime() / 1000.0;
    return this.expiresAt - now;
  }

  /**
   * Process this job.
   *
   * The function that's ultimately called _must_ return a Promise.
   *
   * The function that's called depends on what's available. It will first try to
   * see if there is a method `queueName` on the class itself. Failing that, it
   * will look for a method called 'process' on the class.
   *
   * Options may be provided, which are passed to `getKlass`.
   */
  process(options) {
    return Promise
      .try(() => {
        const klass = this.getKlass(options);
        const method = klass[this.queueName] || klass.process;
        if (method) {
          return method(this);
        } else {
          throw Error(`No method ${this.queueName} or process`);
        }
      })
      .catch((error) => {
        const group = `${this.queueName}-${error.name}`;
        const message = error.stack;
        logger.error('Job %s failed in group %s', this.jid, group, error);
        return this.fail(group, message);
      })
      .catch(error => logger.error('Failed to fail job %s', this.jid, error));
  }

  /**
   * Move this job out of its existing state and into another queue. If a worker
   * has been given this job, then that worker's attempts to heartbeat that job
   * will fail. Like `Queue.put`, this accepts a delay, and dependencies.
   */
  move(queue, options) {
    const opts = {
      jid: this.jid,
      klass: this.klassName,
      data: this.data,
      priority: this.priority,
      delay: (options && options.delay) || 0,
      tags: this.tags,
      retries: this.originalRetries,
      depends: (options && options.depends) || [],
    };
    logger.info('Moving job %s to %s', this.jid, queue);
    return this.client.queue(queue).put(opts);
  }

  complete(next, options) {
    const args = [
      'complete', this.jid, this.client.workerName, this.queueName,
      JSON.stringify(this.data),
    ];
    if (next) {
      args.push(
        'next', next,
        'delay', (options && options.delay) || 0,
        'depends', JSON.stringify((options && options.depends) || []));
      logger.info('Advancing job %s to %s', this.jid, next);
    } else {
      logger.info('Completing job %s', this.jid);
    }
    return this.client.call.apply(this.client, args);
  }

  heartbeat() {
    return this.client
      .call('heartbeat', this.jid, this.client.workerName, JSON.stringify(this.data))
      .then((expiration) => {
        logger.info('Heartbeated job %s, ttl=%s', this.jid, this.getTtl());
        this.expiresAt = expiration;
        return expiration;
      });
  }

  /**
   * Heartbeat as needed, until a promise resolves.
   *
   * Before the job lock is lost, the heartbeat is run. The padding controls how long
   * (in seconds) before the job lock loss to run the heartbeat. The default value is
   * 10, meaning that the heartbeat will run 10 seconds before the lock is set to
   * expire.
   */
  heartbeatUntilPromise(promise, padding) {
    // The promise is wrapped in Bluebird to ensure it adheres to the expected API
    const wrappedPromise = Promise.resolve(promise);
    // Default to 10 seconds
    padding = padding || 10;

    const poll = () => {
      // Heartbeat when `padding` seconds remain (converted to milliseconds)
      const interval = (this.getTtl() - padding) * 1000;
      return wrappedPromise.timeout(interval).catch(() => {
        if (wrappedPromise.isPending()) {
          return this.heartbeat().then(poll);
        }
        return wrappedPromise;
      });
    };

    return poll();
  }

  fail(group, message) {
    logger.info('Failing job %s in group %s', this.jid, group);
    return this.client.call(
      'fail', this.jid, this.client.workerName, group, message, JSON.stringify(this.data));
  }

  track() {
    return this.client.call('track', 'track', this.jid);
  }

  untrack() {
    return this.client.call('track', 'untrack', this.jid);
  }

  /**
   * Retry a job, providing an optional group and message.
   *
   * If provided, the group and message will be used should the retries be
   * exhausted and the job failed as a result. Optionally, a delay may also be
   * provided to implement backoff.
   *
   * Optional:
   *  - group (a string)
   *  - message (a string)
   *  - delay (a number)
   */
  retry(options) {
    options = options || {};
    const args = [
      'retry', this.jid, this.queueName, this.client.workerName, options.delay || 0,
    ];
    if (options.group && options.message) {
      args.push(options.group, options.message);
    }
    logger.info('Retrying job %s', this.jid);
    return this.client.call.apply(this.client, args);
  }

  depend() {
    return this.client.call.apply(
      this.client, ['depends', this.jid, 'on'].concat(Array.from(arguments)));
  }

  undepend() {
    return this.client.call.apply(
      this.client, ['depends', this.jid, 'off'].concat(Array.from(arguments)));
  }

  undependAll() {
    return this.undepend('all');
  }

  timeout() {
    logger.info('Timing out job %s', this.jid);
    return this.client.call('timeout', this.jid);
  }

}

module.exports = Job;
<|endoftext|>


<commit_before>import { Model } from 'common';
import { isUndefined } from 'underscore';

export default class Trait extends Model {
  initialize() {
    const { target, name, changeProp } = this.attributes;
    !this.get('id') && this.set('id', name);

    if (target) {
      this.target = target;
      this.unset('target');
      const targetEvent = changeProp ? `change:${name}` : `change:attributes:${name}`;
      this.listenTo(target, targetEvent, this.targetUpdated);
    }
  }

  /**
   * Get trait id.
   * @returns {String}
   */
  getId() {
    return this.get('id');
  }

  /**
   * Get the trait type.
   * @returns {String}
   */
  getType() {
    return this.get('type');
  }

  /**
   * Get trait name.
   * @returns {String}
   */
  getName() {
    return this.get('name');
  }

  /**
   * Get trait label.
   * @param {Object} [opts={}] Options
   * @param {Boolean} [opts.locale=true] Use the locale string from i18n module
   * @returns {String}
   */
  getLabel(opts = {}) {
    const { locale = true } = opts;
    const id = this.getId();
    const name = this.get('label') || this.getName();
    return (locale && this.em?.t(`traitManager.traits.labels.${id}`)) || name;
  }

  setValue(value, opts = {}) {
    const valueOpts = {};

    if (opts.partial) {
      valueOpts.avoidStore = true;
    }

    this.setTargetValue(value, valueOpts);

    if (opts.partial === false) {
      this.setTargetValue('');
      this.setTargetValue(value);
    }
  }

  props() {
    return this.attributes;
  }

  targetUpdated() {
    const value = this.getTargetValue();
    this.set({ value }, { fromTarget: 1 });
    this.em?.trigger('trait:update', {
      trait: this,
      component: this.target,
    });
  }

  getValue() {
    return this.getTargetValue();
  }

  getTargetValue() {
    const name = this.get('name');
    const target = this.target;
    let value;

    if (this.get('changeProp')) {
      value = target.get(name);
    } else {
      value = target.getAttributes()[name];
    }

    return !isUndefined(value) ? value : '';
  }

  setTargetValue(value, opts = {}) {
    const target = this.target;
    const name = this.get('name');
    if (isUndefined(value)) return;
    let valueToSet = value;

    if (value === 'false') {
      valueToSet = false;
    } else if (value === 'true') {
      valueToSet = true;
    }

    if (this.get('changeProp')) {
      target.set(name, valueToSet, opts);
    } else {
      const attrs = { ...target.get('attributes') };
      attrs[name] = valueToSet;
      target.set('attributes', attrs, opts);
    }
  }

  setValueFromInput(value, final = 1, opts = {}) {
    const toSet = { value };
    this.set(toSet, { ...opts, avoidStore: 1 });

    // Have to trigger the change
    if (final) {
      this.set('value', '', opts);
      this.set(toSet, opts);
    }
  }

  getInitValue() {
    const target = this.target;
    const name = this.get('name');
    let value;

    if (target) {
      const attrs = target.get('attributes');
      value = this.get('changeProp') ? target.get(name) : attrs[name];
    }

    return value || this.get('value') || this.get('default');
  }
}

Trait.prototype.defaults = {
  type: 'text', // text, number, range, select
  label: '',
  name: '',
  min: '',
  max: '',
  unit: '',
  step: 1,
  value: '',
  target: '',
  default: '',
  placeholder: '',
  changeProp: 0,
  options: [],
};
<commit_msg>Update Trait doc<commit_after>import { Model } from 'common';
import { isUndefined } from 'underscore';

/**
 * @typedef Trait
 * @property {String} id Trait id, eg. `my-trait-id`.
 * @property {String} type Trait type, defines how the trait should rendered. Possible values: `text` (default), `number`, `select`, `checkbox`, `color`, `button`
 * @property {String} label The trait label to show for the rendered trait.
 * @property {String} name The name of the trait used as a key for the attribute/property. By default, the name is used as attribute name or property in case `changeProp` in enabled.
 * @property {Boolean} changeProp If `true` the trait value is applied on component
 *
 */
export default class Trait extends Model {
  initialize() {
    const { target, name, changeProp } = this.attributes;
    !this.get('id') && this.set('id', name);

    if (target) {
      this.target = target;
      this.unset('target');
      const targetEvent = changeProp ? `change:${name}` : `change:attributes:${name}`;
      this.listenTo(target, targetEvent, this.targetUpdated);
    }
  }

  /**
   * Get the trait id.
   * @returns {String}
   */
  getId() {
    return this.get('id');
  }

  /**
   * Get the trait type.
   * @returns {String}
   */
  getType() {
    return this.get('type');
  }

  /**
   * Get the trait name.
   * @returns {String}
   */
  getName() {
    return this.get('name');
  }

  /**
   * Get the trait label.
   * @param {Object} [opts={}] Options.
   * @param {Boolean} [opts.locale=true] Use the locale string from i18n module.
   * @returns {String}
   */
  getLabel(opts = {}) {
    const { locale = true } = opts;
    const id = this.getId();
    const name = this.get('label') || this.getName();
    return (locale && this.em?.t(`traitManager.traits.labels.${id}`)) || name;
  }

  /**
   * Get the trait value.
   * The value is taken from component attributes by default or from properties if the trait has the `changeProp` enabled.
   * @returns {any}
   */
  getValue() {
    return this.getTargetValue();
  }

  /**
   * Update the trait value.
   * The value is applied on component attributes by default or on properties if the trait has the `changeProp` enabled.
   * @param {any} value Value of the trait.
   * @param {Object} [opts={}] Options.
   * @param {Boolean} [opts.partial] If `true` the update won't be considered complete (not stored in UndoManager).
   */
  setValue(value, opts = {}) {
    const valueOpts = {};

    if (opts.partial) {
      valueOpts.avoidStore = true;
    }

    this.setTargetValue(value, valueOpts);

    if (opts.partial === false) {
      this.setTargetValue('');
      this.setTargetValue(value);
    }
  }

  props() {
    return this.attributes;
  }

  targetUpdated() {
    const value = this.getTargetValue();
    this.set({ value }, { fromTarget: 1 });
    this.em?.trigger('trait:update', {
      trait: this,
      component: this.target,
    });
  }

  getTargetValue() {
    const name = this.get('name');
    const target = this.target;
    let value;

    if (this.get('changeProp')) {
      value = target.get(name);
    } else {
      value = target.getAttributes()[name];
    }

    return !isUndefined(value) ? value : '';
  }

  setTargetValue(value, opts = {}) {
    const target = this.target;
    const name = this.get('name');
    if (isUndefined(value)) return;
    let valueToSet = value;

    if (value === 'false') {
      valueToSet = false;
    } else if (value === 'true') {
      valueToSet = true;
    }

    if (this.get('changeProp')) {
      target.set(name, valueToSet, opts);
    } else {
      const attrs = { ...target.get('attributes') };
      attrs[name] = valueToSet;
      target.set('attributes', attrs, opts);
    }
  }

  setValueFromInput(value, final = 1, opts = {}) {
    const toSet = { value };
    this.set(toSet, { ...opts, avoidStore: 1 });

    // Have to trigger the change
    if (final) {
      this.set('value', '', opts);
      this.set(toSet, opts);
    }
  }

  getInitValue() {
    const target = this.target;
    const name = this.get('name');
    let value;

    if (target) {
      const attrs = target.get('attributes');
      value = this.get('changeProp') ? target.get(name) : attrs[name];
    }

    return value || this.get('value') || this.get('default');
  }
}

Trait.prototype.defaults = {
  type: 'text',
  label: '',
  name: '',
  min: '',
  max: '',
  unit: '',
  step: 1,
  value: '',
  target: '',
  default: '',
  placeholder: '',
  changeProp: 0,
  options: [],
};
<|endoftext|>


<commit_before>/* javascript wrapper for inchi */

(function () {
    'use strict';

    var inchiLib = require('../build/Release/libinchi.node');

    /**
     * this is the higher-level javascript wrapper
     *
     * @module InChI
     * @class  InChI
     */

    exports.version = function () {
        return {
            wrapperVersion: '0.0.2pre',
            algorithmVersion: inchiLib.getAlgorithmVersion(),
            libraryVersion: '1.04'
        };
    };

}());
<commit_msg>make inchilib public<commit_after>/* javascript wrapper for inchi */

(function () {
    'use strict';

    var inchilib = require('../build/Release/libinchi.node');
    exports.inchilib = inchilib;

    /**
     * High-level javascript wrapper of InChI API
     *
     * @module InChI
     * @class  InChI
     */

    exports.version = function () {
        return {
            wrapperVersion: '0.0.2pre',
            algorithmVersion: inchilib.getAlgorithmVersion(),
            libraryVersion: '1.04'
        };
    };

}());
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import config from './../../../../env/client.js';

class FileUpload extends Component {
  componentDidMount() {
    const Dropzone = window.Dropzone;
    const dropzone = new Dropzone('#dropzone', { url: `${config.GOBBLE_API_URL}/api/media` });
    dropzone.on('success', (err, res) => {
      // console.log(`image name: ${res}`);
      this.props.handleFile(res);
    });
  }

  render() {
    return (

    );
  }
}

FileUpload.propTypes = {
  handleFile: React.PropTypes.func,
};

export default FileUpload;
<commit_msg>files uploaded to right server<commit_after>import React, { Component } from 'react';
import config from './../../../../env/client.js';

class FileUpload extends Component {
  componentDidMount() {
    const Dropzone = window.Dropzone;
    const dropzone = new Dropzone('#dropzone', { url: `${config.GOBBLE_MEDIA_URL}/api/media` });
    dropzone.on('success', (err, res) => {
      // console.log(`image name: ${res}`);
      this.props.handleFile(res);
    });
  }

  render() {
    return (

    );
  }
}

FileUpload.propTypes = {
  handleFile: React.PropTypes.func,
};

export default FileUpload;
<|endoftext|>


<commit_before>// https://leetcode.com/problems/merge-sorted-array/#/description

/**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function (nums1, m, nums2, n) {
  var len = m + n - 1;
  var nums1Flag = m - 1;
  var nums2Flag = n - 1;
  while (nums1Flag >= 0 && nums2Flag >= 0) {
    if (nums1[nums1Flag] !== undefined && nums1[nums1Flag] > nums2[nums2Flag]) {
      nums1[len] = nums1[nums1Flag];
      nums1[nums1Flag] = undefined;
      nums1Flag--;
    } else {
      nums1[len] = nums2[nums2Flag];
      nums2Flag--;
    }
    len--;
  }
  while (nums1Flag >= 0) {
    nums1[len] = nums1[nums1Flag];
    nums1Flag--;
    len--;
  }
  while (nums2Flag >= 0) {
    nums1[len] = nums2[nums2Flag];
    nums2Flag--;
    len--;
  }
};

var nums1 = [1, 3, 5, 7];
var nums2 = [0, 2, 6];
merge(nums1, 4, nums2, 3);
console.log(nums1);

nums1 = [-1, 3, 5, 7];
nums2 = [-1, 3, 6, 8, 9];
merge(nums1, 4, nums2, 5);
console.log(nums1);
<commit_msg>Improve Merge Sorted Array<commit_after>// https://leetcode.com/problems/merge-sorted-array/#/description

/**
 * @param {number[]} nums1
 * @param {number} m
 * @param {number[]} nums2
 * @param {number} n
 * @return {void} Do not return anything, modify nums1 in-place instead.
 */
var merge = function (nums1, m, nums2, n) {
  var len = m + n - 1;
  var nums1Flag = m - 1;
  var nums2Flag = n - 1;
  while (nums1Flag >= 0 && nums2Flag >= 0) {
    if (nums1[nums1Flag] !== undefined && nums1[nums1Flag] > nums2[nums2Flag]) {
      nums1[len] = nums1[nums1Flag];
      nums1[nums1Flag] = undefined;
      nums1Flag--;
    } else {
      nums1[len] = nums2[nums2Flag];
      nums2Flag--;
    }
    len--;
  }
  while (nums1Flag >= 0) {
    nums1[len] = nums1[nums1Flag];
    nums1Flag--;
    len--;
  }
  while (nums2Flag >= 0) {
    nums1[len] = nums2[nums2Flag];
    nums2Flag--;
    len--;
  }
};

var merge2 = function (nums1, m, nums2, n) {
  nums1.length = m;
  nums2.length = n;

  Array.prototype.push.apply(nums1, nums2);
  nums1.sort(function (a, b) {
    return a - b;
  });
}

var nums1 = [1, 3, 5, 7];
var nums2 = [0, 2, 6];
merge(nums1, 4, nums2, 3);
console.log(nums1);

nums1 = [-1, 3, 5, 7];
nums2 = [-1, 3, 6, 8, 9];
merge(nums1, 4, nums2, 5);
console.log(nums1);
<|endoftext|>


<commit_before>'use strict'

var cp = require('child_process')
var fs = require('fs')
var http = require('http')
var https = require('https')
var path = require('path')
var url = require('url')
var rimraf = require('rimraf').sync
var AdmZip = require('adm-zip')

fs.existsSync = fs.existsSync || path.existsSync

var libPath = path.join(__dirname, 'lib', 'casperjs')
var tmpPath = path.join(__dirname, 'tmp')
var downloadUrl = 'https://github.com/n1k0/casperjs/archive/1.0.3.zip'

function tidyUp() {
    rimraf(tmpPath);
}

function unzipTheZippedFile() {
    var zip = new AdmZip(path.join(tmpPath, 'archive.zip'));
    zip.extractAllTo(libPath, true);

    if (process.platform != 'win32') {
        var pathToCommand = path.join(libPath, 'casperjs-1.0.3', 'bin', 'casperjs');
        var stat = fs.statSync(pathToCommand)
        if (!(stat.mode & 64)) {
            fs.chmodSync(pathToCommand, '755')
        }
    }
    tidyUp();
}

function downloadZipFromGithub() {
    var file = fs.createWriteStream(path.join(tmpPath, "archive.zip"));
    var lengthSoFar = 0;
    var request = https.get(downloadUrl, function(response) {
        if (response.statusCode === 301 || response.statusCode === 302) {
            downloadUrl = response.headers.location;
            downloadZipFromGithub();
        } else {
            response.pipe(file);
            response.on('data', function(chunk) {
               console.log('Receiving ' + Math.floor((lengthSoFar += chunk.length) / 1024) + 'K...' );
            }).
            on('end', unzipTheZippedFile).
            on('error', function(e) {
                console.log('An error occured whilst trying to download Casper.JS ' + e.message);
                tidyUp();
            });
        }
    });
    request.on('error', function(e) {
        console.log('An error occured whilst trying to download Casper.JS ' + e.message);
        tidyUp();
    });
}

if (!fs.existsSync(tmpPath)) {
    fs.mkdirSync(tmpPath);
}
rimraf(libPath);

downloadZipFromGithub();
<commit_msg>Adding check for prior casperjs installations before installing 1.0.3<commit_after>'use strict'

var cp = require('child_process')
var fs = require('fs')
var http = require('http')
var https = require('https')
var path = require('path')
var url = require('url')
var rimraf = require('rimraf').sync
var AdmZip = require('adm-zip')

fs.existsSync = fs.existsSync || path.existsSync

var libPath = path.join(__dirname, 'lib', 'casperjs')
var tmpPath = path.join(__dirname, 'tmp')
var downloadUrl = 'https://github.com/n1k0/casperjs/archive/1.0.3.zip'

function isCasperInstalled(notInstalledCallback) {
    cp.exec("casperjs --version", function(error, stdout, stderr) {
        if ( error || stderr || !stdout.length ) {
            console.log("Casperjs not installed.  Installing.");
            notInstalledCallback();
        } else {
            console.log("Casperjs already installed: " + stdout);
        }
    });
}

function tidyUp() {
    rimraf(tmpPath);
}

function unzipTheZippedFile() {
    var zip = new AdmZip(path.join(tmpPath, 'archive.zip'));
    zip.extractAllTo(libPath, true);

    if (process.platform != 'win32') {
        var pathToCommand = path.join(libPath, 'casperjs-1.0.3', 'bin', 'casperjs');
        var stat = fs.statSync(pathToCommand)
        if (!(stat.mode & 64)) {
            fs.chmodSync(pathToCommand, '755')
        }
    }
    tidyUp();
}

function downloadZipFromGithub() {
    var file = fs.createWriteStream(path.join(tmpPath, "archive.zip"));
    var lengthSoFar = 0;
    var request = https.get(downloadUrl, function(response) {
        if (response.statusCode === 301 || response.statusCode === 302) {
            downloadUrl = response.headers.location;
            downloadZipFromGithub();
        } else {
            response.pipe(file);
            response.on('data', function(chunk) {
                console.log('Receiving ' + Math.floor((lengthSoFar += chunk.length) / 1024) + 'K...' );
            }).
                on('end', unzipTheZippedFile).
                on('error', function(e) {
                    console.log('An error occured whilst trying to download Casper.JS ' + e.message);
                    tidyUp();
                });
        }
    });
    request.on('error', function(e) {
        console.log('An error occured whilst trying to download Casper.JS ' + e.message);
        tidyUp();
    });
}

isCasperInstalled(function() {
    if (!fs.existsSync(tmpPath)) {
        fs.mkdirSync(tmpPath);
    }
    rimraf(libPath);

    downloadZipFromGithub();
});<|endoftext|>


<commit_before>/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global require, yo, define, brackets: true, $, jQuery, window, document, navigator*/

/**************
 *   @author : Ajain Vivek
 *   @desc : Yo.js - Templating Utility Library
 *   @license : MIT Licensed
 ***************/

(function (w, doc, un) {
    "use strict";

    window.yo.utils = window.yo.utils || {};

    yo.utils.template = yo.utils.template || {};

    var baseURL = "";

    //Set the base URL for template class
    var setBaseURL = function (url) {
        baseURL = url;
    };

    //Get the base URL
    var getBaseURL = function () {
        return baseURL;
    };

    //Cache the dom reference
    var cachedDOM = function (uid, root, ele, template) {

        var cacheObj = {
            uid: uid,
            ele: ele,
            template: template
        };

        var cacheId = cacheObj.uid;
        var setCache = true;
        var i;

        cachedDOM.cache = cachedDOM.cache || {};

        if (cachedDOM.cache[root] === null || cachedDOM.cache[root] === undefined) {
            cachedDOM.cache[root] = [];
        } else {
            for (i = 0; i < cachedDOM.cache[root].length; i++) {
                if (cachedDOM.cache[root][i].ele === ele) {
                    cacheId = cachedDOM.cache[root][i].uid;
                    setCache = false;
                }
            }
        }

        if (setCache) {
            cachedDOM.cache[root].push(cacheObj);
        }

        return {
            uid : cacheId
        };
    };

    //Fetch the HTML Template
    var fetchHTML = function (fileRef) {
        var ele = "";
        var url = baseURL + fileRef;
        $.ajax({
            url: url,
            type: 'get',
            dataType: 'html',
            async: false,
            cache: false,
            success: function (html) {
                ele = html;
            },
            fail: function () {
                console.error("Error: source not found");
            }
        });

        return ele;
    };

    //Map the string with curly braces
    var getValues = function (str) {
        var vals = [], // an array to collect the strings that are found
            rxp = new RegExp("{([^}]+)}", "g"),
            curMatch;

        while ((curMatch = rxp.exec(str)) !== null) {
            vals.push(curMatch[1]);
        }

        return vals;
    };

    //Add the element on to the dom
    var add = function (options, callback) {

        var defaults = {
            root: options.root || "body",
            ele: options.ele || "",
            template: options.template || "",
            animate: options.animate || "slide",
            mode: options.mode || "append",
            data: options.data || {}
        };

        var uid = (new Date()).getTime();

        var keys = Object.keys(defaults.data);
        var html = fetchHTML(defaults.template);
        var template = html;
        var arrValues = getValues(html);
        var i, j;

        var cacheDOM = cachedDOM(uid, defaults.root, defaults.ele, defaults.template);

        //Set the data value for dom element
        for (i = 0; i < arrValues.length; i++) {
            for (j = 0; j < keys.length; j++) {
                if (arrValues[i] === keys[j]) {
                    html = html.replace("{" + keys[j] + "}", defaults.data[keys[j]]);
                }
            }
        }

        //Remove Hidden Element if it exists in the DOM
        $("#templateBuilder").remove();

        var hiddenEle = $("body").append("

");
        var ele = "";

        if (defaults.ele.charAt(0) === "#" || defaults.ele.charAt(0) === ".") {
            ele = $("#templateBuilder").html(html).find(defaults.ele); //Insert into the dom
            ele.first().attr("uid", cacheDOM.uid);
        } else {
            console.error("Error: Incorrect reference - pass class or id only.");
        }

        if (defaults.mode === "insert") {
            $(defaults.root).html(ele);
        } else {
            $(defaults.root).append(ele);
        }

        if (typeof callback === "function") {
            callback(); // Execute callback function
        }

        return {
            uid: cacheDOM.uid,
            template: defaults.template
        };

    };

    //Get cached data
    var cache = function () {
        return cachedDOM.cache;
    };

    //Remove from the dom but will not be removed from cache
    var remove = function (options, callback) {

        var defaults = {
            root: options.root || "body",
            ele: options.ele || "",
            uid: options.uid || "",
            animate: options.animate || "slide"
        };
        var i, j;
        var cachedDom = cache();
        var keys = Object.keys(cachedDom);

        if (defaults.uid !== "") {
            for (i = 0; i < keys.length; i++) {
                for (j = 0; j < cachedDom[keys[i]].length; j++) {
                    if (defaults.uid === cachedDom[keys[i]][j].uid) {
                        $(keys[i]).find("[uid='" + defaults.uid + "']").remove();
                        break;
                    }
                }
            }

        } else {
            if (defaults.ele.charAt(0) === "#" || defaults.ele.charAt(0) === ".") {
                $(defaults.ele).remove();
            }
        }

    };

    //Destroy the element from dom
    var destroy = function (options, callback) {

        var defaults = {
            root: options.root || "body",
            ele: options.ele || "",
            uid: options.uid || "",
            animate: options.animate || "slide"
        };

        var i, j;
        var cachedDom = cache();
        var keys = Object.keys(cachedDom);

        if (defaults.uid !== "") {
            for (i = 0; i < keys.length; i++) {
                for (j = 0; j < cachedDom[keys[i]].length; j++) {
                    if (defaults.uid === cachedDom[keys[i]][j].uid) {
                        $(keys[i]).find("[uid='" + defaults.uid + "']").remove();
                        cachedDom[keys[i]].splice(j, 1); //Remove from cache
                        break;
                    }
                }
            }

        } else {
            if (defaults.ele.charAt(0) === "#" || defaults.ele.charAt(0) === ".") {

                for (i = 0; i < keys.length; i++) {
                    for (j = 0; j < cachedDom[keys[i]].length; j++) {
                        if (defaults.ele === cachedDom[keys[i]][j].ele) {
                            cachedDom[keys[i]].splice(j, 1); //Remove from cache
                        }
                    }
                }

                $(defaults.ele).remove();

            } else {
                console.error("Error: Incorrect reference - pass class or id only.");
            }
        }

    };

    yo.utils.template = {
        add: add,
        remove: remove,
        destroy: destroy,
        cache: cache,
        setBaseURL: setBaseURL,
        getBaseURL: getBaseURL
    };

    return yo.utils.template;

}(window, document, undefined));<commit_msg>Template Utility : Supports array of templates<commit_after>/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global require, yo, define, brackets: true, $, jQuery, window, document, navigator*/

/**************
 *   @author : Ajain Vivek
 *   @desc : Yo.js - Templating Utility Library
 *   @license : MIT Licensed
 ***************/

(function (w, doc, un) {
    "use strict";

    window.yo.utils = window.yo.utils || {};

    yo.utils.template = yo.utils.template || {};

    var baseURL = "";

    //Set the base URL for template class
    var setBaseURL = function (url) {
        baseURL = url;
    };

    //Get the base URL
    var getBaseURL = function () {
        return baseURL;
    };

    //Cache the dom reference
    var cachedDOM = function (uid, root, ele, template) {

        var cacheObj = {
            uid: uid,
            ele: ele,
            template: template
        };

        var cacheId = cacheObj.uid;
        var setCache = true;
        var i;

        cachedDOM.cache = cachedDOM.cache || {};

        if (cachedDOM.cache[root] === null || cachedDOM.cache[root] === undefined) {
            cachedDOM.cache[root] = [];
        } else {
            for (i = 0; i < cachedDOM.cache[root].length; i++) {
                if (cachedDOM.cache[root][i].ele === ele) {
                    cacheId = cachedDOM.cache[root][i].uid;
                    setCache = false;
                }
            }
        }

        if (setCache) {
            cachedDOM.cache[root].push(cacheObj);
        }

        return {
            uid : cacheId
        };
    };

    //Fetch the HTML Template
    var fetchHTML = function (fileRef) {
        var ele = "";
        var url = baseURL + fileRef;
        $.ajax({
            url: url,
            type: 'get',
            dataType: 'html',
            async: false,
            cache: false,
            success: function (html) {
                ele = html;
            },
            fail: function () {
                console.error("Error: source not found");
            }
        });

        return ele;
    };

    //Map the string with curly braces
    var getValues = function (str) {
        var vals = [], // an array to collect the strings that are found
            rxp = new RegExp("{([^}]+)}", "g"),
            curMatch;

        while ((curMatch = rxp.exec(str)) !== null) {
            vals.push(curMatch[1]);
        }

        return vals;
    };

    //Add the element on to the dom
    var add = function (options, callback) {

        var defaults = {
            root: options.root || "body",
            ele: options.ele || "",
            template: options.template || "",
            animate: options.animate || "slide",
            mode: options.mode || "append",
            data: options.data || {}
        };

        var uid = (new Date()).getTime();

        var keys = Object.keys(defaults.data);
        var html = fetchHTML(defaults.template);
        var template = html;
        var arrValues = getValues(html);
        var i, j;

        var cacheDOM = cachedDOM(uid, defaults.root, defaults.ele, defaults.template);

        //Set the data value for dom element
        for (i = 0; i < arrValues.length; i++) {
            for (j = 0; j < keys.length; j++) {
                if (arrValues[i] === keys[j]) {
                    html = html.replace("{" + keys[j] + "}", defaults.data[keys[j]]);
                }
            }
        }

        //Remove Hidden Element if it exists in the DOM
        $("#templateBuilder").remove();

        var hiddenEle = $("body").append("

");
        var ele = [];
        var arrEl = [];

        if (defaults.ele instanceof Array) {
            for (i = 0; i < defaults.ele.length; i++) {
                if (defaults.ele[i].charAt(0) === "#" || defaults.ele[i].charAt(0) === ".") {
                    arrEl = $("#templateBuilder").html(html).find(defaults.ele[i]); //Insert into the dom
                    arrEl.first().attr("uid", cacheDOM.uid);
                    ele.push(arrEl[0]);
                } else {
                    console.error("Error: Incorrect reference - pass class or id only.");
                }
            }
        } else {
            if (defaults.ele.charAt(0) === "#" || defaults.ele.charAt(0) === ".") {
                ele = $("#templateBuilder").html(html).find(defaults.ele); //Insert into the dom
                ele.first().attr("uid", cacheDOM.uid);
            } else {
                console.error("Error: Incorrect reference - pass class or id only.");
            }
        }

        if (defaults.mode === "insert") {
            $(defaults.root).html(ele);
        } else {
            $(defaults.root).append(ele);
        }

        var oRef = {
            uid: cacheDOM.uid,
            template: defaults.template,
            ele: defaults.ele
        };

        if (typeof callback === "function") {
            callback(oRef); // Execute callback function
        }

        return oRef;

    };

    //Get cached data
    var cache = function () {
        return cachedDOM.cache;
    };

    //Remove from the dom but will not be removed from cache
    var remove = function (options, callback) {

        var defaults = {
            root: options.root || "body",
            ele: options.ele || "",
            uid: options.uid || "",
            animate: options.animate || "slide"
        };
        var i, j;
        var cachedDom = cache();
        var keys = Object.keys(cachedDom);

        if (defaults.uid !== "") {
            for (i = 0; i < keys.length; i++) {
                for (j = 0; j < cachedDom[keys[i]].length; j++) {
                    if (defaults.uid === cachedDom[keys[i]][j].uid) {
                        $(keys[i]).find("[uid='" + defaults.uid + "']").remove();
                        break;
                    }
                }
            }

        } else {
            if (defaults.ele.charAt(0) === "#" || defaults.ele.charAt(0) === ".") {
                $(defaults.ele).remove();
            }
        }

    };

    //Destroy the element from dom
    var destroy = function (options, callback) {

        var defaults = {
            root: options.root || "body",
            ele: options.ele || "",
            uid: options.uid || "",
            animate: options.animate || "slide"
        };

        var i, j;
        var cachedDom = cache();
        var keys = Object.keys(cachedDom);

        if (defaults.uid !== "") {
            for (i = 0; i < keys.length; i++) {
                for (j = 0; j < cachedDom[keys[i]].length; j++) {
                    if (defaults.uid === cachedDom[keys[i]][j].uid) {
                        $(keys[i]).find("[uid='" + defaults.uid + "']").remove();
                        cachedDom[keys[i]].splice(j, 1); //Remove from cache
                        break;
                    }
                }
            }

        } else {
            if (defaults.ele.charAt(0) === "#" || defaults.ele.charAt(0) === ".") {

                for (i = 0; i < keys.length; i++) {
                    for (j = 0; j < cachedDom[keys[i]].length; j++) {
                        if (defaults.ele === cachedDom[keys[i]][j].ele) {
                            cachedDom[keys[i]].splice(j, 1); //Remove from cache
                        }
                    }
                }

                $(defaults.ele).remove();

            } else {
                console.error("Error: Incorrect reference - pass class or id only.");
            }
        }

    };

    yo.utils.template = {
        add: add,
        remove: remove,
        destroy: destroy,
        cache: cache,
        setBaseURL: setBaseURL,
        getBaseURL: getBaseURL
    };

    return yo.utils.template;

}(window, document, undefined));<|endoftext|>


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

'use strict';

function LCG(seed) {
    var self = this;
    if (typeof seed === 'number') {
        self.last = seed;
    } else {
        self.last = Math.floor(Math.pow(2, 32) * Math.random());
    }
    self.mod = Math.pow(2, 32);
    self.mul = 214013;
    self.add = 253101;
}

LCG.prototype.rand = function rand() {
    var self = this;
    self.last = (self.mul * self.last + self.add) % self.mod;
    return self.last;
};

LCG.prototype.rand64 = function rand64() {
    var self = this;
    var ret = new Buffer(8);
    ret.writeUInt32BE(self.rand(), 0);
    ret.writeUInt32BE(self.rand(), 4);
    return ret;
};

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

'use strict';

var Buffer = require('buffer').Buffer;

function LCG(seed) {
    var self = this;
    if (typeof seed === 'number') {
        self.last = seed;
    } else {
        self.last = Math.floor(Math.pow(2, 32) * Math.random());
    }
    self.mod = Math.pow(2, 32);
    self.mul = 214013;
    self.add = 253101;
}

LCG.prototype.rand = function rand() {
    var self = this;
    self.last = (self.mul * self.last + self.add) % self.mod;
    return self.last;
};

LCG.prototype.rand64 = function rand64() {
    var self = this;
    var ret = new Buffer(8);
    ret.writeUInt32BE(self.rand(), 0);
    ret.writeUInt32BE(self.rand(), 4);
    return ret;
};

module.exports = LCG;
<|endoftext|>


<commit_before>/* global describe, it */
import Stamp from "relativity";
import chai from "chai";
var expect = chai.expect;

describe("Acceptance Tests", function(){

  it("completes sample run from Almeida, et al", function() {
    var a, b, c, d, e, f, g, h, i, j, k, l, m, n;

    a = new Stamp();    //
    [b,c] = a.fork();   //
    d = b.event();      //                       -----o--------o-----------
    e = c.event();      //                      /     F        I           `
    [f,g] = d.fork();   //                     /                            `
    h = e.event();      //       ----o--------o                              o--------o
    i = f.event();      //      /    B        D`                            /M        N
    j = g.join(h);      //     /                `                          /
    [k,l] = j.fork();   //    o                  -----o-----     -----o----
    m = i.join(k);      //    A`                      G     `   /     K
    n = m.event();      //      `                            ` /
                        //       `                            o
                        //        `                          /J`
                        //         `                        /   `
                        //          -o--------o-------o-----     -----o
                        //           C        E       H               L
                        //

    expect(n.flatten()).to.deep.equal([[1,0], 2]);
    expect(l.flatten()).to.deep.equal([[0,1], [0, 1, 1]]);
    expect(a.lte(d) ,"a in d's causal history").to.be.true();
    expect(d.lte(a), "d not in a's causal history").to.be.false();
    expect(d.lte(e), "d not in e's causal history").to.be.false();
    expect(e.lte(d), "e not in d's causal history").to.be.false();
    expect(e.lte(j), "e in j's causal history").to.be.true();
    expect(d.lte(j), "d in j's causal history").to.be.true();
  });
});
<commit_msg>adding a test<commit_after>/* global describe, it */
import Stamp from "relativity";
import chai from "chai";
var expect = chai.expect;

describe("Acceptance Tests", function(){

  it("completes sample run from Almeida, et al", function() {
    var a, b, c, d, e, f, g, h, i, j, k, l, m, n;

    a = new Stamp();    //
    [b,c] = a.fork();   //
    d = b.event();      //                       -----o--------o-----------
    e = c.event();      //                      /     F        I           `
    [f,g] = d.fork();   //                     /                            `
    h = e.event();      //       ----o--------o                              o--------o
    i = f.event();      //      /    B        D`                            /M        N
    j = g.join(h);      //     /                `                          /
    [k,l] = j.fork();   //    o                  -----o-----     -----o----
    m = i.join(k);      //    A`                      G     `   /     K
    n = m.event();      //      `                            ` /
                        //       `                            o
                        //        `                          /J`
                        //         `                        /   `
                        //          -o--------o-------o-----     -----o
                        //           C        E       H               L
                        //

    expect(n.flatten()).to.deep.equal([[1,0], 2]);
    expect(l.flatten()).to.deep.equal([[0,1], [0, 1, 1]]);
    expect(a.lte(d) ,"a in d's causal history").to.be.true();
    expect(d.lte(a), "d not in a's causal history").to.be.false();
    expect(d.lte(e), "d not in e's causal history").to.be.false();
    expect(e.lte(d), "e not in d's causal history").to.be.false();
    expect(e.lte(j), "e in j's causal history").to.be.true();
    expect(d.lte(j), "d in j's causal history").to.be.true();
  });

  it("anonymous stamps can be joined and will sort correctly", function() {
    var a, b, c, d, e, f, g, h, i, j, k, l, m, n;

    a = new Stamp();
    [b,c] = a.fork();
    d = b.event();
    e = c.event();
    [f,g] = d.fork();
    h = e.event();
    i = f.event();
    j = g.join(h);
    [k,l] = j.fork();
    m = i.join(k);
    n = m.event();

    var virtualJ = g.peek().join(h.peek());
    expect(virtualJ.lte(j)).to.be.true();
    expect(j.lte(virtualJ)).to.be.true();

    var intermediate = b.peek().join(h.peek());
    expect(a.lte(intermediate)).to.be.true();
    expect(b.lte(intermediate)).to.be.true();
    expect(c.lte(intermediate)).to.be.true();
    expect(e.lte(intermediate)).to.be.true();
    expect(h.lte(intermediate)).to.be.true();

    expect(d.lte(intermediate)).to.be.false();
    expect(f.lte(intermediate)).to.be.false();
    expect(g.lte(intermediate)).to.be.false();
    expect(i.lte(intermediate)).to.be.false();
    expect(j.lte(intermediate)).to.be.false();
  });

});
<|endoftext|>


<commit_before>var url = "https://api.uber.com/",
    version = "v1",
    request = require("request");

/**
 *
 * Constructor, takes in your Uber API Server token and version.  Currently for most request, this is 'v1'.
 * However, for some user history request, this is 'v1.1'.
 * This assumes if data is of type string, it is a server_token.
 *
 * @param object required
 *  - server_token | bearer_token
 *  - version
 *
 * @throws Error if token is not supplied
 */
function Uber(data) {
  if (!(this instanceof Uber)) {
    return new Uber(data);
  }
  if (typeof data === 'undefined') {
    throw new Error("Server token or data object is required.");
  }

  if (typeof data === 'string') {
    this.setServerToken(data);
    this.setApiVersion('v1');
  } else { // assume object
    if (typeof data.server_token === 'undefined') {
      if (typeof data.bearer_token === 'undefined') {
        throw new Error("An API token is required.");
      } else {
        this.setBearerToekn(data.bearer_token);
      }
    } else {
      this.setServerToken(data.server_token);
    }
    this.setApiVersion((typeof data.version === 'undefined')? version : data.version);
  }
}

Uber.prototype = {
  /**
   *
   * getProducts
   *
   * @param Number required Latitude component of location.
   * @param Number required Longitude component of location.
   * @param Function A callback function which takes two parameters
   *
   * @throws Error If the latitude or longitude are not supplied
   */
  getProducts: function(latitude, longitude, callback) {
    if (typeof latitude === 'undefined' || typeof latitude === 'function') {
      throw new Error("Latitude must be defined");
    }
    if (typeof longitude === 'undefined' || typeof longitude === 'function') {
      throw new Error("Longitude must be defined");
    }

    callback = (typeof callback === 'undefined') ? function(e,b){} : callback;

    get(this.getAuthToken(), url+this.version+"/products?latitude="+latitude+"&longitude="+longitude, callback);
  },

  /**
   *
   * getPriceEstimate Requires both a starting and ending point
   *
   * @param Number required Latitude component of start location.
   * @param Number required Longitude component of start location.
   * @param Number required Latitude component of end location.
   * @param Number required Longitude component of end location.
   * @param Function A callback function which takes two parameters
   *
   * @throws Error If the starting or ending latitude or longitude are not supplied
   */
  getPriceEstimate: function (start_latitude, start_longitude, end_latitude, end_longitude, callback) {
    var u = url + this.version + "/estimates/price?";
    u += "start_latitude="+start_latitude+"&start_longitude="+start_longitude;
    u += "&end_latitude="+end_latitude+"&end_longitude="+end_longitude;
    callback = (typeof callback === 'undefined') ? function(e,b){} : callback;
    get(this.getAuthToken(), u, callback);
  },

  /**
   *
   * getTimeEstimate Requires starting point, gives an estimate (in seconds) of time until arrival
   *
   * @param Number required Latitude component.
   * @param Number required Longitude component.
   * @param String Unique customer identifier to be used for experience customization.
   * @param String Unique identifier representing a specific product for a given latitude & longitude.
   * @param Function A callback function which takes two parameters
   *
   * @throws Error If the starting or ending latitude or longitude are not supplied
   */
  getTimeEstimate: function (start_latitude, start_longitude, customer_uuid, product_id, callback) {
    if (typeof customer_uuid === 'function') {
      callback = customer_uuid;
    }
    if (typeof product_id === 'function') {
      callback = product_id;
    }
    callback = (typeof callback === 'undefined') ? function(e,b){} : callback;
    var u = url+this.version+"/estimates/time?start_latitude="+start_latitude+"&start_longitude="+start_longitude;
    if (typeof customer_uuid !== 'undefined' && typeof customer_uuid != 'function') {
      url += "&customer_uuid="+customer_uuid;
    }
    if (typeof product_id !== 'undefined' && typeof product_id != 'function') {
      url += "&product_id="+product_id;
    }
    get(this.getAuthToken(), u, callback);
  },

  setBearerToken: function(token) {
    this.bearer_token = token;
  },
  getBearerToken: function(token) {
    return this.bearer_token;
  },
  setServerToken: function(token) {
    this.server_token = token;
  },
  getServerToken: function() {
    return this.server_token;
  },
  setApiVersion: function(version) {
    this.version = version;
  },

  /**
   *
   */
  getAuthToken: function() {
    var data = {
      token: this.getServerToken(),
      type: "server"
    };
    if (typeof this.bearer_token !== 'undefined') {
      data.token = this.getBearerToken();
      data.type = "bearer";
    }
    return data;
  }
}

//Uber.prototype.getUserActivity = null;
//Uber.prototype.getUserProfile = null;

module.exports = Uber;

/**
 * @private
 * A function to help ease development. So as not to rewrite the same thing over and over again.
 */
function get(tokenData, url, callback) {
  var tokenStr = "Token ";

  if (tokenData.type == "bearer") {
    tokenStr = "Bearer ";
  }

  var opts = {
    url: url,
    headers: {
      "Authorization": tokenStr + tokenData.token
    }
  }
  request.get(opts, function(error, body, response) {
    if (error) {
      callback(error, null);
    } else {
      if (body.statusCode != 200) {
        callback(JSON.parse(response), null);
      } else {
        callback(null, JSON.parse(response));
      }
    }
  });
}<commit_msg>Updating to add user profile and user history functionality<commit_after>var url = "https://api.uber.com/",
    version = "v1",
    request = require("request");

/**
 *
 * Constructor, takes in your Uber API Server token and version.  Currently for most request, this is 'v1'.
 * However, for some user history request, this is 'v1.1'.
 * This assumes if data is of type string, it is a server_token.
 *
 * @param object required
 *  - server_token | bearer_token
 *  - version
 *
 * @throws Error if token is not supplied
 */
function Uber(data) {
  if (!(this instanceof Uber)) {
    return new Uber(data);
  }
  if (typeof data === 'undefined') {
    throw new Error("Server token or data object is required.");
  }

  if (typeof data === 'string') {
    this.setServerToken(data);
    this.setApiVersion('v1');
  } else { // assume object
    if (typeof data.server_token === 'undefined') {
      if (typeof data.bearer_token === 'undefined') {
        throw new Error("An API token is required.");
      } else {
        this.setBearerToekn(data.bearer_token);
      }
    } else {
      this.setServerToken(data.server_token);
    }
    this.setApiVersion((typeof data.version === 'undefined')? version : data.version);
  }
}

Uber.prototype = {
  /**
   *
   * getProducts
   *
   * @param Number required Latitude component of location.
   * @param Number required Longitude component of location.
   * @param Function A callback function which takes two parameters
   *
   * @throws Error If the latitude or longitude are not supplied
   */
  getProducts: function(latitude, longitude, callback) {
    if (typeof latitude === 'undefined' || typeof latitude === 'function') {
      throw new Error("Latitude must be defined");
    }
    if (typeof longitude === 'undefined' || typeof longitude === 'function') {
      throw new Error("Longitude must be defined");
    }

    callback = (typeof callback === 'undefined') ? function(e,b){} : callback;

    get(this.getAuthToken(), url+this.version+"/products?latitude="+latitude+"&longitude="+longitude, callback);
  },

  /**
   *
   * getPriceEstimate Requires both a starting and ending point
   *
   * @param Number required Latitude component of start location.
   * @param Number required Longitude component of start location.
   * @param Number required Latitude component of end location.
   * @param Number required Longitude component of end location.
   * @param Function A callback function which takes two parameters
   *
   * @throws Error If the starting or ending latitude or longitude are not supplied
   */
  getPriceEstimate: function (start_latitude, start_longitude, end_latitude, end_longitude, callback) {
    var u = url + this.version + "/estimates/price?";
    u += "start_latitude="+start_latitude+"&start_longitude="+start_longitude;
    u += "&end_latitude="+end_latitude+"&end_longitude="+end_longitude;
    callback = (typeof callback === 'undefined') ? function(e,b){} : callback;
    get(this.getAuthToken(), u, callback);
  },

  /**
   *
   * getTimeEstimate Requires starting point, gives an estimate (in seconds) of time until arrival
   *
   * @param Number required Latitude component.
   * @param Number required Longitude component.
   * @param String Unique customer identifier to be used for experience customization.
   * @param String Unique identifier representing a specific product for a given latitude & longitude.
   * @param Function A callback function which takes two parameters
   *
   * @throws Error If the starting or ending latitude or longitude are not supplied
   */
  getTimeEstimate: function (start_latitude, start_longitude, customer_uuid, product_id, callback) {
    if (typeof customer_uuid === 'function') {
      callback = customer_uuid;
    }
    if (typeof product_id === 'function') {
      callback = product_id;
    }
    callback = (typeof callback === 'undefined') ? function(e,b){} : callback;
    var u = url+this.version+"/estimates/time?start_latitude="+start_latitude+"&start_longitude="+start_longitude;
    if (typeof customer_uuid !== 'undefined' && typeof customer_uuid != 'function') {
      url += "&customer_uuid="+customer_uuid;
    }
    if (typeof product_id !== 'undefined' && typeof product_id != 'function') {
      url += "&product_id="+product_id;
    }
    get(this.getAuthToken(), u, callback);
  },

  /**
   * getHistory Get the currently logged in user history
   *
   * @param Function A callback function which takes two paramenters
   */
  getHistory: function(callback) {
    if (typeof callback === 'undefined') {
    } else {
      var u = url+((this.version == "v1") ? "v1.1" : this.version)+"/history",
          tokenData = this.getAuthToken();
      if (tokenData.type != "bearer") {
        throw new Error("Invalid token type. Must use a token of type bearer.");
      }
      get(tokenData, u, callback);
    }
  },

  /**
   * getMe Get the currently logged in user profile.
   *
   * @param Function A callback function which takes two parameters
   */
  getMe: function(callback) {
    if (typeof callback === 'undefined') {
      throw new Error("Callback function undefined");
    } else {
      var u = url+this.version+"/me",
          tokenData = this.getAuthToken();
      if (tokenData.type != "bearer") {
        throw new Error("Invalid token type. Must use a token of type bearer.");
      }
      get(tokenData, u, callback);
    }
  },

  setBearerToken: function(token) {
    this.bearer_token = token;
  },
  getBearerToken: function(token) {
    return this.bearer_token;
  },
  setServerToken: function(token) {
    this.server_token = token;
  },
  getServerToken: function() {
    return this.server_token;
  },
  setApiVersion: function(version) {
    this.version = version;
  },

  /**
   *
   */
  getAuthToken: function() {
    var data = {
      token: this.getServerToken(),
      type: "server"
    };
    if (typeof this.bearer_token !== 'undefined') {
      data.token = this.getBearerToken();
      data.type = "bearer";
    }
    return data;
  }
}

//Uber.prototype.getUserActivity = null;
//Uber.prototype.getUserProfile = null;

module.exports = Uber;

/**
 * @private
 * A function to help ease development. So as not to rewrite the same thing over and over again.
 */
function get(tokenData, url, callback) {
  var tokenStr = "Token ";

  if (tokenData.type == "bearer") {
    tokenStr = "Bearer ";
  }

  var opts = {
    url: url,
    headers: {
      "Authorization": tokenStr + tokenData.token
    }
  }
  request.get(opts, function(error, body, response) {
    if (error) {
      callback(error, null);
    } else {
      if (body.statusCode != 200) {
        callback(JSON.parse(response), null);
      } else {
        callback(null, JSON.parse(response));
      }
    }
  });
}<|endoftext|>