<commit_before>const _ = require('lodash');
const moment = require('moment');
const debug = require('debug')('lib:glue');
const reportDuplicate = require('debug')('lib:glue:duplicate!');
const nconf = require('nconf');
const Promise = require('bluebird');
const request = Promise.promisifyAll(require('request'));

const mongo = require('./mongo');
const params = require('./params');

/* these functions are used in:
 *  bin/importfreshsample
 * because it download a random timeline and import in the local db
 *
 * and `parsers/unique` (via lib/parse), because when a requested ID is not found,
 * is downloaded with the function glue.retrive
 *
 * the api is /api/v1/glue/$password/$samplesize
 */

function importer(content) {
    const htmlCleanFields = [ 'savingTime', 'id', 'userId',
        'impressionId', 'timelineId', 'html' ];

    var timeline = content[2];
    timeline.startTime = new Date(content[2].startTime);
    var impressions = _.map(content[0], function(i) {
        i.impressionTime = new Date(i.impressionTime);
        return i;
    });
    var htmls = _.map(content[1], function(h) {
        var clean = _.pick(h, htmlCleanFields);
        clean.savingTime = new Date(clean.savingTime);
        return clean;
    });

    if(!_.size(htmls) || !_.size(impressions)) {
        debug("Found an empty timeline! (%s) nothing to save.",
            content[2].id);
        return [ null, [], [] ];
    }
    debug("Ready with a timeline with %d impressions and %d htmls",
        _.size(impressions), _.size(htmls));

    /* because one writing operation might fail for
     * duplicated Id the operation are separated */
    return [ timeline, impressions, htmls ];
}

function writeTimeline(blob) {
    if(blob[0] && _.get(blob[0], 'id')) {
        return mongo
            .writeOne(nconf.get('schema').timelines, blob[0])
            .catch(duplicatedError)
            .return(blob);
    } else
        throw new Error("Nothing to do here");
}

function writeImpressions(blob) {
    var counter = 0;
    return Promise.map(blob[1], function(impression) {
        return mongo
            .writeOne(nconf.get('schema').impressions, impression)
            .tap(function() { counter++; })
            .catch(duplicatedError);
    }, { concurrency: 1} )
    .tap(function() {
        if(_.size(blob[1])) {
            if(!counter)
                reportDuplicate("timeline already saved");
            else
                debug("Written %d impressions", counter);
        }
    })
    .return(blob);
}

function writeHtmls(blob) {
    return Promise.map(blob[2], function(html) {
        _.unset(html, 'processed');
        /* this hack and updateSupporter, are necessary to make run the test with bin/parserv.js */
        html.savingTime = new Date();
        return mongo
            .writeOne(nconf.get('schema').htmls, html)
            .catch(duplicatedError);
    }, { concurrency: 1} )
    .return(blob);
}

function duplicatedError(error) {
    if(error.code !== 11000) {
        debug("unexpected error?\n%s", error.message);
        console.log(error.stack);
        process.exit(0);
    }
}

function updateSupporter(blob) {
    if(blob[0]) {
        var userId = blob[0].userId;
        return mongo
            .readOne(nconf.get('schema').supporters, { userId: userId })
            .then(function(found) {
                if(!found) found = { userId };
                return _.set(found, 'lastActivity', new Date());
            })
            .then(function(updated) {
                return mongo
                    .upsertOne(nconf.get('schema').supporters, { userId: updated.userId }, updated);
            });
    };
};

function retrive(htmlfilter) {
    const url = ( nconf.get('server') || 'https://testing.tracking.exposed' ) + '/api/v2/debug/html/' + htmlfilter.id;
    debug("Remotely retrive the HTML content (%s)", url);
    return request
        .getAsync(url)
        .then(function(res) {
            return res.body;
        })
        .then(JSON.parse)
        .then(function(x) {
            debug("Importing the HTML %s (%s | %s) impressionOrder %d",
                x.impression.htmlId,
                moment.duration(moment(x.impression.impressionTime) - moment()).humanize(),
                x.timeline.geoip,
                x.impression.impressionOrder
            );
            return [ x.timeline, [ x.impression ] , [ x.html ] ];
        });
};

function writers(blob) {
    debug("Ready to write %d total bytes", _.size(JSON.stringify(blob)));
    return writeTimeline(blob)
        .tap(writeImpressions)
        .tap(updateSupporter)
        .then(writeHtmls)
        .catch(function(error) {
            debug("Impossible to write: %s", error.message);
        });
};

module.exports = {
    importer: importer,
    writers: writers,
    retrive: retrive
};
<commit_msg>aligned glue.js to API v2<commit_after>const _ = require('lodash');
const moment = require('moment');
const debug = require('debug')('lib:glue');
const reportDuplicate = require('debug')('lib:glue:duplicate!');
const nconf = require('nconf');
const Promise = require('bluebird');
const request = Promise.promisifyAll(require('request'));

const mongo = require('./mongo');
const params = require('./params');

/* these functions are used in:
 *  bin/importfreshsample
 * because it download a random timeline and import in the local db
 *
 * and `parsers/unique` (via lib/parse), because when a requested ID is not found,
 * is downloaded with the function glue.retrive
 *
 * the api is /api/v1/glue/$password/$samplesize
 */

function importer(content) {
    const htmlCleanFields = [ 'savingTime', 'id', 'userId',
        'impressionId', 'timelineId', 'html' ];

    var timeline = content[2];
    timeline.startTime = new Date(content[2].startTime);
    var impressions = _.map(content[0], function(i) {
        i.impressionTime = new Date(i.impressionTime);
        return i;
    });
    var htmls = _.map(content[1], function(h) {
        var clean = _.pick(h, htmlCleanFields);
        clean.savingTime = new Date(clean.savingTime);
        return clean;
    });

    if(!_.size(htmls) || !_.size(impressions)) {
        debug("Found an empty timeline! (%s) nothing to save.",
            content[2].id);
        return [ null, [], [] ];
    }
    debug("Ready with a timeline with %d impressions and %d htmls",
        _.size(impressions), _.size(htmls));

    /* because one writing operation might fail for
     * duplicated Id the operation are separated */
    return [ timeline, impressions, htmls ];
}

function writeTimeline(blob) {
    if(blob[0] && _.get(blob[0], 'id')) {
        return mongo
            .writeOne(nconf.get('schema').timelines, blob[0])
            .catch(duplicatedError)
            .return(blob);
    } else
        throw new Error("Nothing to do here");
}

function writeImpressions(blob) {
    var counter = 0;
    return Promise.map(blob[1], function(impression) {
        return mongo
            .writeOne(nconf.get('schema').impressions, impression)
            .tap(function() { counter++; })
            .catch(duplicatedError);
    }, { concurrency: 1} )
    .tap(function() {
        if(_.size(blob[1])) {
            if(!counter)
                reportDuplicate("timeline already saved");
            else
                debug("Written %d impressions", counter);
        }
    })
    .return(blob);
}

function writeHtmls(blob) {
    return Promise.map(blob[2], function(html) {
        _.unset(html, 'processed');
        /* this hack and updateSupporter, are necessary to make run the test with bin/parserv.js */
        html.savingTime = new Date();
        return mongo
            .writeOne(nconf.get('schema').htmls, html)
            .catch(duplicatedError);
    }, { concurrency: 1} )
    .return(blob);
}

function duplicatedError(error) {
    if(error.code !== 11000) {
        debug("unexpected error?\n%s", error.message);
        console.log(error.stack);
        process.exit(0);
    }
}

function updateSupporter(blob) {
    if(blob[0]) {
        var userId = blob[0].userId;
        return mongo
            .readOne(nconf.get('schema').supporters, { userId: userId })
            .then(function(found) {
                if(!found) found = { userId };
                return _.set(found, 'lastActivity', new Date());
            })
            .then(function(updated) {
                return mongo
                    .upsertOne(nconf.get('schema').supporters, { userId: updated.userId }, updated);
            });
    };
};

function retrive(htmlfilter) {
    const url = ( nconf.get('server') || 'https://facebook.tracking.exposed' ) + '/api/v2/debug/html/' + htmlfilter.id;
    debug("Remotely retrive the HTML content (%s)", url);
    return request
        .getAsync(url)
        .then(function(res) {
            return res.body;
        })
        .then(JSON.parse)
        .then(function(x) {
            debug("Importing the HTML %s (%s | %s) impressionOrder %d",
                x.impression.htmlId,
                moment.duration(moment(x.impression.impressionTime) - moment()).humanize(),
                x.timeline.geoip,
                x.impression.impressionOrder
            );
            return [ x.timeline, [ x.impression ] , [ x.html ] ];
        });
};

function writers(blob) {
    debug("Ready to write %d total bytes", _.size(JSON.stringify(blob)));
    return writeTimeline(blob)
        .tap(writeImpressions)
        .tap(updateSupporter)
        .then(writeHtmls)
        .catch(function(error) {
            debug("Impossible to write: %s", error.message);
        });
};

module.exports = {
    importer: importer,
    writers: writers,
    retrive: retrive
};
<|endoftext|>


<commit_before>(function() {
    var identifierCounter = 0;
    var generateIdentifier = function() {
        return ""+(+new Date())+":"+(identifierCounter++);
    };
    window.WonderPushInAppSDK = new Proxy({}, new function() {
        this.get = function(target, prop, receiver) {
            if (this.hasOwnProperty(prop)) return this[prop];
            return function() {
                var callId = generateIdentifier();
                webkit.messageHandlers.WonderPushInAppSDK.postMessage({
                    method : prop,
                    args: Array.from(arguments),
                    callId: callId,
                });
                return new Promise(function(res, rej) {
                    window.WonderPushInAppSDK.callIdToPromise[callId] = {resolve:res, reject:rej};
                });
            };
        }.bind(this);
        this.callIdToPromise = {};
        this.resolve =  function(result, callId) {
            var promise = window.WonderPushInAppSDK.callIdToPromise[callId];
            if (!promise || !promise.resolve) return;
            promise.resolve(result);
            delete window.WonderPushInAppSDK.callIdToPromise[callId];
        };
        this.reject = function(error, callId) {
            var promise = window.WonderPushInAppSDK.callIdToPromise[callId];
            if (!promise || !promise.reject) return;
            promise.reject(error);
            delete window.WonderPushInAppSDK.callIdToPromise[callId];
        };
    });

    // Executed when the window is loaded
    var onload = function() {
        // Register event listeners on data-wonderpush-button-label elements
        document.querySelectorAll('*[data-wonderpush-button-label]').forEach(function(elt) {
            var buttonLabel = elt.dataset.wonderpushButtonLabel;
            elt.addEventListener('click', function() {
                window.WonderPushInAppSDK.trackClick(buttonLabel);
            });
        });
        // Register event listeners on data-wonderpush-dismiss elements
        document.querySelectorAll('*[data-wonderpush-dismiss]').forEach(function(elt) {
            elt.addEventListener('click', function() {
                window.WonderPushInAppSDK.dismiss();
            });
        });
    }
    if (document.readyState === "complete") {
        onload();
    } else {
        window.addEventListener("load", onload);
    }
})();

