<commit_before>define(['marionette',
    'models/visit',
    'modules/stats/models/breakdown',
    'modules/stats/collections/pies',

    'modules/stats/views/visit',
    'modules/stats/views/proposal',

    'modules/types/gen/stats/views/visit',

    'modules/stats/views/overview',
    'modules/stats/views/beamline'

    ], function(Marionette, Visit, BreakDown, Pies, VisitView, ProposalView, GenericVisitView, BAGOverviewView, BeamlineOverview) {

    var bc = { title: 'Visit Statistics', url: '/stats' }

    var controller = {

        // Visit Stats
        visit:  function(visit) {
            var prop = visit.replace(/-\d+/,'')
            app.cookie(prop)

            app.loading()
            var vis = new Visit({ VISIT: visit })
            vis.fetch({
                success: function() {
                    var breakdown = new BreakDown({ visit: visit })
                    breakdown.fetch({
                        success: function() {
                            var views = {
                                mx: VisitView,
                            }

                            if (vis.get('TYPE') in views) view = views[vis.get('TYPE')]
                            else view = GenericVisitView

                            app.bc.reset([bc, { title: app.prop, url: '/stats' }, { title: visit, url : '/dc/visit/'+visit }]),
                            app.content.show(new view({ model: vis, breakdown: breakdown }))
                        },
                        error: function() {
                            app.bc.reset([bc, { title: 'No Data' }])
                            app.message({ title: 'No data', message: 'No data for this visit yet' })
                        },
                    })
                },
                error: function() {
                    app.bc.reset([bc, { title: 'Error' }])
                    app.message({ title: 'No such visit', message: 'Couldnt find the specified viist' })
                }
            })
        },

        // Proposal Stats
        proposal: function(page) {
            app.loading()
            if (!page) page = 1
            var pies = new Pies(null, { state: { pageSize: app.mobile() ? 5 : 12, currentPage: parseInt(page) } })
            pies.fetch({
                success: function() {
                    app.bc.reset([bc, { title: 'Proposal' }, { title: app.prop }]),
                    app.content.show(new ProposalView({ pies: pies }))
                },
                error: function() {

                }
            })
        },

        overview: function(s,page) {
            if (!app.user_can('all_prop_stats')) app.message({ title: 'Access Denied', message: 'You do not have access to that page' })
            if (!page) page = 1
            app.bc.reset([bc, { title: 'BAG Overview' }]),
            app.content.show(new BAGOverviewView({ params: { s: s } }))
        },

        beamline: function(bl) {
            app.bc.reset([bc, { title: 'Beamline Overview' }]),
            app.content.show(new BeamlineOverview({ bl: bl }))
        }
    }

    app.addInitializer(function() {
        app.on('stats:show', function(visit) {
            app.navigate('stats/visit/'+visit)
            controller.visit(visit)
        })

        app.on('pstats:show', function() {
            app.navigate('stats')
            controller.proposal()
        })
    })

    return controller
})<commit_msg>restrict access to beamline stats<commit_after>define(['marionette',
    'models/visit',
    'modules/stats/models/breakdown',
    'modules/stats/collections/pies',

    'modules/stats/views/visit',
    'modules/stats/views/proposal',

    'modules/types/gen/stats/views/visit',

    'modules/stats/views/overview',
    'modules/stats/views/beamline'

    ], function(Marionette, Visit, BreakDown, Pies, VisitView, ProposalView, GenericVisitView, BAGOverviewView, BeamlineOverview) {

    var bc = { title: 'Visit Statistics', url: '/stats' }

    var controller = {

        // Visit Stats
        visit:  function(visit) {
            var prop = visit.replace(/-\d+/,'')
            app.cookie(prop)

            app.loading()
            var vis = new Visit({ VISIT: visit })
            vis.fetch({
                success: function() {
                    var breakdown = new BreakDown({ visit: visit })
                    breakdown.fetch({
                        success: function() {
                            var views = {
                                mx: VisitView,
                            }

                            if (vis.get('TYPE') in views) view = views[vis.get('TYPE')]
                            else view = GenericVisitView

                            app.bc.reset([bc, { title: app.prop, url: '/stats' }, { title: visit, url : '/dc/visit/'+visit }]),
                            app.content.show(new view({ model: vis, breakdown: breakdown }))
                        },
                        error: function() {
                            app.bc.reset([bc, { title: 'No Data' }])
                            app.message({ title: 'No data', message: 'No data for this visit yet' })
                        },
                    })
                },
                error: function() {
                    app.bc.reset([bc, { title: 'Error' }])
                    app.message({ title: 'No such visit', message: 'Couldnt find the specified viist' })
                }
            })
        },

        // Proposal Stats
        proposal: function(page) {
            app.loading()
            if (!page) page = 1
            var pies = new Pies(null, { state: { pageSize: app.mobile() ? 5 : 12, currentPage: parseInt(page) } })
            pies.fetch({
                success: function() {
                    app.bc.reset([bc, { title: 'Proposal' }, { title: app.prop }]),
                    app.content.show(new ProposalView({ pies: pies }))
                },
                error: function() {

                }
            })
        },

        overview: function(s,page) {
            if (!app.user_can('all_prop_stats')) app.message({ title: 'Access Denied', message: 'You do not have access to that page' })
            if (!page) page = 1
            app.bc.reset([bc, { title: 'BAG Overview' }]),
            app.content.show(new BAGOverviewView({ params: { s: s } }))
        },

        beamline: function(bl) {
            if (!app.user_can('all_breakdown')) app.message({ title: 'Access Denied', message: 'You do not have access to that page' })
            app.bc.reset([bc, { title: 'Beamline Overview' }]),
            app.content.show(new BeamlineOverview({ bl: bl }))
        }
    }

    app.addInitializer(function() {
        app.on('stats:show', function(visit) {
            app.navigate('stats/visit/'+visit)
            controller.visit(visit)
        })

        app.on('pstats:show', function() {
            app.navigate('stats')
            controller.proposal()
        })
    })

    return controller
})<|endoftext|>


<commit_before>const path = require('path')
const webpack = require('webpack')
const appName = 'formatter'
const outputFile = appName + '.js'

const PATH = {
  source: path.join(__dirname, 'src'),
  dist: path.join(__dirname, 'dist'),
  entry: path.join(__dirname, 'src', 'index.js')
}

const config = {
  entry: PATH.entry,
  devtool: 'eval-source-map',
  output: {
    path: PATH.dist,
    filename: outputFile,
    library: [appName],
    libraryTarget: 'umd'
  },
  module: {
    loaders: [{
      test: /(\.jsx|\.js)$/,
      loader: 'babel',
      exclude: /(node_modules|bower_components)/,
      query: {
        presets: ['react', 'es2015', 'stage-1']
      }
    }, {
      test: /(\.jsx|\.js)$/,
      loader: 'eslint-loader',
      exclude: /node_modules/
    }]
  },
  resolve: {
    root: path.resolve('./src'),
    extensions: ['', '.js', '.jsx']
  },
  plugins: [
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: true
        }
     })
  ]
}

module.exports = config
<commit_msg>Update config<commit_after>const path = require('path')
const webpack = require('webpack')
const appName = 'formatter'
const outputFile = appName + '.js'

const PATH = {
  source: path.join(__dirname, 'src'),
  dist: path.join(__dirname, 'dist'),
  entry: path.join(__dirname, 'src', 'index.js')
}

const config = {
  entry: PATH.entry,
  devtool: 'eval-source-map',
  output: {
    path: PATH.dist,
    filename: outputFile,
    library: [appName],
    libraryTarget: 'umd'
  },
  module: {
    loaders: [{
      test: /(\.jsx|\.js)$/,
      loader: 'babel',
      exclude: /node_modules/,
      query: {
        presets: ['react', 'es2015', 'stage-1']
      }
    }, {
      test: /(\.jsx|\.js)$/,
      loader: 'eslint-loader',
      exclude: /node_modules/
    }]
  },
  resolve: {
    root: [path.resolve(__dirname, 'src'), path.resolve(__dirname, 'node_modules')],
    extensions: ['', '.js', '.jsx']
  },
  plugins: [
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: true
        }
     })
  ]
}

module.exports = config
<|endoftext|>


<commit_before>import reducer from './reducer';
import * as selectors from './selectors';
import * as actions from './actions';
import {
  ACTION_TYPES,
  TEST_TYPES,
} from '../constants';

export function isActive({ cast, gamestates }) {
  const { initiallyEnabled = true, comparators = [] } = cast;
  return comparators.every(({
    gameStateId,
    testType,
    value,
  }) => {
    const gs = gamestates[gameStateId];
    let retValue;
    switch (TEST_TYPES[testType]) {
      case 'EqualTo':
        retValue = value === gs.value;
        break;
      case 'NotEqualTo':
        retValue = value !== gs.value;
        break;
      case 'GreaterThan':
        retValue = value > gs.value;
        break;
      case 'LessThan':
        retValue = value < gs.value;
        break;
      default:
        retValue = false;
    }
    retValue = initiallyEnabled ? retValue : !retValue;
    return retValue;
  });
}

export {
  selectors,
  reducer,
  actions,
};

export default {
  selectors,
  reducer,
  actions,
};
<commit_msg>ut fix<commit_after>import reducer from './reducer';
import * as selectors from './selectors';
import * as actions from './actions';
import {
  TEST_TYPES,
} from '../constants';

export function isActive({ cast, gamestates }) {
  const { initiallyEnabled = true, comparators = [] } = cast;
  return comparators.every(({
    gameStateId,
    testType,
    value,
  }) => {
    const gs = gamestates[gameStateId];
    let retValue;
    switch (TEST_TYPES[testType]) {
      case 'EqualTo':
        retValue = gs && (value === gs.value);
        break;
      case 'NotEqualTo':
        retValue = gs && (value !== gs.value);
        break;
      case 'GreaterThan':
        retValue = gs && (value > gs.value);
        break;
      case 'LessThan':
        retValue = gs && (value < gs.value);
        break;
      default:
        retValue = false;
    }
    retValue = initiallyEnabled ? retValue : !retValue;
    return retValue;
  });
}

export {
  selectors,
  reducer,
  actions,
};

export default {
  selectors,
  reducer,
  actions,
};
<|endoftext|>


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

var assert = require('assert');
var paxos  = require('./paxos');

function ballot_test() {
  console.log(".. ballot_test");
  with (paxos) {
    var a = ballot_mk(1, 0, 0);
    assert(ballot_gte(a, ballot_mk(-1, -1, -1)));
    assert(ballot_gte(ballot_mk(1, 1, 1), a));
    assert(ballot_gte(ballot_mk(1, 1, 0), a));
    assert(ballot_gte(ballot_mk(1, 0, 1), a));
    assert(ballot_gte(ballot_mk(1, 0, 0), a));
    assert(!ballot_gte(ballot_mk(0, 0, 0), a));
    assert(!ballot_gte(ballot_mk(0, 0, 1), a));
    assert(!ballot_gte(ballot_mk(0, 1, 0), a));
    assert(!ballot_gte(ballot_mk(0, 1, 1), a));
    assert(ballot_gte(ballot_inc(a), a));
    assert(ballot_gte(a, a));
    assert(ballot_eq(a, a));
    assert(!ballot_eq(ballot_inc(a), a));
  }
  console.log("ok ballot_test");
}
ballot_test();

function majority_test() {
  console.log(".. majority_test");
  with (paxos) {
    assert(majority(4) == 3);
    assert(majority(3) == 2);
    assert(majority(2) == 2);
    assert(majority(1) == 1);
    assert(majority(0) == 1);
  }
  console.log("ok majority_test");
}
majority_test();

