Index: frontend/node_modules/asynckit/lib/abort.js
===================================================================
--- frontend/node_modules/asynckit/lib/abort.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/asynckit/lib/abort.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,29 @@
+// API
+module.exports = abort;
+
+/**
+ * Aborts leftover active jobs
+ *
+ * @param {object} state - current state object
+ */
+function abort(state)
+{
+  Object.keys(state.jobs).forEach(clean.bind(state));
+
+  // reset leftover jobs
+  state.jobs = {};
+}
+
+/**
+ * Cleans up leftover job by invoking abort function for the provided job id
+ *
+ * @this  state
+ * @param {string|number} key - job id to abort
+ */
+function clean(key)
+{
+  if (typeof this.jobs[key] == 'function')
+  {
+    this.jobs[key]();
+  }
+}
Index: frontend/node_modules/asynckit/lib/async.js
===================================================================
--- frontend/node_modules/asynckit/lib/async.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/asynckit/lib/async.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,34 @@
+var defer = require('./defer.js');
+
+// API
+module.exports = async;
+
+/**
+ * Runs provided callback asynchronously
+ * even if callback itself is not
+ *
+ * @param   {function} callback - callback to invoke
+ * @returns {function} - augmented callback
+ */
+function async(callback)
+{
+  var isAsync = false;
+
+  // check if async happened
+  defer(function() { isAsync = true; });
+
+  return function async_callback(err, result)
+  {
+    if (isAsync)
+    {
+      callback(err, result);
+    }
+    else
+    {
+      defer(function nextTick_callback()
+      {
+        callback(err, result);
+      });
+    }
+  };
+}
Index: frontend/node_modules/asynckit/lib/defer.js
===================================================================
--- frontend/node_modules/asynckit/lib/defer.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/asynckit/lib/defer.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,26 @@
+module.exports = defer;
+
+/**
+ * Runs provided function on next iteration of the event loop
+ *
+ * @param {function} fn - function to run
+ */
+function defer(fn)
+{
+  var nextTick = typeof setImmediate == 'function'
+    ? setImmediate
+    : (
+      typeof process == 'object' && typeof process.nextTick == 'function'
+      ? process.nextTick
+      : null
+    );
+
+  if (nextTick)
+  {
+    nextTick(fn);
+  }
+  else
+  {
+    setTimeout(fn, 0);
+  }
+}
Index: frontend/node_modules/asynckit/lib/iterate.js
===================================================================
--- frontend/node_modules/asynckit/lib/iterate.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/asynckit/lib/iterate.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,75 @@
+var async = require('./async.js')
+  , abort = require('./abort.js')
+  ;
+
+// API
+module.exports = iterate;
+
+/**
+ * Iterates over each job object
+ *
+ * @param {array|object} list - array or object (named list) to iterate over
+ * @param {function} iterator - iterator to run
+ * @param {object} state - current job status
+ * @param {function} callback - invoked when all elements processed
+ */
+function iterate(list, iterator, state, callback)
+{
+  // store current index
+  var key = state['keyedList'] ? state['keyedList'][state.index] : state.index;
+
+  state.jobs[key] = runJob(iterator, key, list[key], function(error, output)
+  {
+    // don't repeat yourself
+    // skip secondary callbacks
+    if (!(key in state.jobs))
+    {
+      return;
+    }
+
+    // clean up jobs
+    delete state.jobs[key];
+
+    if (error)
+    {
+      // don't process rest of the results
+      // stop still active jobs
+      // and reset the list
+      abort(state);
+    }
+    else
+    {
+      state.results[key] = output;
+    }
+
+    // return salvaged results
+    callback(error, state.results);
+  });
+}
+
+/**
+ * Runs iterator over provided job element
+ *
+ * @param   {function} iterator - iterator to invoke
+ * @param   {string|number} key - key/index of the element in the list of jobs
+ * @param   {mixed} item - job description
+ * @param   {function} callback - invoked after iterator is done with the job
+ * @returns {function|mixed} - job abort function or something else
+ */
+function runJob(iterator, key, item, callback)
+{
+  var aborter;
+
+  // allow shortcut if iterator expects only two arguments
+  if (iterator.length == 2)
+  {
+    aborter = iterator(item, async(callback));
+  }
+  // otherwise go with full three arguments
+  else
+  {
+    aborter = iterator(item, key, async(callback));
+  }
+
+  return aborter;
+}
Index: frontend/node_modules/asynckit/lib/readable_asynckit.js
===================================================================
--- frontend/node_modules/asynckit/lib/readable_asynckit.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/asynckit/lib/readable_asynckit.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,91 @@
+var streamify = require('./streamify.js')
+  , defer     = require('./defer.js')
+  ;
+
+// API
+module.exports = ReadableAsyncKit;
+
+/**
+ * Base constructor for all streams
+ * used to hold properties/methods
+ */
+function ReadableAsyncKit()
+{
+  ReadableAsyncKit.super_.apply(this, arguments);
+
+  // list of active jobs
+  this.jobs = {};
+
+  // add stream methods
+  this.destroy = destroy;
+  this._start  = _start;
+  this._read   = _read;
+}
+
+/**
+ * Destroys readable stream,
+ * by aborting outstanding jobs
+ *
+ * @returns {void}
+ */
+function destroy()
+{
+  if (this.destroyed)
+  {
+    return;
+  }
+
+  this.destroyed = true;
+
+  if (typeof this.terminator == 'function')
+  {
+    this.terminator();
+  }
+}
+
+/**
+ * Starts provided jobs in async manner
+ *
+ * @private
+ */
+function _start()
+{
+  // first argument – runner function
+  var runner = arguments[0]
+    // take away first argument
+    , args   = Array.prototype.slice.call(arguments, 1)
+      // second argument - input data
+    , input  = args[0]
+      // last argument - result callback
+    , endCb  = streamify.callback.call(this, args[args.length - 1])
+    ;
+
+  args[args.length - 1] = endCb;
+  // third argument - iterator
+  args[1] = streamify.iterator.call(this, args[1]);
+
+  // allow time for proper setup
+  defer(function()
+  {
+    if (!this.destroyed)
+    {
+      this.terminator = runner.apply(null, args);
+    }
+    else
+    {
+      endCb(null, Array.isArray(input) ? [] : {});
+    }
+  }.bind(this));
+}
+
+
+/**
+ * Implement _read to comply with Readable streams
+ * Doesn't really make sense for flowing object mode
+ *
+ * @private
+ */
+function _read()
+{
+
+}
Index: frontend/node_modules/asynckit/lib/readable_parallel.js
===================================================================
--- frontend/node_modules/asynckit/lib/readable_parallel.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/asynckit/lib/readable_parallel.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,25 @@
+var parallel = require('../parallel.js');
+
+// API
+module.exports = ReadableParallel;
+
+/**
+ * Streaming wrapper to `asynckit.parallel`
+ *
+ * @param   {array|object} list - array or object (named list) to iterate over
+ * @param   {function} iterator - iterator to run
+ * @param   {function} callback - invoked when all elements processed
+ * @returns {stream.Readable#}
+ */
+function ReadableParallel(list, iterator, callback)
+{
+  if (!(this instanceof ReadableParallel))
+  {
+    return new ReadableParallel(list, iterator, callback);
+  }
+
+  // turn on object mode
+  ReadableParallel.super_.call(this, {objectMode: true});
+
+  this._start(parallel, list, iterator, callback);
+}
Index: frontend/node_modules/asynckit/lib/readable_serial.js
===================================================================
--- frontend/node_modules/asynckit/lib/readable_serial.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/asynckit/lib/readable_serial.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,25 @@
+var serial = require('../serial.js');
+
+// API
+module.exports = ReadableSerial;
+
+/**
+ * Streaming wrapper to `asynckit.serial`
+ *
+ * @param   {array|object} list - array or object (named list) to iterate over
+ * @param   {function} iterator - iterator to run
+ * @param   {function} callback - invoked when all elements processed
+ * @returns {stream.Readable#}
+ */
+function ReadableSerial(list, iterator, callback)
+{
+  if (!(this instanceof ReadableSerial))
+  {
+    return new ReadableSerial(list, iterator, callback);
+  }
+
+  // turn on object mode
+  ReadableSerial.super_.call(this, {objectMode: true});
+
+  this._start(serial, list, iterator, callback);
+}
Index: frontend/node_modules/asynckit/lib/readable_serial_ordered.js
===================================================================
--- frontend/node_modules/asynckit/lib/readable_serial_ordered.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/asynckit/lib/readable_serial_ordered.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,29 @@
+var serialOrdered = require('../serialOrdered.js');
+
+// API
+module.exports = ReadableSerialOrdered;
+// expose sort helpers
+module.exports.ascending  = serialOrdered.ascending;
+module.exports.descending = serialOrdered.descending;
+
+/**
+ * Streaming wrapper to `asynckit.serialOrdered`
+ *
+ * @param   {array|object} list - array or object (named list) to iterate over
+ * @param   {function} iterator - iterator to run
+ * @param   {function} sortMethod - custom sort function
+ * @param   {function} callback - invoked when all elements processed
+ * @returns {stream.Readable#}
+ */
+function ReadableSerialOrdered(list, iterator, sortMethod, callback)
+{
+  if (!(this instanceof ReadableSerialOrdered))
+  {
+    return new ReadableSerialOrdered(list, iterator, sortMethod, callback);
+  }
+
+  // turn on object mode
+  ReadableSerialOrdered.super_.call(this, {objectMode: true});
+
+  this._start(serialOrdered, list, iterator, sortMethod, callback);
+}
Index: frontend/node_modules/asynckit/lib/state.js
===================================================================
--- frontend/node_modules/asynckit/lib/state.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/asynckit/lib/state.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,37 @@
+// API
+module.exports = state;
+
+/**
+ * Creates initial state object
+ * for iteration over list
+ *
+ * @param   {array|object} list - list to iterate over
+ * @param   {function|null} sortMethod - function to use for keys sort,
+ *                                     or `null` to keep them as is
+ * @returns {object} - initial state object
+ */
+function state(list, sortMethod)
+{
+  var isNamedList = !Array.isArray(list)
+    , initState =
+    {
+      index    : 0,
+      keyedList: isNamedList || sortMethod ? Object.keys(list) : null,
+      jobs     : {},
+      results  : isNamedList ? {} : [],
+      size     : isNamedList ? Object.keys(list).length : list.length
+    }
+    ;
+
+  if (sortMethod)
+  {
+    // sort array keys based on it's values
+    // sort object's keys just on own merit
+    initState.keyedList.sort(isNamedList ? sortMethod : function(a, b)
+    {
+      return sortMethod(list[a], list[b]);
+    });
+  }
+
+  return initState;
+}
Index: frontend/node_modules/asynckit/lib/streamify.js
===================================================================
--- frontend/node_modules/asynckit/lib/streamify.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/asynckit/lib/streamify.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,141 @@
+var async = require('./async.js');
+
+// API
+module.exports = {
+  iterator: wrapIterator,
+  callback: wrapCallback
+};
+
+/**
+ * Wraps iterators with long signature
+ *
+ * @this    ReadableAsyncKit#
+ * @param   {function} iterator - function to wrap
+ * @returns {function} - wrapped function
+ */
+function wrapIterator(iterator)
+{
+  var stream = this;
+
+  return function(item, key, cb)
+  {
+    var aborter
+      , wrappedCb = async(wrapIteratorCallback.call(stream, cb, key))
+      ;
+
+    stream.jobs[key] = wrappedCb;
+
+    // it's either shortcut (item, cb)
+    if (iterator.length == 2)
+    {
+      aborter = iterator(item, wrappedCb);
+    }
+    // or long format (item, key, cb)
+    else
+    {
+      aborter = iterator(item, key, wrappedCb);
+    }
+
+    return aborter;
+  };
+}
+
+/**
+ * Wraps provided callback function
+ * allowing to execute snitch function before
+ * real callback
+ *
+ * @this    ReadableAsyncKit#
+ * @param   {function} callback - function to wrap
+ * @returns {function} - wrapped function
+ */
+function wrapCallback(callback)
+{
+  var stream = this;
+
+  var wrapped = function(error, result)
+  {
+    return finisher.call(stream, error, result, callback);
+  };
+
+  return wrapped;
+}
+
+/**
+ * Wraps provided iterator callback function
+ * makes sure snitch only called once,
+ * but passes secondary calls to the original callback
+ *
+ * @this    ReadableAsyncKit#
+ * @param   {function} callback - callback to wrap
+ * @param   {number|string} key - iteration key
+ * @returns {function} wrapped callback
+ */
+function wrapIteratorCallback(callback, key)
+{
+  var stream = this;
+
+  return function(error, output)
+  {
+    // don't repeat yourself
+    if (!(key in stream.jobs))
+    {
+      callback(error, output);
+      return;
+    }
+
+    // clean up jobs
+    delete stream.jobs[key];
+
+    return streamer.call(stream, error, {key: key, value: output}, callback);
+  };
+}
+
+/**
+ * Stream wrapper for iterator callback
+ *
+ * @this  ReadableAsyncKit#
+ * @param {mixed} error - error response
+ * @param {mixed} output - iterator output
+ * @param {function} callback - callback that expects iterator results
+ */
+function streamer(error, output, callback)
+{
+  if (error && !this.error)
+  {
+    this.error = error;
+    this.pause();
+    this.emit('error', error);
+    // send back value only, as expected
+    callback(error, output && output.value);
+    return;
+  }
+
+  // stream stuff
+  this.push(output);
+
+  // back to original track
+  // send back value only, as expected
+  callback(error, output && output.value);
+}
+
+/**
+ * Stream wrapper for finishing callback
+ *
+ * @this  ReadableAsyncKit#
+ * @param {mixed} error - error response
+ * @param {mixed} output - iterator output
+ * @param {function} callback - callback that expects final results
+ */
+function finisher(error, output, callback)
+{
+  // signal end of the stream
+  // only for successfully finished streams
+  if (!error)
+  {
+    this.push(null);
+  }
+
+  // back to original track
+  callback(error, output);
+}
Index: frontend/node_modules/asynckit/lib/terminator.js
===================================================================
--- frontend/node_modules/asynckit/lib/terminator.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/asynckit/lib/terminator.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,29 @@
+var abort = require('./abort.js')
+  , async = require('./async.js')
+  ;
+
+// API
+module.exports = terminator;
+
+/**
+ * Terminates jobs in the attached state context
+ *
+ * @this  AsyncKitState#
+ * @param {function} callback - final callback to invoke after termination
+ */
+function terminator(callback)
+{
+  if (!Object.keys(this.jobs).length)
+  {
+    return;
+  }
+
+  // fast forward iteration index
+  this.index = this.size;
+
+  // abort jobs
+  abort(this);
+
+  // send back results we have so far
+  async(callback)(null, this.results);
+}