<commit_msg>Data tag shortcuts<commit_after>(function() {
    var identifierCounter = 0;
    var generateIdentifier = function() {
        return ""+(+new Date())+":"+(identifierCounter++);
    };
    window.WonderPushInAppSDK = new Proxy({}, new function() {
        this.get = function(target, prop, receiver) {
            if (this.hasOwnProperty(prop)) return this[prop];
            return function() {
                var callId = generateIdentifier();
                webkit.messageHandlers.WonderPushInAppSDK.postMessage({
                    method : prop,
                    args: Array.from(arguments),
                    callId: callId,
                });
                return new Promise(function(res, rej) {
                    window.WonderPushInAppSDK.callIdToPromise[callId] = {resolve:res, reject:rej};
                });
            };
        }.bind(this);
        this.callIdToPromise = {};
        this.resolve =  function(result, callId) {
            var promise = window.WonderPushInAppSDK.callIdToPromise[callId];
            if (!promise || !promise.resolve) return;
            promise.resolve(result);
            delete window.WonderPushInAppSDK.callIdToPromise[callId];
        };
        this.reject = function(error, callId) {
            var promise = window.WonderPushInAppSDK.callIdToPromise[callId];
            if (!promise || !promise.reject) return;
            promise.reject(error);
            delete window.WonderPushInAppSDK.callIdToPromise[callId];
        };
    });

    // Executed when the window is loaded
    var onload = function() {
        // Register event listeners on data-wonderpush-* elements
        document.querySelectorAll('*').forEach(function(elt) {
          if (!elt.dataset) return;
          Object.keys(elt.dataset).forEach(function (key) {
            var val = elt.dataset[key];
            var fn;
            switch (key) {
              case "wonderpushAddTag":
                fn = function () {
                  window.WonderPushInAppSDK.addTag(val);
                };
                break;
              case "wonderpushButtonLabel":
                fn = function () {
                  window.WonderPushInAppSDK.trackClick(val);
                };
                break;
              case "wonderpushDismiss":
                fn = function () {
                  window.WonderPushInAppSDK.dismiss();
                };
                break;
              case "wonderpushOpenDeepLink":
                fn = function () {
                  window.WonderPushInAppSDK.openDeepLink(val);
                };
                break;
              case "wonderpushOpenExternalUrl":
                fn = function () {
                  window.WonderPushInAppSDK.openExternalUrl(val);
                };
                break;
              case "wonderpushRemoveAllTags":
                fn = function () {
                  window.WonderPushInAppSDK.removeAllTags();
                };
                break;
              case "wonderpushRemoveTag":
                fn = function () {
                  window.WonderPushInAppSDK.removeTag(val);
                };
                break;
              case "wonderpushSubscribeToNotifications":
                fn = function () {
                  window.WonderPushInAppSDK.subscribeToNotifications();
                };
                break;
              case "wonderpushTrackEvent":
                fn = function () {
                  window.WonderPushInAppSDK.trackEvent(val);
                };
                break;
              case "wonderpushTriggerLocationPrompt":
                fn = function () {
                  window.WonderPushInAppSDK.triggerLocationPrompt();
                };
                break;
              case "wonderpushUnsubscribeFromNotifications":
                fn = function () {
                  window.WonderPushInAppSDK.unsubscribeFromNotifications();
                };
                break;
            }
            if (fn) {
              elt.addEventListener('click', fn);
            }
          });
        });
    }
    if (document.readyState === "complete") {
        onload();
    } else {
        window.addEventListener("load", onload);
    }
})();

<|endoftext|>


<commit_before>var merge = require('react/lib/merge');
var Route = require('./Route');
var Request = require('./Request');
var Response = require('./Response');
var Unhandled = require('./errors/Unhandled');
var once = require('once');
var delayed = require('./utils/delayed');
var getDefaultHistory = require('./history/getHistory');
var invokeHandlers = require('./utils/invokeHandlers');
var noop = require('./utils/noop');
var inherits = require('inherits');
var EventEmitter = require('EventEmitter2').EventEmitter2;

function Router(opts) {
  this.state = {};
  this.rootURL = (opts && opts.rootURL || '/');
}

inherits(Router, EventEmitter);

/**
 * Expose the `Unhandled` error so it can be used in handlers more easily.
 */
Router.prototype.Unhandled = Unhandled;

/**
 * A list of routes for this router.
 */
Router.routes = null;

/**
 * Add a route to the router class. This API can be used in a manner similar
 * to many server-side JS routing libraries—by chainging calls to `route`—
 * however, it's more likely that you'll want to pass your routes to the
 * router class constructor using JSX.
 *
 * This function accepts either `(path, handlers...)`, or
 * `(name, path, handlers...)`.
 */
Router.route = function() {
  var RouterClass = this;
  var args = Array.prototype.slice.call(arguments, 0);
  var opts = {};

  if (typeof args[1] !== 'function') {
    opts.name = args.shift();
  }
  opts.path = args.shift();
  opts.handlers = args;

  if (!RouterClass.routes) RouterClass.routes = [];
  RouterClass.routes.push(new Route(opts));

  // For chaining!
  return this;
};

Router.prototype.setState = function(state) {
  this.state = merge(this.state, state);
  this.emit('stateChange');
};

Router.prototype.setView = function(view) {
  this.view = view;
  this.emit('viewChange');
};

/**
 *
 * @param {string} url
 * @param {function?} callback
 */
Router.prototype.dispatch = function(url, opts, callback) {
  var RouterClass = this.constructor;

  if (typeof arguments[1] === 'function') {
    callback = arguments[1];
    opts = null;
  }

  // TODO: Handle this better.
  if (url.indexOf(this.rootURL) === 0) {
    url = url.substr(this.rootURL.length);
  } else {
    throw new Error('URL not within root: ' + url);
  }

  // Wrap the callback, imposing a delay to force asynchronousness in
  // case the user calls it synchronously.
  var cb = once(delayed(function(err) {
    this._currentResponse = null;
    if (callback)
      callback(err, err ? null : res);
  }.bind(this)));

  var req = new Request(url, opts);
  var res = new Response(req, this)
    .on('error', cb)
    .on('end', cb);

  if (this._currentResponse) {
    this._currentResponse.request.cancel();
  }
  this._currentResponse = res;

  var routeCount = RouterClass.routes ? RouterClass.routes.length : 0;
  for (var i = 0; i < routeCount; i++) {
    var route = RouterClass.routes[i];
    var match = route.match(req.path);

    if (!match) continue;

    req.params = match;

    // Force async behavior so you have a chance to add listeners to the
    // request object.
    delayed(function() {
      invokeHandlers(route.handlers, req, res, cb);
    })();

    return res;
  }

  // Uh-oh. Unhandled route!
  // TODO: Probably need to emit an error so middleware can catch this.
  cb(new Unhandled(req));

  return res;
};

Router.extend = function() {
  var SuperClass = this;
  var NewRouter = function(opts) {
    if (!(this instanceof NewRouter)) {
      return new NewRouter(opts);
    }
    SuperClass.call(this, opts);
  };
  inherits(NewRouter, SuperClass);
  NewRouter.route = SuperClass.route;
  return NewRouter;
};

module.exports = Router;
<commit_msg>Move more stuff onto the router class<commit_after>var merge = require('react/lib/merge');
var Route = require('./Route');
var Request = require('./Request');
var Response = require('./Response');
var Unhandled = require('./errors/Unhandled');
var once = require('once');
var delayed = require('./utils/delayed');
var getDefaultHistory = require('./history/getHistory');
var invokeHandlers = require('./utils/invokeHandlers');
var noop = require('./utils/noop');
var inherits = require('inherits');
var EventEmitter = require('EventEmitter2').EventEmitter2;

function Router() {
  this.state = {};
}

inherits(Router, EventEmitter);

/**
 * Expose the `Unhandled` error so it can be used in handlers more easily.
 */
Router.Unhandled = Unhandled;

/**
 * A list of routes for this router.
 */
Router.routes = null;

/**
 * Add a route to the router class. This API can be used in a manner similar
 * to many server-side JS routing libraries—by chainging calls to `route`—
 * however, it's more likely that you'll want to pass your routes to the
 * router class constructor using JSX.
 *
 * This function accepts either `(path, handlers...)`, or
 * `(name, path, handlers...)`.
 */
Router.route = function() {
  var RouterClass = this;
  var args = Array.prototype.slice.call(arguments, 0);
  var opts = {};

  if (typeof args[1] !== 'function') {
    opts.name = args.shift();
  }
  opts.path = args.shift();
  opts.handlers = args;

  if (!RouterClass.routes) RouterClass.routes = [];
  RouterClass.routes.push(new Route(opts));

  // For chaining!
  return this;
};

Router.prototype.setState = function(state) {
  this.state = merge(this.state, state);
  this.emit('stateChange');
};

Router.prototype.setView = function(view) {
  this.view = view;
  this.emit('viewChange');
};

/**
 *
 * @param {string} url
 * @param {function?} callback
 */
Router.prototype.dispatch = function(url, opts, callback) {
  var RouterClass = this.constructor;

  if (typeof arguments[1] === 'function') {
    callback = arguments[1];
    opts = null;
  }

  // TODO: Handle this better.
  if (url.indexOf(RouterClass.rootURL) === 0) {
    url = url.substr(RouterClass.rootURL.length);
  } else {
    throw new Error('URL not within root: ' + url);
  }

  // Wrap the callback, imposing a delay to force asynchronousness in
  // case the user calls it synchronously.
  var cb = once(delayed(function(err) {
    this._currentResponse = null;
    if (callback)
      callback(err, err ? null : res);
  }.bind(this)));

  var req = new Request(url, opts);
  var res = new Response(req, this)
    .on('error', cb)
    .on('end', cb);

  if (this._currentResponse) {
    this._currentResponse.request.cancel();
  }
  this._currentResponse = res;

  var routeCount = RouterClass.routes ? RouterClass.routes.length : 0;
  for (var i = 0; i < routeCount; i++) {
    var route = RouterClass.routes[i];
    var match = route.match(req.path);

    if (!match) continue;

    req.params = match;

    // Force async behavior so you have a chance to add listeners to the
    // request object.
    delayed(function() {
      invokeHandlers(route.handlers, req, res, cb);
    })();

    return res;
  }

  // Uh-oh. Unhandled route!
  // TODO: Probably need to emit an error so middleware can catch this.
  cb(new Unhandled(req));

  return res;
};