function is_member_test() {
  console.log(".. is_member_test");
  with (paxos) {
    assert(is_member([10], 10));
    assert(is_member([10,20], 10));
    assert(is_member([10,20], 20));
    assert(!is_member([10,20], 30));
    assert(!is_member([10], 30));
    assert(!is_member([], 30));
  }
  console.log("ok is_member_test");
}
is_member_test();

function create_test() {
  console.log(".. create_test");
  with (paxos) {
    assert(proposer('A', 1, 0, ['A'], null, null));
    try {
      proposer('A', 1, 0, [], null, null);
      assert(false);
    } catch (ex) { assert(ex); }
  }
  console.log("ok create_test");
}
create_test();

// ------------------------------------------------

var broadcasts = []; // Records all the broadcasts by a mock comm.

function mock_comm(label) {
  label = label || "";
  if (label.length > 0) {
    label = label + " ";
  }
  broadcasts = [];
  var comm = {
    "broadcast": function(acceptors, msg) {
      log(label + "received: " + acceptors + ", " + JSON.stringify(msg));
      broadcasts[broadcasts.length] = [acceptors, msg];
    }
  };
  return comm;
}

function log(msg) { console.log("     " + msg); }

var to_s = JSON.stringify;
var blackboard = {};

propose_phase_test();

function propose_phase_test() {
  console.log(".. propose_phase_test");
  var proposer = blackboard.proposer =
    paxos.proposer('A', 1, 0, ['B'], mock_comm(),
                   { proposer_timeout: 100 });
  proposer.propose(123, propose_phase_test1);
}

function propose_phase_test1(err, info) {
  assert(err == 'timeout');
  assert(broadcasts.length == 1);
  assert(broadcasts[0][0] == 'B');
  assert(broadcasts[0][1].kind == paxos.REQ_PROPOSE);
  assert(paxos.ballot_eq(broadcasts[0][1].ballot,
                         paxos.ballot_mk(0, 'A', 1)));
  assert(blackboard.proposer.stats().tot_propose_phase == 1);

  log("propose_phase_test1... done");

  // Two propose() calls.
  blackboard.callback_count = 0;
  var proposer = blackboard.proposer =
    paxos.proposer('A', 1, 0, ['B'], mock_comm(),
                   { proposer_timeout: 100 });
  proposer.propose(123, propose_phase_test2);
  proposer.propose(234, propose_phase_test2);
}

function propose_phase_test2(err, info) {
  // Should be called twice.
  assert(err == 'timeout');
  blackboard.callback_count++;
  assert(blackboard.callback_count <= 2);
  if (blackboard.callback_count < 2) {
    return;
  }

  assert(broadcasts.length == 2);
  assert(broadcasts[0][0] == 'B');
  assert(broadcasts[0][1].kind == paxos.REQ_PROPOSE);
  assert(paxos.ballot_eq(broadcasts[0][1].ballot,
                         paxos.ballot_mk(0, 'A', 1)));
  assert(broadcasts[1][0] == 'B');
  assert(broadcasts[1][1].kind == paxos.REQ_PROPOSE);
  assert(paxos.ballot_eq(broadcasts[1][1].ballot,
                         paxos.ballot_mk(1, 'A', 1)));
  assert(blackboard.proposer.stats().tot_propose_phase == 2);

  log("propose_phase_test2... done");

  console.log("ok propose_phase_test");

  done();
}

function done() {
  console.log("DONE.");
}

<commit_msg>Test paxos propose to two acceptors.<commit_after>#!/usr/bin/env node

var assert = require('assert');
var paxos  = require('./paxos');

function ballot_test() {
  console.log(".. ballot_test");
  with (paxos) {
    var a = ballot_mk(1, 0, 0);
    assert(ballot_gte(a, ballot_mk(-1, -1, -1)));
    assert(ballot_gte(ballot_mk(1, 1, 1), a));
    assert(ballot_gte(ballot_mk(1, 1, 0), a));
    assert(ballot_gte(ballot_mk(1, 0, 1), a));
    assert(ballot_gte(ballot_mk(1, 0, 0), a));
    assert(!ballot_gte(ballot_mk(0, 0, 0), a));
    assert(!ballot_gte(ballot_mk(0, 0, 1), a));
    assert(!ballot_gte(ballot_mk(0, 1, 0), a));
    assert(!ballot_gte(ballot_mk(0, 1, 1), a));
    assert(ballot_gte(ballot_inc(a), a));
    assert(ballot_gte(a, a));
    assert(ballot_eq(a, a));
    assert(!ballot_eq(ballot_inc(a), a));
  }
  console.log("ok ballot_test");
}
ballot_test();

function majority_test() {
  console.log(".. majority_test");
  with (paxos) {
    assert(majority(4) == 3);
    assert(majority(3) == 2);
    assert(majority(2) == 2);
    assert(majority(1) == 1);
    assert(majority(0) == 1);
  }
  console.log("ok majority_test");
}
majority_test();

function is_member_test() {
  console.log(".. is_member_test");
  with (paxos) {
    assert(is_member([10], 10));
    assert(is_member([10,20], 10));
    assert(is_member([10,20], 20));
    assert(!is_member([10,20], 30));
    assert(!is_member([10], 30));
    assert(!is_member([], 30));
  }
  console.log("ok is_member_test");
}
is_member_test();

function create_test() {
  console.log(".. create_test");
  with (paxos) {
    assert(proposer('A', 1, 0, ['A'], null, null));
    try {
      proposer('A', 1, 0, [], null, null);
      assert(false);
    } catch (ex) { assert(ex); }
  }
  console.log("ok create_test");
}
create_test();

// ------------------------------------------------

var broadcasts = []; // Records all the broadcasts by a mock comm.

function mock_comm(label) {
  label = label || "";
  if (label.length > 0) {
    label = label + " ";
  }
  broadcasts = [];
  var comm = {
    "broadcast": function(acceptors, msg) {
      log(label + "received: " + acceptors + ", " + JSON.stringify(msg));
      broadcasts[broadcasts.length] = [acceptors, msg];
    }
  };
  return comm;
}

function log(msg) { console.log("     " + msg); }

var to_s = JSON.stringify;
var blackboard = {};

propose_phase_test();

function propose_phase_test() {
  console.log(".. propose_phase_test");
  log("propose_phase_test1...");
  var proposer = blackboard.proposer =
    paxos.proposer('A', 1, 0, ['B'], mock_comm(),
                   { proposer_timeout: 100 });
  proposer.propose(123, propose_phase_test1);
}

function propose_phase_test1(err, info) {
  assert(err == 'timeout');
  assert(broadcasts.length == 1);
  assert(broadcasts[0][0].length == 1);
  assert(broadcasts[0][0][0] == 'B');
  assert(broadcasts[0][1].kind == paxos.REQ_PROPOSE);
  assert(paxos.ballot_eq(broadcasts[0][1].ballot,
                         paxos.ballot_mk(0, 'A', 1)));
  assert(blackboard.proposer.stats().tot_propose_phase == 1);

  log("propose_phase_test1... done");
  log("propose_phase_test2...");

  // Two propose() calls.
  blackboard.callback_count = 0;
  var proposer = blackboard.proposer =
    paxos.proposer('A', 1, 0, ['B'], mock_comm(),
                   { proposer_timeout: 100 });
  proposer.propose(123, propose_phase_test2);
  proposer.propose(234, propose_phase_test2);
}

function propose_phase_test2(err, info) {
  // Should be called twice.
  assert(err == 'timeout');
  blackboard.callback_count++;
  assert(blackboard.callback_count <= 2);
  if (blackboard.callback_count < 2) {
    return;
  }

  assert(broadcasts.length == 2);
  assert(broadcasts[0][0].length == 1);
  assert(broadcasts[0][0][0] == 'B');
  assert(broadcasts[0][1].kind == paxos.REQ_PROPOSE);
  assert(paxos.ballot_eq(broadcasts[0][1].ballot,
                         paxos.ballot_mk(0, 'A', 1)));
  assert(broadcasts[1][0].length == 1);
  assert(broadcasts[1][0][0] == 'B');
  assert(broadcasts[1][1].kind == paxos.REQ_PROPOSE);
  assert(paxos.ballot_eq(broadcasts[1][1].ballot,
                         paxos.ballot_mk(1, 'A', 1)));
  assert(blackboard.proposer.stats().tot_propose_phase == 2);

  log("propose_phase_test2... done");

  propose_2_acceptors_test();
}

function propose_2_acceptors_test() {
  log("propose_2_acceptors_test...");

  blackboard.callback_count = 0;
  var proposer = blackboard.proposer =
    paxos.proposer('A', 1, 0, ['B', 'C'], mock_comm(),
                   { proposer_timeout: 100 });
  proposer.propose(123, propose_2_acceptors_test2);
}

function propose_2_acceptors_test2(err, info) {
  assert(err == 'timeout');
  assert(broadcasts.length == 1);
  assert(broadcasts[0][0].length == 2);
  assert(broadcasts[0][0][0] == 'B');
  assert(broadcasts[0][0][1] == 'C');
  assert(broadcasts[0][1].kind == paxos.REQ_PROPOSE);
  assert(paxos.ballot_eq(broadcasts[0][1].ballot,
                         paxos.ballot_mk(0, 'A', 1)));
  assert(blackboard.proposer.stats().tot_propose_phase == 1);
  assert(blackboard.proposer.stats().tot_propose_send == 2);

  log("propose_2_acceptors_test...done");

  console.log("ok propose_phase_test");

  done();
}

function done() {
  console.log("DONE.");
}

<|endoftext|>


<commit_before>require('object.assign').shim();
var request = require('request');

var defaultBaseUrl = 'http://api.hubapi.com';

