/* Copyright © 2015-2016 David Valdman */
define(function(require, exports, module) {
var EventHandler = require('../events/EventHandler');
var EventMapper = require('../events/EventMapper');
var EventFilter = require('../events/EventFilter');
var EventSplitter = require('../events/EventSplitter');
/**
* A SimpleStream wraps an EventHandler and provides convenience
* methods of `map`, `filter`, `split`, and `pluck` to
* transform one stream into another.
*
* @example
*
* @class SimpleStream
* @extends Core.EventHandler
* @private
* @namespace Streams
* @constructor
*/
function SimpleStream(){
EventHandler.call(this);
}
SimpleStream.prototype = Object.create(EventHandler.prototype);
SimpleStream.prototype.constructor = SimpleStream;
/**
* Map converts the current stream into a new stream
* with a modified (mapped) data payload.
*
* @method map
* @param mapperFn {Function} Function to map event payload
*/
SimpleStream.prototype.map = function(mapperFn){
var stream = new SimpleStream();
var mapper = new EventMapper(mapperFn);
stream.subscribe(mapper).subscribe(this);
return stream;
};
/**
* Filter converts the current stream into a new stream
* that only emits if the filter condition is satisfied.
* The function should return a Boolean.
*
* @method filter
* @param filterFn {Function} Function to filter event payload
*/
SimpleStream.prototype.filter = function(filterFn){
var filter = new EventFilter(filterFn);
var filteredStream = new SimpleStream();
filteredStream.subscribe(filter).subscribe(this);
return filteredStream;
};
/**
* Split maps one of several streams based on custom logic.
* The function should return an EventEmitter.
*
* @method split
* @param splitterFn {Function} Splitter function
*/
SimpleStream.prototype.split = function(splitterFn){
var splitter = new EventSplitter(splitterFn);
var splitStream = new SimpleStream();
splitStream.subscribe(splitter).subscribe(this);
return splitStream;
};
/**
* Pluck is an opinionated mapper. It projects a Stream
* onto one of its return values.
*
* Useful if a Stream returns an array or an object.
*
* @method pluck
* @param key {String|Number} Key to project event payload onto
*/
SimpleStream.prototype.pluck = function(key){
return this.map(function(value){
return value[key];
});
};
//TODO: can this be inherited by other streams?
SimpleStream.merge = function(){};
/**
* Lift is like map, except it maps several event sources,
* not only one.
*
* @example
*
* var liftedStream = SimpleStream.lift(function(payload1, payload2){
* return payload1 + payload2;
* }, [stream2, stream2]);
*
* liftedStream.on('name'), function(data){
* // data = 3;
* });
*
* stream2.emit('name', 1);
* stream2.emit('name', 2);
*
* @method lift
* @static
* @param map {Function} Function to map stream payloads
* @param streams {Array|Object} Stream sources
*/
SimpleStream.lift = function(map, streams){
//TODO: fix comma separated arguments
var mergedStream = (streams instanceof Array)
? this.merge(streams)
: this.merge.apply(null, Array.prototype.splice.call(arguments, 1));
var mappedStream = new EventMapper(function liftMap(data){
return map.apply(null, data);
});
var liftedStream = new SimpleStream();
liftedStream.subscribe(mappedStream).subscribe(mergedStream);
return liftedStream;
};
module.exports = SimpleStream;
});