Router.extend = function(opts) {
  var SuperClass = this;
  var NewRouter = function() {
    if (!(this instanceof NewRouter)) {
      return new NewRouter();
    }
    SuperClass.call(this);
  };
  inherits(NewRouter, SuperClass);

  // Add "static" props to the new router.
  for (var k in SuperClass) {
    if (SuperClass.hasOwnProperty(k)) {
      NewRouter[k] = SuperClass[k];
    }
  }

  NewRouter.rootURL = opts && opts.rootURL || '/';
  return NewRouter;
};

module.exports = Router;
<|endoftext|>


<commit_before>import Arr from './Array';
import Promise from './Promise';
import Str from './String';
import Super from './Super';
import { window } from './HtmlElement';
import { isFunction, assign, iterate } from './helpers';

const eventPromise = Promise.resolve();
const URL = global.URL;
const history = global.history;
const location = global.location;
const origin = location && location.origin;
const stoppable = new Arr(['beforeLeave', 'beforeLoad']);
const stopError = new Error();
const store = new Super({});

let loaded;
let initialized;
let routerLoaded;

export const Router = {
  $: {
    default: '/',
    icon: null,
    listeners: {},
    state: null,
    states: {},
    title: null
  },

  get store() {
    return store.$;
  },
  set store(value) {
    store.assign(value);
  },

  back() {
    return this.go(-1);
  },
  config(f) {
    const config = this.$;

    if (!arguments.length) {
      return config;
    }

    if (isFunction(f)) {
      f(config);
    } else {
      config.icon = f.icon || config.icon;
      config.title = f.title || config.title;
    }

    return this;
  },
  forward() {
    return this.go(1);
  },
  go(page) {
    history.go(page);

    return this;
  },
  history: new Arr([]),
  init() {
    initialized = true;

    initialize();

    return this;
  },
  on(event, listener) {
    if (arguments.length >= 2) {
      event = { [event]: listener };
    }

    const listeners = this.$.listeners;

    iterate(event, (listener, event) => {
      const array = listeners[event] || [];
      (listeners[event] = array).push(listener);
    });

    return this;
  },
  state(name, options) {
    const {
      controller = () => {},
      icon,
      parent,
      template = '',
      title,
      url = '/'
    } = options;

    if (this.$.states[name]) {
      throw new Error('State name must be unique');
    }

    const state = this.$.states[name] = {};

    state.controller = null;
    state.icon = icon;
    state.parent = parent;
    state.template = template;
    state.title = title;
    state.url = url;

    state.createController = function createController() {
      let ctrl;

      if (controller.prototype instanceof StateController.prototype) {
        ctrl = new controller();
      } else {
        ctrl = new StateController();
        controller.call(ctrl);
      }

      return ctrl;
    };

    return this;
  }
};

export class StateController {
  constructor() {
    Object.defineProperty(this, '$', {
      value: {
        listeners: {}
      }
    });
  }

  beforeLeave() {}
  beforeLoad() {}
  leave() {}
  load() {}
  on(event, listener) {
    if (arguments.length >= 2) {
      event = { [event]: listener };
    }

    const listeners = this.$.listeners;

    iterate(event, (listener, event) => {
      const array = listeners[event] || [];
      (listeners[event] = array).push(listener);
    });

    return this;
  }
}

window.on('DOMContentLoaded', () => {
  loaded = true;

  initialize();
});

function beforeLeave(state, title, url, push) {
  const currentURL = location.pathname;
  const event = {
    from: currentURL,
    to: url,
    type: 'beforeLeave'
  };

  return dispatchEvent(event).then((error) => {
    if (error !== stopError) {
      return leave(state, title, url, push);
    }

    return error;
  });
}
function beforeLoad(state, title, url, push) {
  const currentURL = location.pathname;
  const event = {
    from: currentURL,
    to: url,
    type: 'beforeLoad'
  };

  return dispatchEvent(event).then((error) => {
    if (error !== stopError) {
      url = new URL(url, currentURL).href.replace(/\/$/, '');

      if (url.indexOf(origin) === 0) {
        if (push) {
          pushState(state, title, url);
        } else {
          replaceState(state, title, url);
        }
      } else {
        global.location = url;
      }

      return;
    }

    return error;
  });
}
function leave(state, title, url, push) {
  const currentURL = location.pathname;
  const event = {
    from: currentURL,
    to: url,
    type: 'leave'
  };

  return dispatchEvent(event).then(() => {
    return beforeLoad(state, title, url, push);
  });
}
function load() {
  const current = location.pathname;
  const def = Router.$.default;
  const newState = new Super(Router.$.states).find(({ urlRegExp }) => urlRegExp.test(current));

  if (newState) {
    Router.history.push(current);
    // TODO: render template and so on
    const event = {
      url: current,
      type: 'load'
    };

    dispatchEvent(event);
  } else if (current !== def) {
    replaceState(history.state, '', def);
    load();
  } else {
    console.error(`There is no state with default url (${ def })`);
  }
}

function constructURL(url, params) {
  params = new Super(params);
  url = new Str(url);

  iterate(params, (value, param) => {
    url = url.replaceString(':' + param, value);
  });

  return url.$;
}
function dispatchEvent(event) {
  let paused;
  let stopped;
  let continuePropagation = () => {};
  let promise = Promise.resolve();

  const type = event.type;
  const currentState = Router.$.state;
  const listeners = getListeners(currentState, type);

  if (stoppable.indexOfStrict(type) === -1) {
    assign(event, {
      continue() {
        paused = false;
        continuePropagation();
      },
      pause() {
        paused = true;
      },
      stop() {
        stopped = true;
      }
    });
  }

  listeners.forEach(({ context, listener }) => {
    promise = promise.then(() => {
      return new Promise((resolve, reject) => {
        let finished;

        continuePropagation = () => {
          if (finished) {
            resolve();
          }
        };

        listener.call(context, event);

        finished = true;

        if (stopped) {
          return reject(stopError);
        }

        if (!paused) {
          return resolve();
        }
      });
    });
  });

  return promise.catch((err) => {
    if (err !== stopError) {
      throw err;
    }

    return err;
  });
}
function getListeners(state, type) {
  const tree = [];

  while (state) {
    tree.push(state);
    state = Router.$[state.parent];
  }

  return new Arr(tree).array((array, value) => {
    const controller = value.controller;

    array.push.apply(array, new Arr(controller.$.listeners[type]).push(controller[type]).map((listener) => {
      return { context: controller, listener };
    }).$);
  }).concat(new Arr(Router.$.listeners[type]).map((listener) => {
    return { context: Router, listener };
  }));
}
function initialize() {
  if (loaded && initialized && !routerLoaded) {
    routerLoaded = true;

    window.on('popstate', () => {
      load();
    });

    // TODO: resolve dependencies (parent, store, url)

    beforeLoad(history.state, '', location.pathname);
  }
}
function pushState() {
  history.pushState.apply(history, arguments);
  load();
}
function replaceState() {
  history.replaceState.apply(history, arguments);
  load();
}

export function directByName(name, params) {
  const state = Router.$.states[name];

  if (!state) {
    throw new Error(`There is no state with given name (${ name })`);
  }

  beforeLeave(null, '', constructURL(state.url, params), true);
}
export function directTo(url) {
  beforeLeave(null, '', url, true);
}
export function redirectByName(name, params) {
  const state = Router.$.states[name];

  if (!state) {
    throw new Error(`There is no state with given name (${ name })`);
  }

  beforeLeave(null, '', constructURL(state.url, params));
}
export function redirectTo(url) {
  beforeLeave(null, '', url);
}
<commit_msg>Router: add DOMNodeInserted listener.<commit_after>import Arr from './Array';
import HtmlElement, { find } from './HtmlElement';
import Promise from './Promise';
import Str from './String';
import Super from './Super';
import { window } from './HtmlElement';
import { isFunction, assign, iterate, crossClassMethods } from './helpers';

const eventPromise = Promise.resolve();
const URL = global.URL;
const history = global.history;
const location = global.location;
const origin = location && location.origin;
const stoppable = new Arr(['beforeLeave', 'beforeLoad']);
const stopError = new Error();

let loaded;
let initialized;
let routerLoaded;

export const Router = {
  $: {
    default: '/',
    icon: null,
    listeners: {},
    state: null,
    states: {},
    title: null
  },

  history: new Arr([]),

  get store() {
    return store.$;
  },
  set store(value) {
    store.assign(value);
  },

  back() {
    return this.go(-1);
  },
  config(f) {
    const config = this.$;

    if (!arguments.length) {
      return config;
    }

    if (isFunction(f)) {
      f(config);
    } else {
      config.icon = f.icon || config.icon;
      config.title = f.title || config.title;
    }

    return this;
  },
  forward() {
    return this.go(1);
  },
  go(page) {
    history.go(page);

    return this;
  },
  init() {
    initialized = true;

    initialize();

    return this;
  },
  on(event, listener) {
    if (arguments.length >= 2) {
      event = { [event]: listener };
    }

    const listeners = this.$.listeners;

    iterate(event, (listener, event) => {
      const array = listeners[event] || [];
      (listeners[event] = array).push(listener);
    });

    return this;
  },
  state(name, options) {
    const {
      controller = () => {},
      icon,
      parent,
      template = '',
      title,
      url = '/'
    } = options;

    if (this.$.states[name]) {
      throw new Error('State name must be unique');
    }

    const state = this.$.states[name] = {};

    state.controller = null;
    state.icon = icon;
    state.parent = parent;
    state.template = template;
    state.title = title;
    state.url = url;

    state.createController = function createController() {
      let ctrl;

      if (controller.prototype instanceof StateController) {
        ctrl = new controller();
      } else {
        ctrl = new StateController();
        controller.call(ctrl);
      }

      return ctrl;
    };

    return this;
  }
};

export class StateController {
  constructor() {
    Object.defineProperty(this, '$', {
      value: {
        listeners: {}
      }
    });
  }

  beforeLeave() {}
  beforeLoad() {}
  leave() {}
  load() {}
  render() {}
  on(event, listener) {
    if (arguments.length >= 2) {
      event = { [event]: listener };
    }

    const listeners = this.$.listeners;

    iterate(event, (listener, event) => {
      const array = listeners[event] || [];
      (listeners[event] = array).push(listener);
    });

    return this;
  }
}