function Client(opts) {
  var self = this;
  self.token;
  self.key;

  self.opts = opts || {};
  self.baseUrl = defaultBaseUrl;

  function useToken (token) {
    if (!token || typeof token !== 'string') {
      return cb(new Error("You must provide a token."));
    }

    self.token = token;
  }

  function useKey (key) {
    if (!key || typeof key !== 'string') {
      return cb(new Error("You must provide a key."));
    }

    self.key = key;
  }

  function setBaseUrl(url) {
    self.baseUrl = url;
  }

  var contacts = {
    get: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/lists/all/contacts/all',
        qs: options
      }, cb);
    },
    getByEmail: function (email, cb) {
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/contact/email/' + email + '/profile'
      }, cb);
    },
    getByEmailBatch: function (emails, cb) {
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/contact/emails/batch',
        qs: { email: emails },
        qsStringifyOptions: { indices: false }
      }, cb);
    },
    getById: function (id, cb) {
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/contact/vid/' + id + '/profile'
      }, cb);
    },
    getByIdBatch: function (ids, cb) {
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/contact/vids/batch',
        qs: { vid: ids },
        qsStringifyOptions: { indices: false }
      }, cb);
    },
    update: function(id, data, cb) {
      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/contacts/v1/contact/vid/' + id + '/profile',
        body: data
      }, cb);
    },
    create: function (data, cb) {
      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/contacts/v1/contact',
        body: data
      }, cb);
    },
    createOrUpdate: function (email, data, cb) {
      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/contacts/v1/contact/createOrUpdate/email/' + email,
        body: data
      }, cb);
    },
    // note: response to successful batch update is undefined by design : http://developers.hubspot.com/docs/methods/contacts/batch_create_or_update
    createOrUpdateBatch: function (data, cb) {
      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/contacts/v1/contact/batch',
        body: data
      }, cb);
    },
    search: function(query, cb) {
    	sendRequest({
    		method: 'GET',
    		url: self.baseUrl + '/contacts/v1/search/query?q=' + query
    	}, cb);
    },
    getRecent: function(cb) {
     sendRequest({
       method: 'GET',
       url: self.baseUrl + '/contacts/v1/lists/recently_updated/contacts/recent?count=100'
     }, cb);
    }
  };

  var lists = {
    get: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/lists',
        qs: options
      }, cb);
    },
    getOne: function(id, cb) {
      if (!id || typeof(id) === 'function') {
        return cb(new Error("id parameter must be provided."));
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/lists/' + id
      }, cb);
    },
    getContacts: function(id, options, cb) {
      if (!id || typeof(id) === 'function') {
        return cb(new Error("id parameter must be provided."));
      }

      if (typeof(options) === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/lists/' + id + '/contacts/all',
        qs: options,
        qsStringifyOptions: { indices: false }
      }, cb);
    },
    getRecentContacts: function(id, options, cb) {
      if (!id || typeof(id) === 'function') {
        return cb(new Error("id parameter must be provided."));
      }

      if (typeof(options) === 'function') {
        cb = options;
        options = {};
      }
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/lists/' + id + '/contacts/recent',
        qs: options,
        qsStringifyOptions: { indices: false }
      }, cb);
    },
    addContacts: function(id, contactBody, cb) {
      if (!id || typeof(id) === 'function') {
        return cb(new Error("id parameter must be provided."));
      }
      if (!contactBody || typeof(contactBody) === 'function') {
        return cb(new Error("contactBody parameter must be provided."));
      }

      var body = contactBody;

      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/contacts/v1/lists/' + id + '/add',
        body: body
      }, cb);
    }
  };

  var campaigns = {
    get: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/email/public/v1/campaigns',
        qs: options
      }, cb);
    },
    getById: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/email/public/v1/campaigns/by-id',
        qs: options
      }, cb);
    },
    getOne: function(id, appId, cb) {
      if (!id || typeof id === "function") {
        return cb(new Error("id parameter must be provided."));
      }

      if (typeof appId === "function") {
        cb = appId;
        appId = null;
      }

      var call = {
        method: 'GET',
        url: self.baseUrl + '/email/public/v1/campaigns/' + id
      };

      if (appId) {
        call.qs = {
          appId: appId
        }
      }

      sendRequest(call, cb);
    },
    events: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/email/public/v1/events',
        qs: options
      }, cb);
    }
  };

  var companies = {
    getRecentlyCreated: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/companies/v2/companies/recent/created',
        qs: options
      }, cb);
    },
    getByDomain: function(domain, cb) {
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/companies/v2/companies/domain/' + domain
      }, cb);
    },
    create: function(data, cb) {
      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/companies/v2/companies/',
        body: data
      }, cb);
    }
  };

  var pipelines = {
    get: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/deals/v1/pipelines',
        qs: options
      }, cb);
    }
  };

  var broadcasts = {
    get: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/broadcast/v1/broadcasts',
        qs: options
      }, cb);
    }
  };

  var subscriptions = {
    get: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/email/public/v1/subscriptions/timeline',
        qs: options
      }, cb);
    }
  };

  var files = {
    get: function(cb) {
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/filemanager/api/v2/files'
      }, cb);
    },
    getOne: function(id, cb) {
      if (!id || typeof(id) === 'function') {
        return cb(new Error("id parameter must be provided."));
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/filemanager/api/v2/files/' + id
      }, cb);
    }
  };

  var deals = {
    getRecentlyModified: function(options, cb){
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/deals/v1/deal/recent/modified',
        qs: options
      }, cb);
    },
    getRecentlyCreated: function(options, cb){
      if(typeof options === 'function'){
        cb = options;
        options = {};
      }
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/deals/v1/deal/recent/created',
        qs: options
      }, cb);
    },
    getById: function(id, cb){
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/deals/v1/deal/' + id
      }, cb);
    },
    deleteById: function(id, cb){
      sendRequest({
        method: 'DELETE',
        url: self.baseUrl + '/deals/v1/deal/' + id
      }, cb);
    },
    updateById: function(id, data, cb){
      sendRequest({
        method: 'PUT',
        url: self.baseUrl + '/deals/v1/deal/' + id,
        body: data
      }, cb);
    },
    create: function(data, cb){
      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/deals/v1/deal/',
        body: data
      }, cb);
    },
    associate: function(id, objectType, associatedObjectId, cb){
      sendRequest({
        method: 'PUT',
        url: self.baseUrl + '/deals/v1/deal/' + id + '/associations/'+ objectType +'?id=' + associatedObjectId
      }, cb);
    },
    removeAssociation: function(id, objectType, associatedObjectId, cb){
      sendRequest({
        method: 'DELETE',
        url: self.baseUrl + '/deals/v1/deal/' + id + '/associations/'+ objectType +'?id=' + associatedObjectId
      }, cb);
    }
  };

  var engagements = {
    create: function (data, cb) {
      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/engagements/v1/engagements',
        body: data
      }, cb);
    }
  };

  function sendRequest (call, cb) {
    if (!self.key && !self.token) {
      return cb(new Error("You need to provide either a token or a key."));
    }
    call.json = true
    call.qs = call.qs || {};

    if (self.key) {
      call.qs.hapikey = self.key;
    } else if (self.token) {
      call.qs.access_token = self.token;
    }

    Object.assign(call, self.opts.request);

    request(call, handleResponse(cb));
  }

  function handleResponse (cb) {
    return function (err, res, data) {
      if (err) return cb(err);
      if (typeof data === 'string') {
        try {
          var parsed = JSON.parse(data);
          data = parsed;
        } catch (e) {
          return cb(new Error(data)); // sometimes errors are returned as strings.
        }
      }
      return cb(null, data, res);
    }
  }

  return {
    campaigns: campaigns,
    subscriptions: subscriptions,
    contacts: contacts,
    companies: companies,
    deals: deals,
    pipelines: pipelines,
    broadcasts: broadcasts,
    lists: lists,
    files: files,
    engagements: engagements,
    useToken: useToken,
    useKey: useKey,
    setBaseUrl: setBaseUrl
  }
}

module.exports = Client;
<commit_msg>Added callback parameter to useKey and UseToken methods<commit_after>require('object.assign').shim();
var request = require('request');

var defaultBaseUrl = 'http://api.hubapi.com';

function Client(opts) {
  var self = this;
  self.token;
  self.key;

  self.opts = opts || {};
  self.baseUrl = defaultBaseUrl;

  function useToken (token, cb) {
    if (!token || typeof token !== 'string') {
      return cb(new Error("You must provide a token."));
    }

    self.token = token;
  }

  function useKey (key, cb) {
    if (!key || typeof key !== 'string') {
      return cb(new Error("You must provide a key."));
    }

    self.key = key;
  }

  function setBaseUrl(url) {
    self.baseUrl = url;
  }

  var contacts = {
    get: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/lists/all/contacts/all',
        qs: options
      }, cb);
    },
    getByEmail: function (email, cb) {
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/contact/email/' + email + '/profile'
      }, cb);
    },
    getByEmailBatch: function (emails, cb) {
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/contact/emails/batch',
        qs: { email: emails },
        qsStringifyOptions: { indices: false }
      }, cb);
    },
    getById: function (id, cb) {
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/contact/vid/' + id + '/profile'
      }, cb);
    },
    getByIdBatch: function (ids, cb) {
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/contact/vids/batch',
        qs: { vid: ids },
        qsStringifyOptions: { indices: false }
      }, cb);
    },
    update: function(id, data, cb) {
      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/contacts/v1/contact/vid/' + id + '/profile',
        body: data
      }, cb);
    },
    create: function (data, cb) {
      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/contacts/v1/contact',
        body: data
      }, cb);
    },
    createOrUpdate: function (email, data, cb) {
      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/contacts/v1/contact/createOrUpdate/email/' + email,
        body: data
      }, cb);
    },
    // note: response to successful batch update is undefined by design : http://developers.hubspot.com/docs/methods/contacts/batch_create_or_update
    createOrUpdateBatch: function (data, cb) {
      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/contacts/v1/contact/batch',
        body: data
      }, cb);
    },
    search: function(query, cb) {
    	sendRequest({
    		method: 'GET',
    		url: self.baseUrl + '/contacts/v1/search/query?q=' + query
    	}, cb);
    },
    getRecent: function(cb) {
     sendRequest({
       method: 'GET',
       url: self.baseUrl + '/contacts/v1/lists/recently_updated/contacts/recent?count=100'
     }, cb);
    }
  };

  var lists = {
    get: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/lists',
        qs: options
      }, cb);
    },
    getOne: function(id, cb) {
      if (!id || typeof(id) === 'function') {
        return cb(new Error("id parameter must be provided."));
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/lists/' + id
      }, cb);
    },
    getContacts: function(id, options, cb) {
      if (!id || typeof(id) === 'function') {
        return cb(new Error("id parameter must be provided."));
      }

      if (typeof(options) === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/lists/' + id + '/contacts/all',
        qs: options,
        qsStringifyOptions: { indices: false }
      }, cb);
    },
    getRecentContacts: function(id, options, cb) {
      if (!id || typeof(id) === 'function') {
        return cb(new Error("id parameter must be provided."));
      }

      if (typeof(options) === 'function') {
        cb = options;
        options = {};
      }
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/contacts/v1/lists/' + id + '/contacts/recent',
        qs: options,
        qsStringifyOptions: { indices: false }
      }, cb);
    },
    addContacts: function(id, contactBody, cb) {
      if (!id || typeof(id) === 'function') {
        return cb(new Error("id parameter must be provided."));
      }
      if (!contactBody || typeof(contactBody) === 'function') {
        return cb(new Error("contactBody parameter must be provided."));
      }

      var body = contactBody;

      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/contacts/v1/lists/' + id + '/add',
        body: body
      }, cb);
    }
  };

  var campaigns = {
    get: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/email/public/v1/campaigns',
        qs: options
      }, cb);
    },
    getById: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/email/public/v1/campaigns/by-id',
        qs: options
      }, cb);
    },
    getOne: function(id, appId, cb) {
      if (!id || typeof id === "function") {
        return cb(new Error("id parameter must be provided."));
      }

      if (typeof appId === "function") {
        cb = appId;
        appId = null;
      }

      var call = {
        method: 'GET',
        url: self.baseUrl + '/email/public/v1/campaigns/' + id
      };

      if (appId) {
        call.qs = {
          appId: appId
        }
      }

      sendRequest(call, cb);
    },
    events: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/email/public/v1/events',
        qs: options
      }, cb);
    }
  };

  var companies = {
    getRecentlyCreated: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/companies/v2/companies/recent/created',
        qs: options
      }, cb);
    },
    getByDomain: function(domain, cb) {
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/companies/v2/companies/domain/' + domain
      }, cb);
    },
    create: function(data, cb) {
      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/companies/v2/companies/',
        body: data
      }, cb);
    }
  };

  var pipelines = {
    get: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/deals/v1/pipelines',
        qs: options
      }, cb);
    }
  };

  var broadcasts = {
    get: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/broadcast/v1/broadcasts',
        qs: options
      }, cb);
    }
  };

  var subscriptions = {
    get: function(options, cb) {
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/email/public/v1/subscriptions/timeline',
        qs: options
      }, cb);
    }
  };

  var files = {
    get: function(cb) {
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/filemanager/api/v2/files'
      }, cb);
    },
    getOne: function(id, cb) {
      if (!id || typeof(id) === 'function') {
        return cb(new Error("id parameter must be provided."));
      }

      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/filemanager/api/v2/files/' + id
      }, cb);
    }
  };

  var deals = {
    getRecentlyModified: function(options, cb){
      if (typeof options === 'function') {
        cb = options;
        options = {};
      }
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/deals/v1/deal/recent/modified',
        qs: options
      }, cb);
    },
    getRecentlyCreated: function(options, cb){
      if(typeof options === 'function'){
        cb = options;
        options = {};
      }
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/deals/v1/deal/recent/created',
        qs: options
      }, cb);
    },
    getById: function(id, cb){
      sendRequest({
        method: 'GET',
        url: self.baseUrl + '/deals/v1/deal/' + id
      }, cb);
    },
    deleteById: function(id, cb){
      sendRequest({
        method: 'DELETE',
        url: self.baseUrl + '/deals/v1/deal/' + id
      }, cb);
    },
    updateById: function(id, data, cb){
      sendRequest({
        method: 'PUT',
        url: self.baseUrl + '/deals/v1/deal/' + id,
        body: data
      }, cb);
    },
    create: function(data, cb){
      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/deals/v1/deal/',
        body: data
      }, cb);
    },
    associate: function(id, objectType, associatedObjectId, cb){
      sendRequest({
        method: 'PUT',
        url: self.baseUrl + '/deals/v1/deal/' + id + '/associations/'+ objectType +'?id=' + associatedObjectId
      }, cb);
    },
    removeAssociation: function(id, objectType, associatedObjectId, cb){
      sendRequest({
        method: 'DELETE',
        url: self.baseUrl + '/deals/v1/deal/' + id + '/associations/'+ objectType +'?id=' + associatedObjectId
      }, cb);
    }
  };

  var engagements = {
    create: function (data, cb) {
      sendRequest({
        method: 'POST',
        url: self.baseUrl + '/engagements/v1/engagements',
        body: data
      }, cb);
    }
  };

  function sendRequest (call, cb) {
    if (!self.key && !self.token) {
      return cb(new Error("You need to provide either a token or a key."));
    }
    call.json = true
    call.qs = call.qs || {};

    if (self.key) {
      call.qs.hapikey = self.key;
    } else if (self.token) {
      call.qs.access_token = self.token;
    }

    Object.assign(call, self.opts.request);

    request(call, handleResponse(cb));
  }

  function handleResponse (cb) {
    return function (err, res, data) {
      if (err) return cb(err);
      if (typeof data === 'string') {
        try {
          var parsed = JSON.parse(data);
          data = parsed;
        } catch (e) {
          return cb(new Error(data)); // sometimes errors are returned as strings.
        }
      }
      return cb(null, data, res);
    }
  }

  return {
    campaigns: campaigns,
    subscriptions: subscriptions,
    contacts: contacts,
    companies: companies,
    deals: deals,
    pipelines: pipelines,
    broadcasts: broadcasts,
    lists: lists,
    files: files,
    engagements: engagements,
    useToken: useToken,
    useKey: useKey,
    setBaseUrl: setBaseUrl
  }
}