window.on({
  DOMContentLoaded() {
    loaded = true;

    initialize();
  },
  DOMNodeInserted({ target }) {
    const anchor = new HtmlElement(target);

    if (anchor.name === 'a') {
      const { domcData } = target;

      if (!domcData.clickHandler) {
        domcData.clickHandler = anchor.on('click', (e) => {
          if (!anchor.attr('download')) {
            e.preventDefault();

            // TODO: handle anchor click (beforeLeave(...))
          }
        });
      }
    }
  }
});

crossClassMethods.transformAnchor = (anchor) => {
  if (anchor.name === 'a') {
    // TODO: transform src attr into d-href and src attrs
  }
};

function beforeLeave(state, title, url, push) {
  const currentURL = location.pathname;
  const event = {
    from: currentURL,
    to: url,
    type: 'beforeLeave'
  };

  return dispatchEvent(event).then((error) => {
    if (error !== stopError) {
      return leave(state, title, url, push);
    }

    return error;
  });
}
function beforeLoad(state, title, url, push) {
  const currentURL = location.pathname;
  const event = {
    from: currentURL,
    to: url,
    type: 'beforeLoad'
  };

  return dispatchEvent(event).then((error) => {
    if (error !== stopError) {
      url = new URL(url, currentURL).href.replace(/\/$/, '');

      if (url.indexOf(origin) === 0) {
        if (push) {
          pushState(state, title, url);
        } else {
          replaceState(state, title, url);
        }
      } else {
        global.location = url;
      }

      return;
    }

    return error;
  });
}
function leave(state, title, url, push) {
  const currentURL = location.pathname;
  const event = {
    from: currentURL,
    to: url,
    type: 'leave'
  };

  return dispatchEvent(event).then(() => {
    return beforeLoad(state, title, url, push);
  });
}
function load() {
  const current = location.pathname;
  const def = Router.$.default;
  const { states } = Router.$;
  const maxMatch = new Super(states).max(({ urlRegExp }) => {
    const match = current.match(urlRegExp);

    return match && match[0].length;
  });
  const minLevel = new Super(states)
    .filter(({ urlRegExp }) => {
      const match = current.match(urlRegExp);

      return match && match[0].length === maxMatch.value;
    })
    .min(({ level }) => level);

  if (maxMatch.value > 0) {
    Router.history.push(current);

    const event = {
      url: current,
      type: 'load'
    };

    dispatchEvent(event);
  } else if (current !== def) {
    replaceState(history.state, '', def);
    load();
  } else {
    console.error(`There is no state with default url (${ def })`);
  }
}
function render() {

}

function constructURL(url, params) {
  params = new Super(params);
  url = new Str(url);

  iterate(params, (value, param) => {
    url = url.replaceString(':' + param, value);
  });

  return url.$;
}
function dispatchEvent(event) {
  let paused;
  let stopped;
  let continuePropagation = () => {};
  let promise = Promise.resolve();

  const type = event.type;
  const currentState = Router.$.state;
  const listeners = getListeners(currentState, type);

  if (stoppable.indexOfStrict(type) === -1) {
    assign(event, {
      continue() {
        paused = false;
        continuePropagation();
      },
      pause() {
        paused = true;
      },
      stop() {
        stopped = true;
      }
    });
  }

  listeners.forEach(({ context, listener }) => {
    promise = promise.then(() => {
      return new Promise((resolve, reject) => {
        let finished;

        continuePropagation = () => {
          if (finished) {
            resolve();
          }
        };

        listener.call(context, event);

        finished = true;

        if (stopped) {
          return reject(stopError);
        }

        if (!paused) {
          return resolve();
        }
      });
    });
  });

  return promise.catch((err) => {
    if (err !== stopError) {
      throw err;
    }

    return err;
  });
}
function getListeners(state, type) {
  const tree = [];

  while (state) {
    tree.push(state);
    state = Router.$[state.parent];
  }

  return new Arr(tree).array((array, value) => {
    const controller = value.controller;

    array.push.apply(array, new Arr(controller.$.listeners[type]).push(controller[type]).map((listener) => {
      return { context: controller, listener };
    }).$);
  }).concat(new Arr(Router.$.listeners[type]).map((listener) => {
    return { context: Router, listener };
  }));
}
function initialize() {
  if (loaded && initialized && !routerLoaded) {
    const router = find('d-router');

    if (router) {
      routerLoaded = true;

      window.on('popstate', () => {
        load();
      });

      // TODO: resolve dependencies (parent, url)

      beforeLoad(history.state, '', location.pathname);
    }
  }
}
function pushState() {
  history.pushState.apply(history, arguments);
  load();
}
function replaceState() {
  history.replaceState.apply(history, arguments);
  load();
}

export function directByName(name, params) {
  const state = Router.$.states[name];

  if (!state) {
    throw new Error(`There is no state with given name (${ name })`);
  }

  beforeLeave(null, '', constructURL(state.url, params), true);
}
export function directTo(url) {
  beforeLeave(null, '', url, true);
}
export function redirectByName(name, params) {
  const state = Router.$.states[name];

  if (!state) {
    throw new Error(`There is no state with given name (${ name })`);
  }

  beforeLeave(null, '', constructURL(state.url, params));
}
export function redirectTo(url) {
  beforeLeave(null, '', url);
}
<|endoftext|>


<commit_before>"use strict"

var os = require("os");
var net = require("net");

var mc = require("./ModuleContainer.js");
var log = require("./Logger.js");

exports.Server = function(serverSettings)
{
	this.address = serverSettings.address;
	this.port = serverSettings.port;

	this.nick = serverSettings.nick;
	this.userName = serverSettings.userName;
	this.realName = serverSettings.realName;
	this.commandPrefix = serverSettings.commandPrefix;

	this.channels = {};

	this.connected = false;

	this.modules = new mc.ModuleContainer(this);
	this.modulesStarted = false;

	this.toString = function()
	{
		return this.address+":"+this.port;
	}

	// Connects to the server and starts listening for incoming data.
	this.connect = function()
	{
		//Check that we're not connected
		if(this.connected)
			throw new Error("Connecting to an already connected server");

		log.info("Connecting to "+this+"...");

		var self = this;

		this.socket = net.createConnection(this.port, this.address);
		this.socket.on("connect", function() {
			// Line reading below from
			// https://github.com/martynsmith/node-irc/blob/master/lib/irc.js
			log.info("Successfully connected to "+self+"...");

			var buffer = '';
			self.socket.addListener("data", function (chunk)
			{
				buffer += chunk;
				var lines = buffer.split("\r\n");
				buffer = lines.pop();
				lines.forEach(function (line)
				{
					log.debug(">> "+line);
					var message = parseMessage(line, false);
					self.gotRawMessage(message);
				});
			});

			self.sendCommand("NICK", self.nick);
			self.sendCommand("USER", self.userName+" "+self.userName+" "+self.address+" :"+self.realName);
		});

		var reconnect = function() {
			if(!self.connected) return;
			self.connected = false;
			log.warning("Disconnected from "+self+". Reconnecting in 5s...");
			setTimeout(function() {
				self.connect();
			}, 5000);
		};

		this.socket.on("timeout", reconnect);
		this.socket.on("error", reconnect);
		this.socket.on("close", reconnect);

		this.connected = true;
	}

	this.addChannel = function(channel)
	{
		this.channels[channel.channelName] = channel;
	}

	this.gotRawMessage = function(message)
	{
		switch(message.command)
		{
			case "PRIVMSG":
				var channel = this.channels[message.args[0]];
				var text = message.args[1].trim();
				if (channel)
				{
					if (text.indexOf(this.commandPrefix) == 0) {
						var cmdString = text.substring(this.commandPrefix.length);
						var command = cmdString.split(" ")[0];
						var cmdarguments = cmdString.substring(command.length + 1);
						channel.onCommand(message.nick, command, cmdarguments);
					} else
						channel.onMessage(message.nick, text);
				} else {
					this.modules.run('onMessage', message.nick, text);
				}
				break;
			case "JOIN":
				var channel = this.channels[message.args[0]];
				if(channel)
					channel.onUserJoin(message.nick);
				break;
			case "PART":
				var channel = this.channels[message.args[0]];
				if(channel)
					channel.onUserLeave(message.nick);
				break;
			//Changed this to 251; it's a safer assumption.
			case "251":
				if(!this.modulesStarted)
					this.modules.start();
				this.modulesStarted = true;
				for(var channel in this.channels)
				{
					this.sendCommand("JOIN", channel);
					this.channels[channel].modules.start();
				}
				break;
			case "PING":
				this.sendCommand("PONG", message.args[0]);
				break;
			case true:
				modules.run(message.command, message);
				break;
			case "433":
				this.nick += "_";
				this.sendCommand("NICK", this.nick);
				this.sendCommand("USER", this.userName+" "+this.userName+" "+this.address+" :"+this.realName);
				break;
			case "376":
				this.sendCommand("MODE", this.nick+ " +B");
		}
	}

    this.sendCommand = function(command, args)
    {
		//Check all this to avoid hax
		command = command.replace("\n", "");
		command = command.replace("\r", "");
		args = args.replace("\n", "");
		args = args.replace("\r", "");

		log.debug("<< " + command + " " + args);
    	this.socket.write(command+" "+args+"\r\n");
    }

	//TODO: Functions to say stuff, send PMs, maybe more.
	//But we should only add what we need. No bloat :)

	this.notice = function(nick, message)
	{
		this.sendCommand("NOTICE", nick+" :"+message);
	}

	/*
	* parseMessage(line, stripColors)
	*
	* takes a raw "line" from the IRC server and turns it into an object with
	* useful keys
	*
	* From: https://github.com/martynsmith/node-irc/blob/master/lib/irc.js
	*/
	function parseMessage(line, stripColors) { // {{{
		var message = {};
		var match;

		if (stripColors) {
		    line = line.replace(/[\x02\x1f\x16\x0f]|\x03\d{0,2}(?:,\d{0,2})?/g, "");
		}

		// Parse prefix
		if ( match = line.match(/^:([^ ]+) +/) ) {
		    message.prefix = match[1];
		    line = line.replace(/^:[^ ]+ +/, '');
		    if ( match = message.prefix.match(/^([_a-zA-Z0-9\[\]\\`^{}|-]*)(!([^@]+)@(.*))?$/) ) {
		        message.nick = match[1];
		        message.user = match[3];
		        message.host = match[4];
		    }
		    else {
		        message.server = message.prefix;
		    }
		}

		// Parse command
		match = line.match(/^([^ ]+) */);
		message.command = match[1];
		message.rawCommand = match[1];
		message.commandType = 'normal';
		line = line.replace(/^[^ ]+ +/, '');

		message.args = [];
		var middle, trailing;

		// Parse parameters
		if ( line.indexOf(':') != -1 ) {
		    var index = line.indexOf(':');
		    middle = line.substr(0, index).replace(/ +$/, "");
		    trailing = line.substr(index+1);
		}
		else {
		    middle = line;
		}

		if ( middle.length )
		    message.args = middle.split(/ +/);

		if ( typeof(trailing) != 'undefined' && trailing.length )
		    message.args.push(trailing);

		return message;
	}

}

<commit_msg>Update Server.js<commit_after>"use strict"

var os = require("os");
var net = require("net");

var mc = require("./ModuleContainer.js");
var log = require("./Logger.js");

exports.Server = function(serverSettings)
{
	this.address = serverSettings.address;
	this.port = serverSettings.port;
	this.pass = serverSettings.pass;

	this.nick = serverSettings.nick;
	this.userName = serverSettings.userName;
	this.realName = serverSettings.realName;
	this.commandPrefix = serverSettings.commandPrefix;

	this.channels = {};

	this.connected = false;

	this.modules = new mc.ModuleContainer(this);
	this.modulesStarted = false;

	this.toString = function()
	{
		return this.address+":"+this.port;
	}

	// Connects to the server and starts listening for incoming data.
	this.connect = function()
	{
		//Check that we're not connected
		if(this.connected)
			throw new Error("Connecting to an already connected server");

		log.info("Connecting to "+this+"...");

		var self = this;

		this.socket = net.createConnection(this.port, this.address);
		this.socket.on("connect", function() {
			// Line reading below from
			// https://github.com/martynsmith/node-irc/blob/master/lib/irc.js
			log.info("Successfully connected to "+self+"...");

			var buffer = '';
			self.socket.addListener("data", function (chunk)
			{
				buffer += chunk;
				var lines = buffer.split("\r\n");
				buffer = lines.pop();
				lines.forEach(function (line)
				{
					log.debug(">> "+line);
					var message = parseMessage(line, false);
					self.gotRawMessage(message);
				});
			});

			self.sendCommand("NICK", self.nick);
			self.sendCommand("USER", self.userName+" "+self.userName+" "+self.address+" :"+self.realName);
		});

		var reconnect = function() {
			if(!self.connected) return;
			self.connected = false;
			log.warning("Disconnected from "+self+". Reconnecting in 5s...");
			setTimeout(function() {
				self.connect();
			}, 5000);
		};

		this.socket.on("timeout", reconnect);
		this.socket.on("error", reconnect);
		this.socket.on("close", reconnect);

		this.connected = true;
	}

	this.addChannel = function(channel)
	{
		this.channels[channel.channelName] = channel;
	}

	this.gotRawMessage = function(message)
	{
		switch(message.command)
		{
			case "PRIVMSG":
				var channel = this.channels[message.args[0]];
				var text = message.args[1].trim();
				if (channel)
				{
					if (text.indexOf(this.commandPrefix) == 0) {
						var cmdString = text.substring(this.commandPrefix.length);
						var command = cmdString.split(" ")[0];
						var cmdarguments = cmdString.substring(command.length + 1);
						channel.onCommand(message.nick, command, cmdarguments);
					} else
						channel.onMessage(message.nick, text);
				} else {
					this.modules.run('onMessage', message.nick, text);
				}
				break;
			case "JOIN":
				var channel = this.channels[message.args[0]];
				if(channel)
					channel.onUserJoin(message.nick);
				break;
			case "PART":
				var channel = this.channels[message.args[0]];
				if(channel)
					channel.onUserLeave(message.nick);
				break;
			//Changed this to 251; it's a safer assumption.
			case "251":
				if(!this.modulesStarted)
					this.modules.start();
				this.modulesStarted = true;
				for(var channel in this.channels)
				{
					this.sendCommand("JOIN", channel);
					this.channels[channel].modules.start();
				}
				break;
			case "PING":
				this.sendCommand("PONG", message.args[0]);
				break;
			case true:
				modules.run(message.command, message);
				break;
			case "433":
				this.nick += "_";
				this.sendCommand("NICK", this.nick);
				this.sendCommand("USER", this.userName+" "+this.userName+" "+this.address+" :"+this.realName);
				break;
			case "376":
				this.sendCommand("MODE", this.nick+ " +B");
		}
	}

    this.sendCommand = function(command, args)
    {
		//Check all this to avoid hax
		command = command.replace("\n", "");
		command = command.replace("\r", "");
		args = args.replace("\n", "");
		args = args.replace("\r", "");

		log.debug("<< " + command + " " + args);
    	this.socket.write(command+" "+args+"\r\n");
    }

	//TODO: Functions to say stuff, send PMs, maybe more.
	//But we should only add what we need. No bloat :)

	this.notice = function(nick, message)
	{
		this.sendCommand("NOTICE", nick+" :"+message);
	}

	/*
	* parseMessage(line, stripColors)
	*
	* takes a raw "line" from the IRC server and turns it into an object with
	* useful keys
	*
	* From: https://github.com/martynsmith/node-irc/blob/master/lib/irc.js
	*/
	function parseMessage(line, stripColors) { // {{{
		var message = {};
		var match;

		if (stripColors) {
		    line = line.replace(/[\x02\x1f\x16\x0f]|\x03\d{0,2}(?:,\d{0,2})?/g, "");
		}

		// Parse prefix
		if ( match = line.match(/^:([^ ]+) +/) ) {
		    message.prefix = match[1];
		    line = line.replace(/^:[^ ]+ +/, '');
		    if ( match = message.prefix.match(/^([_a-zA-Z0-9\[\]\\`^{}|-]*)(!([^@]+)@(.*))?$/) ) {
		        message.nick = match[1];
		        message.user = match[3];
		        message.host = match[4];
		    }
		    else {
		        message.server = message.prefix;
		    }
		}

		// Parse command
		match = line.match(/^([^ ]+) */);
		message.command = match[1];
		message.rawCommand = match[1];
		message.commandType = 'normal';
		line = line.replace(/^[^ ]+ +/, '');

		message.args = [];
		var middle, trailing;

		// Parse parameters
		if ( line.indexOf(':') != -1 ) {
		    var index = line.indexOf(':');
		    middle = line.substr(0, index).replace(/ +$/, "");
		    trailing = line.substr(index+1);
		}
		else {
		    middle = line;
		}

		if ( middle.length )
		    message.args = middle.split(/ +/);

		if ( typeof(trailing) != 'undefined' && trailing.length )
		    message.args.push(trailing);

		return message;
	}

}

<|endoftext|>


<commit_before>module.exports = Hash;
var Traverse = require('traverse');

function Hash (ref) {
    var hash = Traverse.clone(ref);
    return {
        map : function (f) {
            var acc = { __proto__ : hash.__proto__ };
            Object.keys(hash).forEach(function (key) {
                acc[key] = f.call(hash, hash[key], key);
            });
            return Hash(acc);
        },
        forEach : function (f) {
            var acc = { __proto__ : hash.__proto__ };
            Object.keys(hash).forEach(function (key) {
                f.call(hash, hash[key], key);
            });
            return Hash(hash);
        },
        filter : function (f) {
            var acc = { __proto__ : hash.__proto__ };
            Object.keys(hash).forEach(function (key) {
                if (f.call(hash, hash[key], key)) {
                    acc[key] = hash[key];
                }
            });
            return Hash(acc);
        },
        reduce : function (f, acc) {
            var keys = Object.keys(hash);
            if (acc === undefined) acc = keys.shift();
            keys.forEach(function (key) {
                acc = f.call(hash, acc, hash[key], key);
            });
            return acc;
        },
        end : hash,
    };
};

Hash.map = function (ref, f) {
    return Hash(ref).map(f).end;
};

Hash.filter = function (ref, f) {
    return Hash(ref).filter(f).end;
};

Hash.reduce = function (ref, f, acc) {
    return Hash(ref).reduce(f, acc);
};

<commit_msg>key and value getters<commit_after>module.exports = Hash;
var Traverse = require('traverse');

function Hash (ref) {
    var hash = Traverse.clone(ref);
    var self = {
        map : function (f) {
            var acc = { __proto__ : hash.__proto__ };
            Object.keys(hash).forEach(function (key) {
                acc[key] = f.call(hash, hash[key], key);
            });
            return Hash(acc);
        },
        forEach : function (f) {
            var acc = { __proto__ : hash.__proto__ };
            Object.keys(hash).forEach(function (key) {
                f.call(hash, hash[key], key);
            });
            return Hash(hash);
        },
        filter : function (f) {
            var acc = { __proto__ : hash.__proto__ };
            Object.keys(hash).forEach(function (key) {
                if (f.call(hash, hash[key], key)) {
                    acc[key] = hash[key];
                }
            });
            return Hash(acc);
        },
        reduce : function (f, acc) {
            var keys = Object.keys(hash);
            if (acc === undefined) acc = keys.shift();
            keys.forEach(function (key) {
                acc = f.call(hash, acc, hash[key], key);
            });
            return acc;
        },
        end : hash
    };

    Object.defineProperty(self, 'keys', { get : function () {
        return Object.keys(hash);
    } });

    Object.defineProperty(self, 'values', { get : function () {
        return Object.keys(hash)
            .map(function (key) { return hash[key] })
    } });

    return self;
};

Hash.map = function (ref, f) {
    return Hash(ref).map(f).end;
};

Hash.filter = function (ref, f) {
    return Hash(ref).filter(f).end;
};

Hash.reduce = function (ref, f, acc) {
    return Hash(ref).reduce(f, acc);
};

<|endoftext|>


<commit_before>var path = require( 'path' );

module.exports = {
  dirname: __dirname,
  _pathToFile: function () {
    var findGitDir = require( 'git-toplevel' );
    var p = findGitDir();

    return p.then( function ( gitDir ) {
      return {
        hookFile: path.resolve( gitDir, './.git/hooks/pre-push' ),
        gitDir: gitDir
      };
    } );
  },
  install: function ( cfg ) {

    var fs = require( 'fs' );

    var read = require( 'read-file' ).sync;
    var write = require( 'write' ).sync;

    var process = require( './process' );

    cfg = cfg || { };

    cfg.workingDirectory = path.resolve( process.cwd() );

    var prepushSource = read( path.resolve( this.dirname, '../hook/pre-push.js' ) );

    prepushSource = prepushSource.replace( /require\(\s*'process'\s*\);/g, 'process;' )
      .replace( /require\(\s*'console'\s*\);/g, 'console;' )
      .replace( /require\(\s*'\.\/Promise'\s*\);/g, 'global.Promise;' );

    return this._pathToFile().then( function ( args ) {
      var pathToFile = args.hookFile;
      cfg.gitDirectory = args.gitDir;

      prepushSource = prepushSource.replace( /require\(\s*'prepush-config'\s*\);/g, JSON.stringify( cfg, null, 2 ) + ';' );
      write( pathToFile, prepushSource );
      fs.chmodSync( pathToFile, '755' );
      return pathToFile;
    } );
  },
  remove: function () {
    return this._pathToFile().then( function ( args ) {
      var pathToFile = args.hookFile;
      var del = require( 'del' );
      del.sync( pathToFile, { force: true } );

      return pathToFile;
    } );
  }
};
<commit_msg>FIX: regression when upgrading read-file<commit_after>var path = require( 'path' );