module.exports = Client;
<|endoftext|>


<commit_before>const webpack = require('webpack');
const path = require('path');
const HtmlwebpackPlugin = require('html-webpack-plugin');
const NpmInstallPlugin = require('npm-install-webpack-plugin');
const Visualizer = require('webpack-visualizer-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

const ROOT_PATH = path.resolve(__dirname);
const env = process.env.NODE_ENV || 'development';
const isProduction = env === 'production';
const PORT = process.env.PORT || 1337;
const HOST = '0.0.0.0'; // Set to localhost if need be.

module.exports = {
  devtool: isProduction ? '' : 'source-map',
  entry: [
    path.resolve(ROOT_PATH,'app/src/index')
  ],
  module: {
    preLoaders: [
      {
        test: /\.jsx?$/,
        loaders: isProduction ? [] : ['eslint'],
        include: path.resolve(ROOT_PATH, './app')
      }
    ],
    loaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loaders: ['react-hot', 'babel']
    },
    {
      test: /\.svg$/,
      loader: 'babel!svg-react'
    },
    {
      test: /\.json$/,
      loader: 'json'
    },
    {
      test: /\.module\.scss$/,
      loader: !isProduction ?
        'style-loader!css-loader?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]!resolve-url-loader!sass-loader'
      :
        ExtractTextPlugin.extract({
          fallbackLoader: 'style-loader',
          loader: 'css-loader?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]!resolve-url-loader!sass-loader'
        }),
    },
    {
      test: /\.scss$/,
      exclude: /\.module\.scss$/,
      loader: !isProduction ?
        'style-loader!css-loader!sass-loader'
      :
        ExtractTextPlugin.extract({
          fallbackLoader: 'style-loader',
          loader: '!css-loader!sass-loader'
        }),
    },
    {
      test: /\.css$/,
      loader: "style-loader!css-loader"
    },
    {
      test: /\.woff(2)?(\?v=[0-9].[0-9].[0-9])?$/,
      loader: "url-loader?mimetype=application/font-woff"
    },
    {
      test: /\.(ttf|eot|svg)(\?v=[0-9].[0-9].[0-9])?$/,
      loader: "file-loader?name=[name].[ext]"
    },
    {
      test: /\.(jpg|png)$/,
      loader: 'file?name=[path][name].[hash].[ext]'
    }
  ]
  },
  sassLoader: {
    includePaths: [
      './node_modules',
    ]
  },
  resolve: {
    extensions: ['', '.js', '.jsx'],
    alias: {
      components: path.resolve(ROOT_PATH, 'app/src/components'),
      containers: path.resolve(ROOT_PATH, 'app/src/containers'),
      pages: path.resolve(ROOT_PATH, 'app/src/pages'),
      utils: path.resolve(ROOT_PATH, 'app/utils')
    },
  },
  output: {
    path: isProduction ?
      path.resolve(ROOT_PATH, 'server/public')
    :
      path.resolve(ROOT_PATH, 'app/build'),
    publicPath: '/',
    filename: isProduction ? '[name].[chunkhash].js' : 'bundle.js',
    chunkFilename: '[name].[chunkhash].chunk.js',
  },
  stats: {
    chunks: isProduction,
  },
  devServer: {
    contentBase: path.resolve(ROOT_PATH, 'app/build'),
    historyApiFallback: true,
    hot: true,
    inline: true,
    progress: true,
    // Constants defined above take care of logic
    // For setting host and port
    host: HOST,
    port: PORT
  },
  plugins: isProduction ?
    [
      new ExtractTextPlugin('[name].[contenthash].css'),
      new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor',
        children: true,
        minChunks: 2,
        async: true,
      }),
      new HtmlwebpackPlugin({
        template: 'config/templates/_index.html',
        minify: {
          removeComments: true,
          collapseWhitespace: true,
          removeRedundantAttributes: true,
          useShortDoctype: true,
          removeEmptyAttributes: true,
          removeStyleLinkTypeAttributes: true,
          keepClosingSlash: true,
          minifyJS: true,
          minifyCSS: true,
          minifyURLs: true,
        },
        inject: true,
      }),
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
      }),
      new webpack.optimize.OccurrenceOrderPlugin(true),
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.UglifyJsPlugin({
        sourceMap: false
      }),
    ]
  :
    [
      new webpack.HotModuleReplacementPlugin(),
      new NpmInstallPlugin(),
      new HtmlwebpackPlugin({
        title: 'Udacity Alumni Client',
        template: 'index.html'
      }),
      new Visualizer()
    ]
};
<commit_msg>Fix: add inline-eval-cheap-source-map to speed up incremental builds<commit_after>const webpack = require('webpack');
const path = require('path');
const HtmlwebpackPlugin = require('html-webpack-plugin');
const NpmInstallPlugin = require('npm-install-webpack-plugin');
const Visualizer = require('webpack-visualizer-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

const ROOT_PATH = path.resolve(__dirname);
const env = process.env.NODE_ENV || 'development';
const isProduction = env === 'production';
const PORT = process.env.PORT || 1337;
const HOST = '0.0.0.0'; // Set to localhost if need be.

module.exports = {
  devtool: isProduction ? '' : 'inline-eval-cheap-source-map',
  entry: [
    path.resolve(ROOT_PATH,'app/src/index')
  ],
  module: {
    preLoaders: [
      {
        test: /\.jsx?$/,
        loaders: isProduction ? [] : ['eslint'],
        include: path.resolve(ROOT_PATH, './app')
      }
    ],
    loaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loaders: ['react-hot', 'babel']
    },
    {
      test: /\.svg$/,
      loader: 'babel!svg-react'
    },
    {
      test: /\.json$/,
      loader: 'json'
    },
    {
      test: /\.module\.scss$/,
      loader: !isProduction ?
        'style-loader!css-loader?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]!resolve-url-loader!sass-loader'
      :
        ExtractTextPlugin.extract({
          fallbackLoader: 'style-loader',
          loader: 'css-loader?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]!resolve-url-loader!sass-loader'
        }),
    },
    {
      test: /\.scss$/,
      exclude: /\.module\.scss$/,
      loader: !isProduction ?
        'style-loader!css-loader!sass-loader'
      :
        ExtractTextPlugin.extract({
          fallbackLoader: 'style-loader',
          loader: '!css-loader!sass-loader'
        }),
    },
    {
      test: /\.css$/,
      loader: "style-loader!css-loader"
    },
    {
      test: /\.woff(2)?(\?v=[0-9].[0-9].[0-9])?$/,
      loader: "url-loader?mimetype=application/font-woff"
    },
    {
      test: /\.(ttf|eot|svg)(\?v=[0-9].[0-9].[0-9])?$/,
      loader: "file-loader?name=[name].[ext]"
    },
    {
      test: /\.(jpg|png)$/,
      loader: 'file?name=[path][name].[hash].[ext]'
    }
  ]
  },
  sassLoader: {
    includePaths: [
      './node_modules',
    ]
  },
  resolve: {
    extensions: ['', '.js', '.jsx'],
    alias: {
      components: path.resolve(ROOT_PATH, 'app/src/components'),
      containers: path.resolve(ROOT_PATH, 'app/src/containers'),
      pages: path.resolve(ROOT_PATH, 'app/src/pages'),
      utils: path.resolve(ROOT_PATH, 'app/utils')
    },
  },
  output: {
    path: isProduction ?
      path.resolve(ROOT_PATH, 'server/public')
    :
      path.resolve(ROOT_PATH, 'app/build'),
    publicPath: '/',
    filename: isProduction ? '[name].[chunkhash].js' : 'bundle.js',
    chunkFilename: '[name].[chunkhash].chunk.js',
  },
  stats: {
    chunks: isProduction,
  },
  devServer: {
    contentBase: path.resolve(ROOT_PATH, 'app/build'),
    historyApiFallback: true,
    hot: true,
    inline: true,
    progress: true,
    // Constants defined above take care of logic
    // For setting host and port
    host: HOST,
    port: PORT
  },
  plugins: isProduction ?
    [
      new ExtractTextPlugin('[name].[contenthash].css'),
      new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor',
        children: true,
        minChunks: 2,
        async: true,
      }),
      new HtmlwebpackPlugin({
        template: 'config/templates/_index.html',
        minify: {
          removeComments: true,
          collapseWhitespace: true,
          removeRedundantAttributes: true,
          useShortDoctype: true,
          removeEmptyAttributes: true,
          removeStyleLinkTypeAttributes: true,
          keepClosingSlash: true,
          minifyJS: true,
          minifyCSS: true,
          minifyURLs: true,
        },
        inject: true,
      }),
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
      }),
      new webpack.optimize.OccurrenceOrderPlugin(true),
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.UglifyJsPlugin({
        sourceMap: false
      }),
    ]
  :
    [
      new webpack.HotModuleReplacementPlugin(),
      new NpmInstallPlugin(),
      new HtmlwebpackPlugin({
        title: 'Udacity Alumni Client',
        template: 'index.html'
      }),
      new Visualizer()
    ]
};
<|endoftext|>