module.exports = {
  dirname: __dirname,
  _pathToFile: function () {
    var findGitDir = require( 'git-toplevel' );
    var p = findGitDir();

    return p.then( function ( gitDir ) {
      return {
        hookFile: path.resolve( gitDir, './.git/hooks/pre-push' ),
        gitDir: gitDir
      };
    } );
  },
  install: function ( cfg ) {

    var fs = require( 'fs' );

    var read = require( 'read-file' ).sync;
    var write = require( 'write' ).sync;

    var process = require( './process' );

    cfg = cfg || { };

    cfg.workingDirectory = path.resolve( process.cwd() );

    var prepushSource = read( path.resolve( this.dirname, '../hook/pre-push.js' ), 'utf8' );

    prepushSource = prepushSource.replace( /require\(\s*'process'\s*\);/g, 'process;' )
      .replace( /require\(\s*'console'\s*\);/g, 'console;' )
      .replace( /require\(\s*'\.\/Promise'\s*\);/g, 'global.Promise;' );

    return this._pathToFile().then( function ( args ) {
      var pathToFile = args.hookFile;
      cfg.gitDirectory = args.gitDir;

      prepushSource = prepushSource.replace( /require\(\s*'prepush-config'\s*\);/g, JSON.stringify( cfg, null, 2 ) + ';' );
      write( pathToFile, prepushSource );
      fs.chmodSync( pathToFile, '755' );
      return pathToFile;
    } );
  },
  remove: function () {
    return this._pathToFile().then( function ( args ) {
      var pathToFile = args.hookFile;
      var del = require( 'del' );
      del.sync( pathToFile, { force: true } );

      return pathToFile;
    } );
  }
};
<|endoftext|>


<commit_before>require.config ({
  baseUrl: '../app/js',
  paths: {
    requireLib: 'libs/require',
    jquery: 'libs/jquery-1.11.0.min',
    underscore: 'libs/underscore-min',
    backbone: 'libs/backbone-min',
    text: 'libs/text',
    bootstrap: 'libs/bootstrap.min',
    jquery_cookie: 'libs/jquery.cookie',
    select2: 'libs/select2.min',
    templates: '../templates',
    jasmine: '../../tests/lib/jasmine-2.2.0/jasmine',
    'jasmine-html': '../../tests/lib/jasmine-2.2.0/jasmine-html',
    'jasmine-boot': '../../tests/lib/jasmine-2.2.0/boot',
    'jasmine-jquery': '../../tests/lib/jasmine-jquery'
  },

  shim: {
    'bootstrap': {
       deps: ["jquery"]
    },
    'jquery': {
       exports: '$'
    },
    'jquery_cookie': {
       deps: ["jquery"]
    },
    'select2': {
       deps: ["jquery"]
    },
    'jasmine-html': {
       deps: ['jasmine'],
    },
    'jasmine-jquery': {
       deps: ['jquery', 'jasmine'],
    },
    'jasmine-boot': {
       deps: ['jasmine', 'jasmine-html'],
    }
  }
});

var specs = [
  '../../tests/spec/sidebar',
  '../../tests/spec/debe'
];

require([
  'app',
  'jasmine-boot'
], function (App) {

  App.initialize ();

  // Load the specs
  require(specs, function () {

    // Initialize the HTML Reporter and execute the environment (setup by `boot.js`)
    window.onload();
  });

});
<commit_msg>do not initialize app in tests<commit_after>require.config ({
  baseUrl: '../app/js',
  paths: {
    requireLib: 'libs/require',
    jquery: 'libs/jquery-1.11.0.min',
    underscore: 'libs/underscore-min',
    backbone: 'libs/backbone-min',
    text: 'libs/text',
    bootstrap: 'libs/bootstrap.min',
    jquery_cookie: 'libs/jquery.cookie',
    select2: 'libs/select2.min',
    templates: '../templates',
    jasmine: '../../tests/lib/jasmine-2.2.0/jasmine',
    'jasmine-html': '../../tests/lib/jasmine-2.2.0/jasmine-html',
    'jasmine-boot': '../../tests/lib/jasmine-2.2.0/boot',
    'jasmine-jquery': '../../tests/lib/jasmine-jquery'
  },

  shim: {
    'bootstrap': {
       deps: ["jquery"]
    },
    'jquery': {
       exports: '$'
    },
    'jquery_cookie': {
       deps: ["jquery"]
    },
    'select2': {
       deps: ["jquery"]
    },
    'jasmine-html': {
       deps: ['jasmine'],
    },
    'jasmine-jquery': {
       deps: ['jquery', 'jasmine'],
    },
    'jasmine-boot': {
       deps: ['jasmine', 'jasmine-html'],
    }
  }
});

var specs = [
  '../../tests/spec/sidebar',
  '../../tests/spec/debe'
];

require([
  'app',
  'jasmine-boot'
], function (App) {

  App.initialize (true);

  // Load the specs
  require(specs, function () {

    // Initialize the HTML Reporter and execute the environment (setup by `boot.js`)
    window.onload();
  });

});
<|endoftext|>


<commit_before>
module.exports = function(fn) {
	var qs		= require('querystring'),
		html	= {};

	html.el = function (name, opts) {
		return  html.beginEl(name, opts) + html.endEl(name);
	};

	html.beginEl = function (name, opts) {
		opts = opts || {};

		var innerHTML = opts && typeof opts.val !== 'undefined' ? fn.e(opts.val) : ''; // escaped value
		delete opts.val;
		if (opts && typeof opts.html !== 'undefined') {
			innerHTML =  opts.html;
			delete opts.html;
		}
		return '<'+ name + fn.toAttr(opts) +'>'+ innerHTML;
	};

	html.endEl = function (name) {
		return '</'+ name +'>';
	};

	// meta charset
	html.charset = function (charset) {
		charset = charset || 'utf-8';
		return '<meta charset="'+ charset +'" />';
	};

	html.css = function (href, opts) {
		return '<link'+ fn.toAttr(fn.mergeObject({ href: href, rel: 'stylesheet', type: 'text/css', media: 'all'}, opts)) +' />';
	};

	html.script = function (src, opts) {
		return '';
	};

	html.a = function(link, text, opts) {
		return ''+ text +'';
	};

	html.img = function (src, alt, opts) {
		return '';
	};

	html.imgText = function(text, opt) {
        opt = opt || {};
        var fgColor = opt.fgColor || 'EFEFEF';
        var bgColor = opt.bgColor || 'AAAAAA';
        var w = opt.w || 291;
        var h = opt.h || 170;
        text = text || 'nincs kép';
        // http://www.placehold.it/291x170/EFEFEF/AAAAAA&text=nincs+kép
        return '';
    };

    html.refresh = function (url, sec, opts) {
    	if (!sec)
    		sec = 5;
    	return '<meta'+ fn.toAttr(fn.mergeObject({ http: { equiv: 'refresh' }, content: sec +',URL='+ url }, opts)) +' />';
    };

	return html;
};<commit_msg>changed refresh<commit_after>
module.exports = function(fn) {
	var qs		= require('querystring'),
		html	= {};

	html.el = function (name, opts) {
		return  html.beginEl(name, opts) + html.endEl(name);
	};

	html.beginEl = function (name, opts) {
		opts = opts || {};

		var innerHTML = opts && typeof opts.val !== 'undefined' ? fn.e(opts.val) : ''; // escaped value
		delete opts.val;
		if (opts && typeof opts.html !== 'undefined') {
			innerHTML =  opts.html;
			delete opts.html;
		}
		return '<'+ name + fn.toAttr(opts) +'>'+ innerHTML;
	};

	html.endEl = function (name) {
		return '</'+ name +'>';
	};

	// meta charset
	html.charset = function (charset) {
		charset = charset || 'utf-8';
		return '<meta charset="'+ charset +'" />';
	};

	html.css = function (href, opts) {
		return '<link'+ fn.toAttr(fn.mergeObject({ href: href, rel: 'stylesheet', type: 'text/css', media: 'all'}, opts)) +' />';
	};

	html.script = function (src, opts) {
		return '';
	};

	html.a = function(link, text, opts) {
		return ''+ text +'';
	};

	html.img = function (src, alt, opts) {
		return '';
	};

	html.imgText = function(text, opt) {
        opt = opt || {};
        var fgColor = opt.fgColor || 'EFEFEF';
        var bgColor = opt.bgColor || 'AAAAAA';
        var w = opt.w || 291;
        var h = opt.h || 170;
        text = text || 'nincs kép';
        // http://www.placehold.it/291x170/EFEFEF/AAAAAA&text=nincs+kép
        return '';
    };

    html.refresh = function (url, sec, opts) {
    	if (!sec)
    		sec = 5;
    	return '<meta'+ fn.toAttr(fn.mergeObject({ 'http-equiv': 'refresh', content: sec +',URL='+ url }, opts)) +' />';
    };

	return html;
};<|endoftext|>