<commit_before>var parsers = require('./parsers');
var zlib = require('zlib');
var transports = require('./transports');
var util = require('util');
var events = require('events');
var os = require('os');
var raw = require('raw-stacktrace');

var traces = raw({rawCallSites: true});
traces.setMaxListeners(100);
traces.on("trace", function (err, callsites) { err.structuredStackTrace = callsites; });

module.exports.version = require('../package.json').version;

module.exports.createClient = function (options) {
  return module.exports.client = new Client(options);
};

var log = function () {
  if (module.exports.client.silent) return;
  console.warn.apply(undefined, arguments);
};

var Client = function (options) {
    options = options || {};

    this.organization_id       = options.organization_id || process.env.OPBEAT_ORGANIZATION_ID;
    this.app_id                = options.app_id          || process.env.OPBEAT_APP_ID;
    this.secret_token          = options.secret_token    || process.env.OPBEAT_SECRET_TOKEN;
    this.env                   = options.env             || process.env.NODE_ENV || 'development';
    this.logger                = options.logger;
    this.hostname              = options.hostname || os.hostname();
    this.stackTraceLimit       = options.stackTraceLimit || Infinity; // To infinity and beyond
    this.handleExceptions      = 'handleExceptions' in options ? options.handleExceptions : true;
    this.silent                = 'silent' in options ? !!options.silent : false;
    this.exceptionsAreCritical = 'exceptionsAreCritical' in options ? !!options.exceptionsAreCritical : true;
    this.dsn                   = {
        protocol: 'https', // Opbeat currently only supports HTTPS. Future options might include HTTP and UDP
        host: 'opbeat.com',
        path: '/api/v1/organizations/' + this.organization_id + '/apps/' + this.app_id + '/errors/'
    };

    if (['development', 'test'].indexOf(this.env) !== -1) {
        console.warn('opbeat: [WARNING] logging is disabled while running in %s mode', this.env);
        this._enabled = false;
    } else if (!this.organization_id || !this.app_id || !this.secret_token) {
        console.warn('opbeat: [WARNING] logging is disabled. To enable, specify organization id, app id and opbeat token');
        this._enabled = false;
    } else {
        this._enabled = true;
    }

    if (this._enabled) {
        Error.stackTraceLimit = this.stackTraceLimit;

        if (this.handleExceptions) this.handleUncaughtExceptions();

        var client = this;
        this.on('connectionError', function (err) {
            log('opbeat: could not notify service.');
            log('opbeat:', err.stack);
        });
        this.on('error', function (err) {
            log('opbeat: could not notify service.');
            log('opbeat:', err.stack);
        });
        this.on('logged', function (url) {
            log('opbeat: logged error successfully at ' + url);
        });
    }
};
util.inherits(Client, events.EventEmitter);
var _ = Client.prototype;

_.process = function (kwargs, cb) {
    if (cb) {
        this.once('error', cb);
        this.once('connectionError', cb);
        this.once('logged', function (url) {
            cb(null, url);
        });
    }

    kwargs['machine'] = { hostname: this.hostname };
    kwargs['extra'] = kwargs['extra'] || {};
    kwargs['extra']['node'] = process.version;
    kwargs['timestamp'] = new Date().toISOString().split('.')[0];
    if (this.logger) kwargs['logger'] = this.logger;

    // this will happen asynchronously. We don't care about it's response.
    this._enabled && this.send(kwargs);
};

_.send = function (kwargs) {
    var client = this;
    zlib.deflate(JSON.stringify(kwargs), function (err, buff) {
        var headers = {
            'Authorization'  : 'Bearer ' + client.secret_token,
            'Content-Type'   : 'application/octet-stream',
            'Content-Length' : buff.length,
            'User-Agent'     : 'opbeat-nodejs/' + module.exports.version
        };
        transports[client.dsn.protocol].send(client, buff, headers);
    });
};

_.captureMessage = function (message, kwargs, cb) {
    if (!cb && typeof kwargs === 'function') {
        cb = kwargs;
        kwargs = {};
    } else {
        kwargs = kwargs || {};
    }
    if (typeof message === 'object') {
        // if `captureMessage` is parsed an object instead of a string we except
        // it to be in the format of `{ message: '...', params: [] }` and it will
        // be used as `param_message` instead of `message`
        kwargs['param_message'] = message;
        log.apply(undefined, ['opbeat: ' + message.message].concat(message.params));
    } else {
        kwargs = parsers.parseText(message, kwargs);
        log('opbeat: ' + message);
    }
    this.process(kwargs, cb);
};

_.captureError = function (err, kwargs, cb) {
    var client = this;

    if (!(err instanceof Error)) {
        // This handles when someone does:
        //   throw "something awesome";
        // We just send the "Error" as a normal message
        // since there is no way to compute a stack trace
        // See: https://github.com/mattrobenolt/raven-node/issues/18
        this.captureMessage('Error: ' + err, kwargs, cb);
        return;
    }

    if (!cb && typeof kwargs === 'function') {
        cb = kwargs;
        kwargs = {};
    } else {
        kwargs = kwargs || {};
    }

    log('opbeat: ' + err.stack);
    parsers.parseError(err, kwargs, function (kw) {
        client.process(kw, cb);
    });
};

_.captureRequestError = function (err, req, kwargs, cb) {
    if (!cb && typeof kwargs === 'function') {
        cb = kwargs;
        kwargs = {};
    } else {
        kwargs = kwargs || {};
    }

    kwargs = parsers.parseRequest(req, kwargs);
    this.captureError(err, kwargs, cb);
};

// The optional callback will be called with the error object after the
// error have been logged to Opbeat. If no callback have been provided
// we will automatically terminate the process, so if you provide a
// callback you must remember to terminate the process manually.
_.handleUncaughtExceptions = function (callback) {
    var client = this;

    process.on('uncaughtException', function (err) {
        log('opbeat: caught unhandled exception');
        log('opbeat:', err.stack);

        // Since we exit the node-process we cannot guarantee that the
        // listeners will be called, so to ensure a uniform result,
        // we'll remove all event listeners if an uncaught exception is
        // found
        client.removeAllListeners();

        var kwargs = {};
        if (client.exceptionsAreCritical) kwargs.level = 'fatal';
        client.captureError(err, kwargs, function (opbeatErr, url) {
            if (opbeatErr) {
                log('opbeat: could not notify service.');
                log('opbeat:', opbeatErr.stack);
            } else {
                log('opbeat: logged error successfully at ' + url);
            }
            callback ? callback(err) : process.exit(1);
        });
    });
};
<commit_msg>Don't output stacktrace twice<commit_after>var parsers = require('./parsers');
var zlib = require('zlib');
var transports = require('./transports');
var util = require('util');
var events = require('events');
var os = require('os');
var raw = require('raw-stacktrace');

var traces = raw({rawCallSites: true});
traces.setMaxListeners(100);
traces.on("trace", function (err, callsites) { err.structuredStackTrace = callsites; });

module.exports.version = require('../package.json').version;

module.exports.createClient = function (options) {
  return module.exports.client = new Client(options);
};

var log = function () {
  if (module.exports.client.silent) return;
  console.warn.apply(undefined, arguments);
};

var Client = function (options) {
    options = options || {};

    this.organization_id       = options.organization_id || process.env.OPBEAT_ORGANIZATION_ID;
    this.app_id                = options.app_id          || process.env.OPBEAT_APP_ID;
    this.secret_token          = options.secret_token    || process.env.OPBEAT_SECRET_TOKEN;
    this.env                   = options.env             || process.env.NODE_ENV || 'development';
    this.logger                = options.logger;
    this.hostname              = options.hostname || os.hostname();
    this.stackTraceLimit       = options.stackTraceLimit || Infinity; // To infinity and beyond
    this.handleExceptions      = 'handleExceptions' in options ? options.handleExceptions : true;
    this.silent                = 'silent' in options ? !!options.silent : false;
    this.exceptionsAreCritical = 'exceptionsAreCritical' in options ? !!options.exceptionsAreCritical : true;
    this.dsn                   = {
        protocol: 'https', // Opbeat currently only supports HTTPS. Future options might include HTTP and UDP
        host: 'opbeat.com',
        path: '/api/v1/organizations/' + this.organization_id + '/apps/' + this.app_id + '/errors/'
    };

    if (['development', 'test'].indexOf(this.env) !== -1) {
        console.warn('opbeat: [WARNING] logging is disabled while running in %s mode', this.env);
        this._enabled = false;
    } else if (!this.organization_id || !this.app_id || !this.secret_token) {
        console.warn('opbeat: [WARNING] logging is disabled. To enable, specify organization id, app id and opbeat token');
        this._enabled = false;
    } else {
        this._enabled = true;
    }

    if (this._enabled) {
        Error.stackTraceLimit = this.stackTraceLimit;

        if (this.handleExceptions) this.handleUncaughtExceptions();

        var client = this;
        this.on('connectionError', function (err) {
            log('opbeat: could not notify service.');
            log('opbeat:', err.stack);
        });
        this.on('error', function (err) {
            log('opbeat: could not notify service.');
            log('opbeat:', err.stack);
        });
        this.on('logged', function (url) {
            log('opbeat: logged error successfully at ' + url);
        });
    }
};
util.inherits(Client, events.EventEmitter);
var _ = Client.prototype;

_.process = function (kwargs, cb) {
    if (cb) {
        this.once('error', cb);
        this.once('connectionError', cb);
        this.once('logged', function (url) {
            cb(null, url);
        });
    }

    kwargs['machine'] = { hostname: this.hostname };
    kwargs['extra'] = kwargs['extra'] || {};
    kwargs['extra']['node'] = process.version;
    kwargs['timestamp'] = new Date().toISOString().split('.')[0];
    if (this.logger) kwargs['logger'] = this.logger;

    // this will happen asynchronously. We don't care about it's response.
    this._enabled && this.send(kwargs);
};

_.send = function (kwargs) {
    var client = this;
    zlib.deflate(JSON.stringify(kwargs), function (err, buff) {
        var headers = {
            'Authorization'  : 'Bearer ' + client.secret_token,
            'Content-Type'   : 'application/octet-stream',
            'Content-Length' : buff.length,
            'User-Agent'     : 'opbeat-nodejs/' + module.exports.version
        };
        transports[client.dsn.protocol].send(client, buff, headers);
    });
};

_.captureMessage = function (message, kwargs, cb) {
    if (!cb && typeof kwargs === 'function') {
        cb = kwargs;
        kwargs = {};
    } else {
        kwargs = kwargs || {};
    }
    if (typeof message === 'object') {
        // if `captureMessage` is parsed an object instead of a string we except
        // it to be in the format of `{ message: '...', params: [] }` and it will
        // be used as `param_message` instead of `message`
        kwargs['param_message'] = message;
        log.apply(undefined, ['opbeat: ' + message.message].concat(message.params));
    } else {
        kwargs = parsers.parseText(message, kwargs);
        log('opbeat: ' + message);
    }
    this.process(kwargs, cb);
};

_.captureError = function (err, kwargs, cb) {
    var client = this;

    if (!(err instanceof Error)) {
        // This handles when someone does:
        //   throw "something awesome";
        // We just send the "Error" as a normal message
        // since there is no way to compute a stack trace
        // See: https://github.com/mattrobenolt/raven-node/issues/18
        this.captureMessage('Error: ' + err, kwargs, cb);
        return;
    }

    if (!cb && typeof kwargs === 'function') {
        cb = kwargs;
        kwargs = {};
    } else {
        kwargs = kwargs || {};
    }

    log('opbeat: ' + err.stack);
    parsers.parseError(err, kwargs, function (kw) {
        client.process(kw, cb);
    });
};