<commit_before>// Generated by CoffeeScript 1.7.1
(function() {
  var Airbud, fs, request, retry;

  request = require("request");

  fs = require("fs");

  retry = require("retry");

  Airbud = (function() {
    function Airbud() {}

    Airbud._defaults = {
      url: null,
      retries: 0,
      timeout: null,
      parseJson: true,
      expectedKey: null,
      testDelay: 0
    };

    Airbud.fetch = function(options, cb) {
      var key, operation, operationDurations, timeoutForOperation, totalStart, val, _ref;
      _ref = this._defaults;
      for (key in _ref) {
        val = _ref[key];
        if (options[key] == null) {
          options[key] = val;
        }
      }
      if (!options.url) {
        return cb(new Error("You did not specify a url to fetch"));
      }
      operation = retry.operation(options);
      timeoutForOperation = null;
      if (options.timeout != null) {
        timeoutForOperation = {
          timeout: options.timeout,
          cb: function() {
            return operation.retry(new Error("Operation timeout of " + options.timeout + "ms reached. "));
          }
        };
      }
      totalStart = +(new Date);
      operationDurations = 0;
      return operation.attempt((function(_this) {
        return function(currentAttempt) {
          var operationStart;
          operationStart = +(new Date);
          return _this._fetch(options, function(err, data) {
            var info, totalDuration;
            operationDurations += +(new Date) - operationStart;
            if (operation.retry(err)) {
              return;
            }
            totalDuration = +(new Date) - totalStart;
            info = {
              errors: operation.errors(),
              attempts: operation.attempts(),
              totalDuration: totalDuration,
              operationDuration: operationDurations / operation.attempts()
            };
            return cb(operation.mainError(), data, info);
          });
        };
      })(this), timeoutForOperation);
    };

    Airbud._fetch = function(options, cb) {
      var path;
      if (options.url.indexOf("file://") === 0) {
        path = options.url.substr(7, options.url.length).split("?")[0];
        setTimeout((function(_this) {
          return function() {
            return fs.readFile(path, "utf8", function(err, buf) {
              if (err) {
                return cb(new Error("Error while opening " + path + ". " + err.message));
              }
              return _this.handleData(options, buf, cb);
            });
          };
        })(this), options.testDelay);
        return;
      }
      return request.get(options.url, (function(_this) {
        return function(err, res, buf) {
          if (err) {
            return cb(err, buf);
          }
          if (options.expectedStatus != null) {
            if (options.expectedStatus.indexOf(parseInt(res.statusCode, 10)) === -1) {
              return cb(new Error(("" + res.statusCode + " received when fetching '" + url + "'. \n") + ("expected one status of: " + (options.expectedStatus.join(', ')) + ". " + buf + " ")));
            }
          }
          return _this.handleData(options, buf, cb);
        };
      })(this));
    };

    Airbud.handleData = function(options, buf, cb) {
      var data, e;
      data = buf;
      if (options.parseJson) {
        try {
          data = JSON.parse(data);
        } catch (_error) {
          e = _error;
          return cb(e, data);
        }
        if (options.expectedKey != null) {
          if (data[options.expectedKey] == null) {
            return cb(new Error(("Invalid body received when fetching '" + options.url + "'. \n") + ("No key: " + options.expectedKey + ". " + buf)));
          }
        }
      }
      return cb(null, data);
    };

    return Airbud;

  })();

  module.exports = Airbud;

}).call(this);
<commit_msg>updated build<commit_after>// Generated by CoffeeScript 1.7.1
(function() {
  var Airbud, fs, request, retry;

  request = require("request");

  fs = require("fs");

  retry = require("retry");

  Airbud = (function() {
    function Airbud() {}

    Airbud._defaults = {
      url: null,
      retries: 0,
      timeout: null,
      parseJson: true,
      expectedKey: null,
      testDelay: 0
    };

    Airbud.fetch = function(options, cb) {
      var err, key, operation, operationDurations, timeoutForOperation, totalStart, val, _ref;
      if (!options.url) {
        err = new Error("You did not specify a url to fetch");
        return cb(err);
      }
      _ref = this._defaults;
      for (key in _ref) {
        val = _ref[key];
        if (options[key] == null) {
          options[key] = val;
        }
      }
      operation = retry.operation(options);
      timeoutForOperation = null;
      if (options.timeout != null) {
        timeoutForOperation = {
          timeout: options.timeout,
          cb: function() {
            var msg;
            msg = "Operation timeout of " + options.timeout + "ms reached.";
            err = new Error(msg);
            return operation.retry(err);
          }
        };
      }
      totalStart = +(new Date);
      operationDurations = 0;
      return operation.attempt((function(_this) {
        return function(currentAttempt) {
          var operationStart;
          operationStart = +(new Date);
          return _this._fetch(options, function(err, data) {
            var info, totalDuration;
            operationDurations += +(new Date) - operationStart;
            if (operation.retry(err)) {
              return;
            }
            totalDuration = +(new Date) - totalStart;
            info = {
              errors: operation.errors(),
              attempts: operation.attempts(),
              totalDuration: totalDuration,
              operationDuration: operationDurations / operation.attempts()
            };
            return cb(operation.mainError(), data, info);
          });
        };
      })(this), timeoutForOperation);
    };

    Airbud._fetch = function(options, cb) {
      var path;
      if (options.url.indexOf("file://") === 0) {
        path = options.url.substr(7, options.url.length).split("?")[0];
        setTimeout((function(_this) {
          return function() {
            return fs.readFile(path, "utf8", function(err, buf) {
              var returnErr;
              if (err) {
                returnErr = new Error("Error while opening " + path + ". " + err.message);
                return cb(returnErr);
              }
              return _this._handleData(options, buf, cb);
            });
          };
        })(this), options.testDelay);
        return;
      }
      return request.get(options.url, (function(_this) {
        return function(err, res, buf) {
          var msg;
          if (err) {
            return cb(err, buf);
          }
          if (options.expectedStatus != null) {
            if (options.expectedStatus.indexOf(parseInt(res.statusCode, 10)) === -1) {
              msg = "" + res.statusCode + " received when fetching '" + url + "'. \n expected";
              msg += " one status of: " + (options.expectedStatus.join(', ')) + ". " + buf;
              err = new Error(msg);
              return cb(err);
            }
          }
          return _this._handleData(options, buf, cb);
        };
      })(this));
    };

    Airbud._handleData = function(options, buf, cb) {
      var data, e, err, msg;
      data = buf;
      if (!options.parseJson) {
        return cb(null, data);
      }
      try {
        data = JSON.parse(data);
      } catch (_error) {
        e = _error;
        return cb(e, data);
      }
      if ((options.expectedKey != null) && (data[options.expectedKey] == null)) {
        msg = "Invalid body received when fetching '" + options.url + "'. \n";
        msg += "No key: " + options.expectedKey + ". " + buf;
        err = new Error(msg);
        return cb(err);
      }
      return cb(null, data);
    };

    return Airbud;

  })();

  module.exports = Airbud;

}).call(this);
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011 Vinay Pulim <vinay@milewise.com>
 * MIT Licensed
 */

'use strict';

var url = require('url');
var req = require('request');
var debug = require('debug')('node-soap');

var VERSION = require('../package.json').version;

/**
 * A class representing the http client
 * @param {Object} [options] Options object. It allows the customization of
 * `request` module
 *
 * @constructor
 */
function HttpClient(options) {
  options = options || {};
  this._request = options.request || req;
}

/**
 * Build the HTTP request (method, uri, headers, ...)
 * @param {String} rurl The resource url
 * @param {Object|String} data The payload
 * @param {Object} exheaders Extra http headers
 * @param {Object} exoptions Extra options
 * @returns {Object} The http request object for the `request` module
 */
HttpClient.prototype.buildRequest = function(rurl, data, exheaders, exoptions) {
  var curl = url.parse(rurl);
  var secure = curl.protocol === 'https:';
  var host = curl.hostname;
  var port = parseInt(curl.port, 10);
  var path = [curl.pathname || '/', curl.search || '', curl.hash || ''].join('');
  var method = data ? 'POST' : 'GET';
  var headers = {
    'User-Agent': 'node-soap/' + VERSION,
    'Accept': 'text/html,application/xhtml+xml,application/xml,text/xml;q=0.9,*/*;q=0.8',
    'Accept-Encoding': 'none',
    'Accept-Charset': 'utf-8',
    'Connection': !!exoptions.forever ? 'keep-alive' : 'close',
    'Host': host + (isNaN(port) ? '' : ':' + port)
  };
  var attr;
  var header;
  var mergeOptions = ['headers'];

  if (typeof data === 'string') {
    headers['Content-Length'] = Buffer.byteLength(data, 'utf8');
    headers['Content-Type'] = 'application/x-www-form-urlencoded';
  }

  exheaders = exheaders || {};
  for (attr in exheaders) {
    headers[attr] = exheaders[attr];
  }

  var options = {
    uri: curl,
    method: method,
    headers: headers,
    followAllRedirects: true
  };

  options.body = data;

  exoptions = exoptions || {};
  for (attr in exoptions) {
    if (mergeOptions.indexOf(attr) !== -1) {
      for (header in exoptions[attr]) {
        options[attr][header] = exoptions[attr][header];
      }
    } else {
      options[attr] = exoptions[attr];
    }
  }
  debug('Http request: %j', options);
  return options;
};

/**
 * Handle the http response
 * @param {Object} The req object
 * @param {Object} res The res object
 * @param {Object} body The http body
 * @param {Object} The parsed body
 */
HttpClient.prototype.handleResponse = function(req, res, body) {
  debug('Http response body: %j', body);
  if (typeof body === 'string') {
    // Remove any extra characters that appear before or after the SOAP
    // envelope.
    var match =
      body.replace(/<!--[\s\S]*?-->/, "").match(/(?:<\?[^?]*\?>[\s]*)?<([^:]*):Envelope([\S\s]*)<\/\1:Envelope>/i);
    if (match) {
      body = match[0];
    }
  }
  return body;
};

HttpClient.prototype.request = function(rurl, data, callback, exheaders, exoptions) {
  var self = this;
  var options = self.buildRequest(rurl, data, exheaders, exoptions);
  var req = self._request(options, function(err, res, body) {
    if (err) {
      return callback(err);
    }
    body = self.handleResponse(req, res, body);
    callback(null, res, body);
  });

  return req;
};

HttpClient.prototype.requestStream = function(rurl, data, exheaders, exoptions) {
  var self = this;
  var options = self.buildRequest(rurl, data, exheaders, exoptions);
  return self._request(options);
};

module.exports = HttpClient;
<commit_msg>Fixing tests broken by #979<commit_after>/*
 * Copyright (c) 2011 Vinay Pulim <vinay@milewise.com>
 * MIT Licensed
 */

'use strict';

var url = require('url');
var req = require('request');
var debug = require('debug')('node-soap');

var VERSION = require('../package.json').version;

/**
 * A class representing the http client
 * @param {Object} [options] Options object. It allows the customization of
 * `request` module
 *
 * @constructor
 */
function HttpClient(options) {
  options = options || {};
  this._request = options.request || req;
}

/**
 * Build the HTTP request (method, uri, headers, ...)
 * @param {String} rurl The resource url
 * @param {Object|String} data The payload
 * @param {Object} exheaders Extra http headers
 * @param {Object} exoptions Extra options
 * @returns {Object} The http request object for the `request` module
 */