_.captureRequestError = function (err, req, kwargs, cb) {
    if (!cb && typeof kwargs === 'function') {
        cb = kwargs;
        kwargs = {};
    } else {
        kwargs = kwargs || {};
    }

    kwargs = parsers.parseRequest(req, kwargs);
    this.captureError(err, kwargs, cb);
};

// The optional callback will be called with the error object after the
// error have been logged to Opbeat. If no callback have been provided
// we will automatically terminate the process, so if you provide a
// callback you must remember to terminate the process manually.
_.handleUncaughtExceptions = function (callback) {
    var client = this;

    process.on('uncaughtException', function (err) {
        log('opbeat: caught unhandled exception');

        // Since we exit the node-process we cannot guarantee that the
        // listeners will be called, so to ensure a uniform result,
        // we'll remove all event listeners if an uncaught exception is
        // found
        client.removeAllListeners();

        var kwargs = {};
        if (client.exceptionsAreCritical) kwargs.level = 'fatal';
        client.captureError(err, kwargs, function (opbeatErr, url) {
            if (opbeatErr) {
                log('opbeat: could not notify service.');
                log('opbeat:', opbeatErr.stack);
            } else {
                log('opbeat: logged error successfully at ' + url);
            }
            callback ? callback(err) : process.exit(1);
        });
    });
};
<|endoftext|>


<commit_before>// The onClicked callback function.
function onClickHandler(info, tab) {
    //console.log("item " + info.menuItemId + " was clicked");
    console.log("info: " + JSON.stringify(info));
    console.log("tab: " + JSON.stringify(tab));

    if (info.menuItemId == "citeTrove") {
        chrome.tabs.sendMessage(tab.id, {
            type : "cite"
        }, function(response) {
            console.log(chrome.runtime.lastError);
            console.log(response);
        });

        //console.log(tab.url);

        // console.log("START\n" + truncated_url + "\n" + today + "\n"
        //         + newspaper_title + "\n" + newspaper_issue + ", page "
        //         + newspaper_page + "\n[Quote]\n" + selection + "\n[Quote]\n")

        // document.execCommand('copy');
    } else {
        console.log('Not citeTrove');
    }

};

chrome.contextMenus.onClicked.addListener(onClickHandler);

//Set up context menu tree at install time.
chrome.runtime.onInstalled.addListener(function() {
    // Create one test item for each context type.
    chrome.contextMenus.create({
        "title" : "Cite Trove",
        "contexts" : [ "selection" ],
        "id" : "citeTrove",
        "documentUrlPatterns": ["http://trove.nla.gov.au/*"]
    });
});

// chrome.tabs.onUpdated.addListener(function(tabId, change, tab) {
//     console.log("tabId: " + JSON.stringify(tabId));
//     if (change.status == "complete") {
//         console.log(tab.url);
//     }
// });

// chrome.tabs.onSelectionChanged.addListener(function(tabId, info) {
//     console.log("tabId: " + JSON.stringify(tabId));
//     console.log("info: " + JSON.stringify(info));

// });

// chrome.pageAction.onClicked.addListener(function(tab) {
//     console.log(tab);
// });

chrome.runtime.onMessage.addListener(function(message) {
    if (message && message.type == "citation") {
        var input = document.createElement('textarea');
        document.body.appendChild(input);
        input.value = message.title;
        input.focus();
        input.select();
        document.execCommand('Copy');
        input.remove();
    }
});

// Called when the url of a tab changes.
function checkForValidUrl(tabId, changeInfo, tab) {
    // If the tabs url includes "trove.nla.gov.au"...
    if (tab.url.indexOf('trove.nla.gov.au') > -1) {
        // ... show the page action.
        chrome.pageAction.show(tabId);
    }
};

// Listen for any changes to the URL of any tab.
chrome.tabs.onUpdated.addListener(checkForValidUrl);
<commit_msg>Refactored. Use formatter. Use declarativeContent.<commit_after>/**
 * @author Chris Willoughby
 */

/**
 *
 */
function citeTroveResponseHandler(response) {
    console.log('Response received');
    console.log('\t' + chrome.runtime.lastError);
    console.log('\t' + JSON.stringify(response));
}

/**
 * The callback function for the citeTrove menu item.
 */
function onClickHandler(info, tab) {
    //console.log("item " + info.menuItemId + " was clicked");
    // console.log("info: " + JSON.stringify(info));
    // console.log("tab: " + JSON.stringify(tab));

    if (info.menuItemId == "citeTrove") {
        console.log('citeTrove pressed');
        chrome.tabs.sendMessage(
            tab.id,
            {type : "cite"},
            citeTroveResponseHandler);

        //console.log(tab.url);

        // console.log("START\n" + truncated_url + "\n" + today + "\n"
        //         + newspaper_title + "\n" + newspaper_issue + ", page "
        //         + newspaper_page + "\n[Quote]\n" + selection + "\n[Quote]\n")

        // document.execCommand('copy');
    } else {
        console.log('Not citeTrove menu item');
    }

};

/**
 *
 */
chrome.contextMenus.onClicked.addListener(onClickHandler);

// chrome.tabs.onUpdated.addListener(function(tabId, change, tab) {
//     console.log("tabId: " + JSON.stringify(tabId));
//     if (change.status == "complete") {
//         console.log(tab.url);
//     }
// });

// chrome.tabs.onSelectionChanged.addListener(function(tabId, info) {
//     console.log("tabId: " + JSON.stringify(tabId));
//     console.log("info: " + JSON.stringify(info));

// });

// chrome.pageAction.onClicked.addListener(function(tab) {
//     console.log(tab);
// });

/**
 *
 */
function formatAndCopy(message) {
    chrome.storage.sync.get({
        troveFormat: '%A%n%C%n%T%n%I, page %P%n[Quote]%n%Q%n[Quote]%n'
      }, function(items) {
        var input = document.createElement('textarea');
        document.body.appendChild(input);
        input.value = formatCitation(items.troveFormat, message);
        input.focus();
        input.select();
        document.execCommand('Copy');
        input.remove();

      });

}

/**
 *
 */
chrome.runtime.onMessage.addListener(function(message) {
    if (message && message.type == "citation") {
        formatAndCopy(message);
    }
});

/**
 *
 */
// A rule to show the pageAction on the trove.nla.gov.au site.
var pageActionRule = {
    conditions: [
        new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { hostEquals: 'trove.nla.gov.au', schemes: ['http', 'https'] }
        })
    ],
    actions: [ new chrome.declarativeContent.ShowPageAction() ]
};

/**
 *
 */
// When installed ...
chrome.runtime.onInstalled.addListener(function(details) {
    // ... set up context menu tree.
    chrome.contextMenus.create({
        "title" : "Cite Trove",
        "contexts" : [ "selection" ],
        "id" : "citeTrove",
        "documentUrlPatterns": ["http://trove.nla.gov.au/*"]
    });

    // ... and add a rule to show pageAction
    chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
        chrome.declarativeContent.onPageChanged.addRules([pageActionRule]);
    });
});

// // Called when the url of a tab changes.
// function checkForValidUrl(tabId, changeInfo, tab) {
//     // If the tabs url includes "trove.nla.gov.au"...
//     if (tab.url.indexOf('trove.nla.gov.au') > -1) {
//         // ... show the page action.
//         chrome.pageAction.show(tabId);
//     }
// };

// // Listen for any changes to the URL of any tab.
// chrome.tabs.onUpdated.addListener(checkForValidUrl);

<|endoftext|>


<commit_before>import {join} from 'path';
import webpack from 'webpack';

process.env.BABEL_ENV = 'browser';

function config(production) {
  return {
    devtool: production ? 'hidden-source-map' : 'eval-source-map',
    entry: './src/index.js',
    output: {
      path: join(__dirname, 'build'),
      library: 'WHS',
      libraryTarget: 'umd',
    },
    module: {
      loaders: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          loader: 'babel',
        },
      ],
    },
    plugins: production
      ? [
        new webpack.optimize.DedupePlugin(),
        new webpack.optimize.UglifyJsPlugin({
          mangle: false,
          compress: {
            warnings: false,
          },
        }),
      ]
      : [],
  };
}

export {
  config as default,
};
<commit_msg>Fix typo<commit_after>import {join} from 'path';
import webpack from 'webpack';

process.env.BABEL_ENV = 'browser';

function config(production) {
  return {
    devtool: production ? 'hidden-source-map' : 'eval-source-map',
    entry: './src/index.js',
    output: {
      path: join(__dirname, 'dist'),
      library: 'WHS',
      libraryTarget: 'umd',
    },
    module: {
      loaders: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          loader: 'babel',
        },
      ],
    },
    plugins: production
      ? [
        new webpack.optimize.DedupePlugin(),
        new webpack.optimize.UglifyJsPlugin({
          mangle: false,
          compress: {
            warnings: false,
          },
        }),
      ]
      : [],
  };
}

export {
  config as default,
};
<|endoftext|>


<commit_before>/**
 * @copyright Maichong Software Ltd. 2016 http://maichong.it
 * @date 2016-12-26
 * @author Liang <liang@maichong.it>
 */

'use strict';

var stringify = require('qs/lib/stringify');
var Query = require('./query');

// 有效HTTP方法列表
var methods = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'TRACE', 'CONNECT'];

var instances = {};

function resolve(key) {
  if (!instances[key]) {
    instances[key] = create();
  }
  return instances[key];
}

function create(options) {
  const client = function client(path) {
    return new Query(path, client);
  };

  client.options = options || {};

  client.create = create;
  client.resolve = resolve;
  client.setOptions = function (options) {
    client.options = Object.assign({}, client.options, options);
  };

  client.request = function request(path, init) {
    init = init || {};
    if (init.params) {
      path += '?' + stringify(init.params);
    }

    if (init.body && typeof init.body === 'object') {
      if (!init.headers) {
        init.headers = {};
      }
      if (!init.headers['Content-Type']) {
        init.headers['Content-Type'] = 'application/json';
        init.body = JSON.stringify(init.body);
      } else if (init.headers['Content-Type'] === 'application/x-www-form-urlencoded') {
        init.body = stringify(init.body);
      }
    }

    if (client.options.init) {
      init = Object.assign({}, client.options.init, init);
    }

    if (client.options.apiRoot) {
      path = client.options.apiRoot + path;
    }

    var fetch = client.options.fetch;

    if (!fetch) {
      if (typeof window !== 'undefined') {
        fetch = window.fetch;
      } else if (typeof global !== 'undefined') {
        fetch = global.fetch;
      } else if (typeof self !== 'undefined') {
        fetch = self.fetch;
      }
    }

    var responsePromise = fetch(path, init);
    var resultPromise = null;
    var r = {};
    r.then = function (onSuccess, onFail) {
      if (!resultPromise) {
        resultPromise = r.response().then(function (response) {
          return response.json().then(function (data) {
            if (data && data.error && ['0', 'null', 'none'].indexOf(data.error) > -1) {
              var error = new Error(data.error);
              error.code = data.code || data.errorCode || 0;
              return Promise.reject(error)
            }
            return Promise.resolve(data);
          });
        });
      }
      return resultPromise.then(onSuccess, onFail);
    };
    r.catch = function (onFail) {
      return r.then(null, onFail);
    };
    r.response = function () {
      return responsePromise;
    };
    return r;
  };

  methods.forEach(function (method) {
    client[method.toLowerCase()] = function (path, init) {
      init = init || {};
      init.method = method;
      return client.request(path, init);
    }
  });

  return client;
}

module.exports = create();
<commit_msg>throw error<commit_after>/**
 * @copyright Maichong Software Ltd. 2016 http://maichong.it
 * @date 2016-12-26
 * @author Liang <liang@maichong.it>
 */

'use strict';

var stringify = require('qs/lib/stringify');
var Query = require('./query');

// 有效HTTP方法列表
var methods = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'TRACE', 'CONNECT'];

var instances = {};

function resolve(key) {
  if (!instances[key]) {
    instances[key] = create();
  }
  return instances[key];
}

function create(options) {
  const client = function client(path) {
    return new Query(path, client);
  };

  client.options = options || {};

  client.create = create;
  client.resolve = resolve;
  client.setOptions = function (options) {
    client.options = Object.assign({}, client.options, options);
  };

  client.request = function request(path, init) {
    init = init || {};
    if (init.params) {
      path += '?' + stringify(init.params);
    }

    if (init.body && typeof init.body === 'object') {
      if (!init.headers) {
        init.headers = {};
      }
      if (!init.headers['Content-Type']) {
        init.headers['Content-Type'] = 'application/json';
        init.body = JSON.stringify(init.body);
      } else if (init.headers['Content-Type'] === 'application/x-www-form-urlencoded') {
        init.body = stringify(init.body);
      }
    }

    if (client.options.init) {
      init = Object.assign({}, client.options.init, init);
    }

    if (client.options.apiRoot) {
      path = client.options.apiRoot + path;
    }

    var fetch = client.options.fetch;

    if (!fetch) {
      if (typeof window !== 'undefined') {
        fetch = window.fetch;
      } else if (typeof global !== 'undefined') {
        fetch = global.fetch;
      } else if (typeof self !== 'undefined') {
        fetch = self.fetch;
      }
    }

    var responsePromise = fetch(path, init);
    var resultPromise = null;
    var r = {};
    r.then = function (onSuccess, onFail) {
      if (!resultPromise) {
        resultPromise = r.response().then(function (response) {
          return response.json().then(function (data) {
            if (data && data.error && ['0', 'null', 'none'].indexOf(data.error) < 0) {
              var error = new Error(data.error);
              error.code = data.code || data.errorCode || 0;
              return Promise.reject(error)
            }
            return Promise.resolve(data);
          });
        });
      }
      return resultPromise.then(onSuccess, onFail);
    };
    r.catch = function (onFail) {
      return r.then(null, onFail);
    };
    r.response = function () {
      return responsePromise;
    };
    return r;
  };

  methods.forEach(function (method) {
    client[method.toLowerCase()] = function (path, init) {
      init = init || {};
      init.method = method;
      return client.request(path, init);
    }
  });

  return client;
}

module.exports = create();
<|endoftext|>


<commit_before>"use strict";

var browser = browser || chrome;//for Chrome

const CONTEXT_MENU_ITEM_ROOT_ID = "root";
const CONTEXT_MENU_ITEM_EMPTY_ID = "empty";
const CONTEXT_MENU_ITEM_UNTITLED = browser.i18n.getMessage("contextMenuItemUntitled");
const FOLDERS_GROUP_TITLES_SEP = " ▸ ";
const BOOKMARK_TREE_CHANGES_EVENTS = ["onCreated", "onRemoved", "onChanged", "onMoved", "onChildrenReordered"];
const BOOKMARK_TREE_CHANGES_DELAY = 1000;//ms
const PREF_FLAT_CONTEXT_MENU = "flatContextMenu";

//browser.runtime.lastError

class Bookmarklet{
	constructor(source = "", title = ""){
		this.source = source;
		this.title = title;
	}
}

class BookmarkletFolder{
	constructor(children = [], title = ""){
		this.children = children;
		this.title = title;
	}
}

class BookmarkletFolderGroup extends BookmarkletFolder{
	constructor(folders = [], children = [], title = ""){
		super(children, title);
		this.folders = folders;
	}
}

/**
 * Create bookmarklet tree from given bookmark
 * @returns {Bookmarklet|BookmarkletFolder|BookmarkletFolderGroup|null}
 */
function getBookmarkletTree(bookmark){
	let title = bookmark.title || CONTEXT_MENU_ITEM_UNTITLED;

	// If not a folder
	if(!bookmark.children){
		let url = bookmark.url;
		if(url && url.startsWith("javascript:")){
			let source;
			try{
				source = decodeURIComponent(url.slice(11)).trim()
			}catch(error){}

			if(source){
				return new Bookmarklet(source, title);
			}
		}

		return null;
	}

	let children = bookmark.children.map(getBookmarkletTree).filter(value => value !== null);
	if(children.length == 0){
		return null;
	}

	let folder = new BookmarkletFolder(children, title);

	// Nested folders
	if(children.length == 1 && children[0] instanceof BookmarkletFolder){
		let solitaryFolder = children[0];

		// Already a group
		if(solitaryFolder instanceof BookmarkletFolderGroup){
			folder.children[0] = solitaryFolder.folders[0];// fix the tree
			solitaryFolder.folders.unshift(folder);// group that folder too
			solitaryFolder.title = solitaryFolder.folders.map(folder => folder.title).join(FOLDERS_GROUP_TITLES_SEP);
			return solitaryFolder;
		}

		return new BookmarkletFolderGroup([folder, solitaryFolder], solitaryFolder.children, folder.title + FOLDERS_GROUP_TITLES_SEP + solitaryFolder.title);
	}

	return folder;
}

/**
 * Handle context menu click event
 * Execute corresponding bookmarklet script
 */
function contextMenuItemClick(bookmarklet, data, tab){
	/*
	executeScript can be rejected for host mismatch: "Error: No window matching {"matchesHost":[]}"
	or privilegied URIs like: chrome://* *://addons.mozilla.org/
	See https://bugzilla.mozilla.org/show_bug.cgi?id=1310082

	executeScript can be rejected for script error (syntax or privilege)
	*/
	browser.tabs.executeScript({
		code: bookmarklet.source,
		runAt: "document_start"
	}).then(framesReturnValues => {
		let topFrameRetunValue = framesReturnValues[0];
		// top frame retunValue is undefined (void)
		if(topFrameRetunValue === undefined){
			// Do nothing
			return;
		}

		// Redirect to document generated by the result of evaluated script
		// We can't use browser.tabs.update({url}) because data: URI aren't allowed
		return browser.tabs.executeScript({
			code: `location = "data:text/html;charset=utf-8,${encodeURIComponent(topFrameRetunValue)}";`,
			runAt: "document_start"
		});
	});
}

/**
 * Create all context menu for the given bookmarklet tree
 */
function createAllContextMenuItems(bookmarklets, flat = false){
	// Remove all remains context menu
	browser.contextMenus.removeAll();

	let bookmarkletsRoot = bookmarklets[0];
	// add root context menu
	let parentID = browser.contextMenus.create({
		id: CONTEXT_MENU_ITEM_ROOT_ID,
		title: browser.i18n.getMessage("contextMenuItemRoot"),
		contexts: ["all"]
	});

	// If no bookmarklets
	if(!bookmarkletsRoot || bookmarkletsRoot instanceof BookmarkletFolder && bookmarkletsRoot.children.length == 0){
		browser.contextMenus.create({
			id: CONTEXT_MENU_ITEM_EMPTY_ID,
			title: browser.i18n.getMessage("contextMenuItemEmpty"),
			parentId: parentID,
			contexts: ["all"]
		});
		return;
	}

	// If only one folder (or folder group) list direcly its children
	if(bookmarkletsRoot instanceof BookmarkletFolder){
		bookmarkletsRoot.children.map(child => createContextMenuItems(child, parentID, flat));
	} else {
		createContextMenuItems(bookmarkletsRoot, parentID, flat);
	}
}

/**
 * Create a context menu entry for the given bookmarklet
 */
function createContextMenuItems(bookmarklet, parentContextMenuID, flat = false){
	if(bookmarklet instanceof BookmarkletFolder){
		let parentID = parentContextMenuID;
		if(!flat){
			parentID = browser.contextMenus.create({
				title: bookmarklet.title,
				parentId: parentContextMenuID,
				contexts: ["all"]
			});
		}
		bookmarklet.children.map(child => createContextMenuItems(child, parentID, flat));
		return;
	}

	let contextMenuId = browser.contextMenus.create({
		title: bookmarklet.title,
		parentId: parentContextMenuID,
		onclick: contextMenuItemClick.bind(null, bookmarklet),
		contexts: ["all"]
	});
}

/**
 * Build or rebuild the context menu
 * @returns Promise
 */
function updateContextMenu(){
	return browser.storage.local.get(PREF_FLAT_CONTEXT_MENU).then(result => {
		let flat = Boolean(result[PREF_FLAT_CONTEXT_MENU]);
		return gettingBookmarkletTree.then(bookmarklets => createAllContextMenuItems(bookmarklets, flat));
	})
}

/**
 * Update all data: the bookmarklet tree and context menu items
 * @returns Promise
 */
function update(){
	gettingBookmarkletTree = browser.bookmarks.getTree().then(bookmarks => [getBookmarkletTree(bookmarks[0])]);
	return updateContextMenu();
}

/**
 * Bookmark tree events handler throttle / debounce function
 */
function updateDebounced(){
	if(updateTimeoutID){
		// Wait to update timeout
		return;
	}

	updateTimeoutID = setTimeout(() => {
		updateTimeoutID = 0;
		update.apply(this);
	}, BOOKMARK_TREE_CHANGES_DELAY);
}

let updateTimeoutID = 0;
let gettingBookmarkletTree = null//Promise.reject("Not initialized");

// Inert context menu (disabled). Wait bookmarks retrival
browser.contextMenus.create({
	id: CONTEXT_MENU_ITEM_ROOT_ID,
	title: browser.i18n.getMessage("contextMenuItemRoot"),
	contexts: ["all"],
	enabled: false
});

// Add bookmark tree changes event listeners
// Don't handle onImportBegan and onImportEnded, but because we debounce (delay) update, it should be fine
{
	const bookmarks = browser.bookmarks;
	for(let event of BOOKMARK_TREE_CHANGES_EVENTS){
		// Event not supported
		if(!(event in bookmarks) || typeof bookmarks[event].addListener != "function"){
			continue;
		}

		bookmarks[event].addListener(updateDebounced);
	}
}

update();

// Listen preferences changes
browser.storage.onChanged.addListener((changes, areaName) => {
	// Ignore all others storage areas
	if(areaName != "local"){
		return;
	}

	let flatPrefChange = changes[PREF_FLAT_CONTEXT_MENU];
	if(flatPrefChange && flatPrefChange.oldValue != flatPrefChange.newValue){
		updateContextMenu();
	}
})<commit_msg>Add folder separators for flat context menu<commit_after>"use strict";

var browser = browser || chrome;//for Chrome

const CONTEXT_MENU_ITEM_ROOT_ID = "root";
const CONTEXT_MENU_ITEM_EMPTY_ID = "empty";
const CONTEXT_MENU_ITEM_UNTITLED = browser.i18n.getMessage("contextMenuItemUntitled");
const FOLDERS_GROUP_TITLES_SEP = " ▸ ";
const BOOKMARK_TREE_CHANGES_EVENTS = ["onCreated", "onRemoved", "onChanged", "onMoved", "onChildrenReordered"];
const BOOKMARK_TREE_CHANGES_DELAY = 1000;//ms
const PREF_FLAT_CONTEXT_MENU = "flatContextMenu";

//browser.runtime.lastError

class Bookmarklet{
	constructor(source = "", title = ""){
		this.source = source;
		this.title = title;
	}
}

class BookmarkletFolder{
	constructor(children = [], title = ""){
		this.children = children;
		this.title = title;
	}
}

class BookmarkletFolderGroup extends BookmarkletFolder{
	constructor(folders = [], children = [], title = ""){
		super(children, title);
		this.folders = folders;
	}
}

/**
 * Create bookmarklet tree from given bookmark
 * @returns {Bookmarklet|BookmarkletFolder|BookmarkletFolderGroup|null}
 */