HttpClient.prototype.buildRequest = function(rurl, data, exheaders, exoptions) {
  var curl = url.parse(rurl);
  var secure = curl.protocol === 'https:';
  var host = curl.hostname;
  var port = parseInt(curl.port, 10);
  var path = [curl.pathname || '/', curl.search || '', curl.hash || ''].join('');
  var method = data ? 'POST' : 'GET';
  var headers = {
    'User-Agent': 'node-soap/' + VERSION,
    'Accept': 'text/html,application/xhtml+xml,application/xml,text/xml;q=0.9,*/*;q=0.8',
    'Accept-Encoding': 'none',
    'Accept-Charset': 'utf-8',
    'Connection': exoptions && exoptions.forever ? 'keep-alive' : 'close',
    'Host': host + (isNaN(port) ? '' : ':' + port)
  };
  var attr;
  var header;
  var mergeOptions = ['headers'];

  if (typeof data === 'string') {
    headers['Content-Length'] = Buffer.byteLength(data, 'utf8');
    headers['Content-Type'] = 'application/x-www-form-urlencoded';
  }

  exheaders = exheaders || {};
  for (attr in exheaders) {
    headers[attr] = exheaders[attr];
  }

  var options = {
    uri: curl,
    method: method,
    headers: headers,
    followAllRedirects: true
  };

  options.body = data;

  exoptions = exoptions || {};
  for (attr in exoptions) {
    if (mergeOptions.indexOf(attr) !== -1) {
      for (header in exoptions[attr]) {
        options[attr][header] = exoptions[attr][header];
      }
    } else {
      options[attr] = exoptions[attr];
    }
  }
  debug('Http request: %j', options);
  return options;
};

/**
 * Handle the http response
 * @param {Object} The req object
 * @param {Object} res The res object
 * @param {Object} body The http body
 * @param {Object} The parsed body
 */
HttpClient.prototype.handleResponse = function(req, res, body) {
  debug('Http response body: %j', body);
  if (typeof body === 'string') {
    // Remove any extra characters that appear before or after the SOAP
    // envelope.
    var match =
      body.replace(/<!--[\s\S]*?-->/, "").match(/(?:<\?[^?]*\?>[\s]*)?<([^:]*):Envelope([\S\s]*)<\/\1:Envelope>/i);
    if (match) {
      body = match[0];
    }
  }
  return body;
};

HttpClient.prototype.request = function(rurl, data, callback, exheaders, exoptions) {
  var self = this;
  var options = self.buildRequest(rurl, data, exheaders, exoptions);
  var req = self._request(options, function(err, res, body) {
    if (err) {
      return callback(err);
    }
    body = self.handleResponse(req, res, body);
    callback(null, res, body);
  });

  return req;
};

HttpClient.prototype.requestStream = function(rurl, data, exheaders, exoptions) {
  var self = this;
  var options = self.buildRequest(rurl, data, exheaders, exoptions);
  return self._request(options);
};

module.exports = HttpClient;
<|endoftext|>


<commit_before>var fs = require('fs');
var net = require('net');
var path = require('path');
var util = require('util');
var actorify = require('actorify');
var spawn = require('child_process').spawn;

function Angelo(args) {
  this.filePath = '';
  this.nodeBinary = 'node';

  if (args) {
    // If args is a string, we're going to assume the
    // common case that it's a file path
    if (typeof args === 'string') {
      this.filePath = args;
    } else {
      var keys = Object.keys(args);
      keys.forEach(function(key) {
        this[key] = args[key];
      }, this);
    }
  }
  this.init();
}

Angelo.prototype.init = function() {
  this.initPlayer();

  setTimeout(function(_this) {
    _this.initConnection();
    _this.initActor();
    _this.actor.send('ready');
  }, 250, this);
};

Angelo.prototype.initPlayer = function() {
  var binFullPath = fs.realpathSync(__filename);
  var binDir = path.dirname(binFullPath);
  var libDir = path.join(binDir, '../lib');
  var playerPath = path.join(libDir, 'mocha-player.js');

  this.player  = spawn(this.nodeBinary, [playerPath, 3000], {detached:false});

  if (!process.hasOwnProperty('children')) {
    process.children = {};
  }
  process.children[this.player.pid] = this.player;

  this.player.on('exit', function() {
    delete process.children[this.pid];
  });
};

Angelo.prototype.initConnection = function() {
  this.sock = net.connect(3000);

  this.sock.on('error', function() {
    console.log('socket error');
  });
};

Angelo.prototype.initActor = function() {
  this.actor = actorify(this.sock);
  this.send = this.actor.send;

  this.actor.on('readied', function() {
    process.stdout.write('Client received message: readied\n');
    if (this.filePath !== '') {
      this.load();
    }
  }.bind(this));

  this.actor.on('echoed', function(message) {
    process.stdout.write('Client received message: echoed\n');
    if (message) {
      process.stdout.write('Client received echoed content: ' + util.inspect(message) + '\n');
    }
  });

  this.actor.on('loaded', function(playlists) {
    process.stdout.write('Client received message: loaded\n');
    if (playlists) {
      process.stdout.write('Client received load: ' + JSON.stringify(playlists,null,2) + '\n');
    }
    this.playlists = playlists;
  }.bind(this));

  this.actor.on('started', function() {
    process.stdout.write('Client received message: started\n');
  });

  this.actor.on('logged', function(message) {
    if (message) {
      process.stdout.write('Client received log: ' + message + '\n');
    }
  });

  this.actor.on('stopped', function(restart) {
    process.stdout.write('Client received message: stopped\n');
    // Re-init everything
    if (restart) {
      setTimeout(function(_this) {
        _this.init();
      }, 250, this);
  }
  }.bind(this));
};

Angelo.prototype.echo = function(message) {
  this.actor.send('echo', message);
};

Angelo.prototype.load = function(newFilePath) {
  if (newFilePath) {
    this.filePath = newFilePath;
  }
  if (this.filePath) {
    this.actor.send('load', this.filePath);
  }
};

Angelo.prototype.play = function() {
  this.actor.send('start');
};

Angelo.prototype.stop = function() {
  var restart = false;
  this.actor.send('stop', restart);
};

process.on("SIGINT", function() {
  process.stdout.write('Exiting...\n');
  process.exit();
});

process.on('SIGTERM', function() {
  process.stdout.write('Exiting...\n');
  process.exit();
});

process.on('exit', function () {
  // process.stdout.write('Event: "exit"\n');
  if (process.hasOwnProperty('children')) {
    // console.log('Child processes:');
    for (var key in process.children) {
      if (process.children.hasOwnProperty(key)) {
        // console.log('  pid: ' + process.children[key].pid);
        // console.log('  exitCode: ' + process.children[key].exitCode);
        // console.log('  killed: ' + process.children[key].killed);
        if ((process.children[key].exitCode === null) && (process.children[key].killed === false)) {
          process.children[key].kill('SIGINT');
          // console.log("  ... but now it's dead!");
        }
      }
    }
  }
  process.exit();
});

module.exports.Angelo = Angelo;<commit_msg>Angelo is now an event emitter.<commit_after>var fs = require('fs');
var net = require('net');
var path = require('path');
var util = require('util');
var actorify = require('actorify');
var spawn = require('child_process').spawn;
var EventEmitter = require('events').EventEmitter;

function Angelo(args) {
  this.filePath = '';
  this.nodeBinary = 'node';

  if (args) {
    // If args is a string, we're going to assume the
    // common case that it's a file path
    if (typeof args === 'string') {
      this.filePath = args;
    } else {
      var keys = Object.keys(args);
      keys.forEach(function(key) {
        this[key] = args[key];
      }, this);
    }
  }
  this.init();
}

util.inherits(Angelo, EventEmitter);

Angelo.prototype.init = function() {
  this.initPlayer();

  setTimeout(function(_this) {
    _this.initConnection();
    _this.initActor();
    _this.actor.send('ready');
  }, 250, this);
};

Angelo.prototype.initPlayer = function() {
  var binFullPath = fs.realpathSync(__filename);
  var binDir = path.dirname(binFullPath);
  var libDir = path.join(binDir, '../lib');
  var playerPath = path.join(libDir, 'mocha-player.js');

  this.player  = spawn(this.nodeBinary, [playerPath, 3000], {detached:false});

  if (!process.hasOwnProperty('children')) {
    process.children = {};
  }
  process.children[this.player.pid] = this.player;

  this.player.on('exit', function() {
    delete process.children[this.pid];
  });
};

Angelo.prototype.initConnection = function() {
  this.sock = net.connect(3000);

  this.sock.on('error', function() {
    console.log('socket error');
  });
};

Angelo.prototype.initActor = function() {
  this.actor = actorify(this.sock);
  this.send = this.actor.send;

  this.actor.on('readied', function() {
    process.stdout.write('Client received message: readied\n');
    if (this.filePath !== '') {
      this.load();
    }
  }.bind(this));

  this.actor.on('echoed', function(message) {
    process.stdout.write('Client received message: echoed\n');
    if (message) {
      process.stdout.write('Client received echoed content: ' + util.inspect(message) + '\n');
    }
  });

  this.actor.on('loaded', function(playlists) {
    process.stdout.write('Client received message: loaded\n');
    if (playlists) {
      process.stdout.write('Client received load: ' + JSON.stringify(playlists,null,2) + '\n');
    }
    this.playlists = playlists;
    this.emit('loaded');
  }.bind(this));

  this.actor.on('started', function() {
    process.stdout.write('Client received message: started\n');
  });

  this.actor.on('logged', function(message) {
    if (message) {
      process.stdout.write('Client received log: ' + message + '\n');
    }
  });

  this.actor.on('stopped', function(restart) {
    process.stdout.write('Client received message: stopped\n');
    // Re-init everything
    if (restart) {
      setTimeout(function(_this) {
        _this.init();
      }, 250, this);
  }
  }.bind(this));
};

Angelo.prototype.echo = function(message) {
  this.actor.send('echo', message);
};

Angelo.prototype.load = function(newFilePath) {
  if (newFilePath) {
    this.filePath = newFilePath;
  }
  if (this.filePath) {
    this.actor.send('load', this.filePath);
  }
};

Angelo.prototype.play = function() {
  this.actor.send('start');
};

Angelo.prototype.stop = function() {
  var restart = false;
  this.actor.send('stop', restart);
};

Angelo.prototype.restart = function() {
  var restart = true;
  this.actor.send('stop', restart);
};

process.on("SIGINT", function() {
  process.stdout.write('Exiting...\n');
  process.exit();
});

process.on('SIGTERM', function() {
  process.stdout.write('Exiting...\n');
  process.exit();
});

process.on('exit', function () {
  // process.stdout.write('Event: "exit"\n');
  if (process.hasOwnProperty('children')) {
    // console.log('Child processes:');
    for (var key in process.children) {
      if (process.children.hasOwnProperty(key)) {
        // console.log('  pid: ' + process.children[key].pid);
        // console.log('  exitCode: ' + process.children[key].exitCode);
        // console.log('  killed: ' + process.children[key].killed);
        if ((process.children[key].exitCode === null) && (process.children[key].killed === false)) {
          process.children[key].kill('SIGINT');
          // console.log("  ... but now it's dead!");
        }
      }
    }
  }
  process.exit();
});

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