function getBookmarkletTree(bookmark){
	let title = bookmark.title || CONTEXT_MENU_ITEM_UNTITLED;

	// If not a folder
	if(!bookmark.children){
		let url = bookmark.url;
		if(url && url.startsWith("javascript:")){
			let source;
			try{
				source = decodeURIComponent(url.slice(11)).trim()
			}catch(error){}

			if(source){
				return new Bookmarklet(source, title);
			}
		}

		return null;
	}

	let children = bookmark.children.map(getBookmarkletTree).filter(value => value !== null);
	if(children.length == 0){
		return null;
	}

	let folder = new BookmarkletFolder(children, title);

	// Nested folders
	if(children.length == 1 && children[0] instanceof BookmarkletFolder){
		let solitaryFolder = children[0];

		// Already a group
		if(solitaryFolder instanceof BookmarkletFolderGroup){
			folder.children[0] = solitaryFolder.folders[0];// fix the tree
			solitaryFolder.folders.unshift(folder);// group that folder too
			solitaryFolder.title = solitaryFolder.folders.map(folder => folder.title).join(FOLDERS_GROUP_TITLES_SEP);
			return solitaryFolder;
		}

		return new BookmarkletFolderGroup([folder, solitaryFolder], solitaryFolder.children, folder.title + FOLDERS_GROUP_TITLES_SEP + solitaryFolder.title);
	}

	return folder;
}

/**
 * Handle context menu click event
 * Execute corresponding bookmarklet script
 */
function contextMenuItemClick(bookmarklet, data, tab){
	/*
	executeScript can be rejected for host mismatch: "Error: No window matching {"matchesHost":[]}"
	or privilegied URIs like: chrome://* *://addons.mozilla.org/
	See https://bugzilla.mozilla.org/show_bug.cgi?id=1310082

	executeScript can be rejected for script error (syntax or privilege)
	*/
	browser.tabs.executeScript({
		code: bookmarklet.source,
		runAt: "document_start"
	}).then(framesReturnValues => {
		let topFrameRetunValue = framesReturnValues[0];
		// top frame retunValue is undefined (void)
		if(topFrameRetunValue === undefined){
			// Do nothing
			return;
		}

		// Redirect to document generated by the result of evaluated script
		// We can't use browser.tabs.update({url}) because data: URI aren't allowed
		return browser.tabs.executeScript({
			code: `location = "data:text/html;charset=utf-8,${encodeURIComponent(topFrameRetunValue)}";`,
			runAt: "document_start"
		});
	});
}

/**
 * Create all context menu for the given bookmarklet tree
 */
function createAllContextMenuItems(bookmarklets, flat = false){
	// Remove all remains context menu
	browser.contextMenus.removeAll();

	let bookmarkletsRoot = bookmarklets[0];
	// add root context menu
	let parentID = browser.contextMenus.create({
		id: CONTEXT_MENU_ITEM_ROOT_ID,
		title: browser.i18n.getMessage("contextMenuItemRoot"),
		contexts: ["all"]
	});

	// If no bookmarklets
	if(!bookmarkletsRoot || bookmarkletsRoot instanceof BookmarkletFolder && bookmarkletsRoot.children.length == 0){
		browser.contextMenus.create({
			id: CONTEXT_MENU_ITEM_EMPTY_ID,
			title: browser.i18n.getMessage("contextMenuItemEmpty"),
			parentId: parentID,
			contexts: ["all"]
		});
		return;
	}

	let emptyParent = true;
	// If only one folder (or folder group) list direcly its children
	if(bookmarkletsRoot instanceof BookmarkletFolder){
		for(let child of bookmarkletsRoot.children){
			createContextMenuItems(child, parentID, flat, emptyParent);
			emptyParent = true;
		}
	} else {
		createContextMenuItems(bookmarkletsRoot, parentID, flat, emptyParent);
	}
}

/**
 * Create a context menu entry for the given bookmarklet
 */
function createContextMenuItems(bookmarklet, parentContextMenuID, flat = false, emptyParent = true){
	// If a folder of bookmarklets
	if(bookmarklet instanceof BookmarkletFolder){
		let parentID = parentContextMenuID;
		let children = bookmarklet.children;

		if(children.length == 0){
			return;
		}

		if(!flat){
			parentID = browser.contextMenus.create({
				title: bookmarklet.title,
				parentId: parentContextMenuID,
				contexts: ["all"]
			});
			emptyParent = true;
		}

		if(flat && emptyParent){
			browser.contextMenus.create({
				type: "separator",
				parentId: parentContextMenuID,
				contexts: ["all"]
			});
			emptyParent = false;
		}

		for(let child of children){
			createContextMenuItems(child, parentID, flat, emptyParent);
			emptyParent = true;
		}

		return;
	}

	browser.contextMenus.create({
		title: bookmarklet.title,
		parentId: parentContextMenuID,
		onclick: contextMenuItemClick.bind(null, bookmarklet),
		contexts: ["all"]
	});
}

/**
 * Build or rebuild the context menu
 * @returns Promise
 */
function updateContextMenu(){
	return Promise.all([gettingBookmarkletTree, gettingFlatPref]).then(([bookmarklets, flat]) => createAllContextMenuItems(bookmarklets, flat));
}

/**
 * Get the bookmarklet tree
 * @returns Promise
 */
function getBookmarkletTreePromise(){
	return browser.bookmarks.getTree().then(bookmarks => [getBookmarkletTree(bookmarks[0])]);
}

/**
 * Bookmark tree events handler throttle / debounce function
 */
function updateDebounced(){
	if(updateTimeoutID){
		// Wait to update timeout
		return;
	}

	updateTimeoutID = setTimeout(() => {
		updateTimeoutID = 0;
		gettingBookmarkletTree = gettingBookmarkletTree();// update bookmarklet tree
		updateContextMenu();
	}, BOOKMARK_TREE_CHANGES_DELAY);
}

let updateTimeoutID = 0;
// Promise for flat context menu perference
var gettingFlatPref = browser.storage.local.get(PREF_FLAT_CONTEXT_MENU).then(result => Boolean(result[PREF_FLAT_CONTEXT_MENU]));
// Promise for bookmarklet tree. The first time is set, enable browser action
var gettingBookmarkletTree = getBookmarkletTreePromise().then(bookmarklets => (browser.browserAction.enable(), bookmarklets));

// Inert context menu (disabled). Wait bookmarks retrival
browser.contextMenus.create({
	id: CONTEXT_MENU_ITEM_ROOT_ID,
	title: browser.i18n.getMessage("contextMenuItemRoot"),
	contexts: ["all"],
	enabled: false
});
// Disable browser action. Wait bookmarks retrival
browser.browserAction.disable();

// Add bookmark tree changes event listeners
// Don't handle onImportBegan and onImportEnded, but because we debounce (delay) update, it should be fine
{
	const bookmarks = browser.bookmarks;
	for(let event of BOOKMARK_TREE_CHANGES_EVENTS){
		// Event not supported
		if(!(event in bookmarks) || typeof bookmarks[event].addListener != "function"){
			continue;
		}

		bookmarks[event].addListener(updateDebounced);
	}
}

// Listen preferences changes
browser.storage.onChanged.addListener((changes, areaName) => {
	// Ignore all others storage areas
	if(areaName != "local"){
		return;
	}

	let flatPrefChange = changes[PREF_FLAT_CONTEXT_MENU];
	if(flatPrefChange && flatPrefChange.oldValue != flatPrefChange.newValue){
		gettingFlatPref = Promise.resolve(Boolean(flatPrefChange.newValue));
		update();
	}
});

// Start
updateContextMenu();<|endoftext|>


<commit_before>import path from "path";
import webpack from "webpack";
import CaseSensitivePathsPlugin from "case-sensitive-paths-webpack-plugin";
import CircularDependencyPlugin from "circular-dependency-plugin";
import DuplicatePackageCheckerPlugin from "duplicate-package-checker-webpack-plugin";
import HappyPack from "happypack";
import TerserPlugin from "terser-webpack-plugin";

const NODE_ENV = process.env.NODE_ENV ? "production" : "development";
const isDevelopment = NODE_ENV === "development";

let options = {
  mode: NODE_ENV,
  entry: ["./helpers/polyfills.js", "./main.js"],
  output: {
    filename: "[name].js",
    path: path.join(__dirname, "/dest/assets/javascripts"),
    publicPath: "/assets/javascripts/",
    library: "App"
  },
  resolve: {
    modules: ["node_modules", path.join(__dirname, "soruce")],
    alias: {
      "lodash-es": "lodash",
      "@": path.resolve(__dirname, "source")
    }
  },
  devtool: isDevelopment ? "eval-source-map" : "source-map",
  context: path.resolve(__dirname, "source/scripts"),
  optimization: {
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          parse: {
            ecma: 8
          },
          compress: {
            ecma: 5,
            warnings: false,
            comparisons: false,
            inline: 2
          },
          mangle: {
            safari10: true
          },
          output: {
            ecma: 5,
            comments: false,
            ascii_only: true
          }
        },
        parallel: true,
        cache: true,
        sourceMap: true
      })
    ]
  },
  module: {
    noParse: /\/node_modules\/(jquery|backbone)/,
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "happypack/loader"
        }
      }
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      "process.env.NODE_ENV": JSON.stringify(NODE_ENV)
    }),
    new CaseSensitivePathsPlugin(),
    new CircularDependencyPlugin({
      // exclude detection of files based on a RegExp
      exclude: /a\.js|node_modules/,
      // add errors to webpack instead of warnings
      failOnError: true
    }),
    new DuplicatePackageCheckerPlugin(),
    new HappyPack({
      loaders: ["babel-loader"]
    })
  ]
};

export default options;
<commit_msg>Update webpack config<commit_after>import path from "path";
import webpack from "webpack";
import CaseSensitivePathsPlugin from "case-sensitive-paths-webpack-plugin";
import CircularDependencyPlugin from "circular-dependency-plugin";
import DuplicatePackageCheckerPlugin from "duplicate-package-checker-webpack-plugin";
import HappyPack from "happypack";
import TerserPlugin from "terser-webpack-plugin";

const NODE_ENV = process.env.NODE_ENV ? "production" : "development";
const isDevelopment = NODE_ENV === "development";

const options = {
  mode: NODE_ENV,
  entry: ["./helpers/polyfills.js", "./main.js"],
  output: {
    filename: "[name].js",
    path: path.join(__dirname, "/dest/assets/javascripts"),
    publicPath: "/assets/javascripts/",
    library: "App",
  },
  resolve: {
    modules: ["node_modules", path.join(__dirname, "soruce")],
    alias: {
      "lodash-es": "lodash",
      "@": path.resolve(__dirname, "source"),
    },
  },
  devtool: isDevelopment ? "eval-source-map" : "source-map",
  context: path.resolve(__dirname, "source/scripts"),
  optimization: {
    minimize: !isDevelopment,
    minimizer: [new TerserPlugin()],
  },
  module: {
    noParse: /\/node_modules\/(jquery|backbone)/,
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "happypack/loader",
        },
      },
    ],
  },
  plugins: [
    new webpack.DefinePlugin({
      "process.env.NODE_ENV": JSON.stringify(NODE_ENV),
    }),
    new CaseSensitivePathsPlugin(),
    new CircularDependencyPlugin({
      // exclude detection of files based on a RegExp
      exclude: /a\.js|node_modules/,
      // add errors to webpack instead of warnings
      failOnError: true,
    }),
    new DuplicatePackageCheckerPlugin(),
    new HappyPack({
      loaders: ["babel-loader"],
    }),
  ],
};

export default options;
<|endoftext|>