raj-compose
Version:
Program composition for Raj
146 lines (117 loc) • 3.87 kB
JavaScript
;
var invariant = require('invariant');
function mapEffect(effect, callback) {
invariant(typeof callback === 'function', 'callback must be a function');
if (!effect) {
return effect;
}
invariant(typeof effect === 'function', 'Effects must be functions or falsy');
return function _mapEffect(dispatch) {
function intercept(message) {
dispatch(callback(message));
}
return effect(intercept);
};
}
function batchEffects(effects) {
for (var i = 0; i < effects.length; i++) {
var effect = effects[i];
invariant(!effect || typeof effect === 'function', 'Effects must be functions or falsy');
}
return function _batchEffects(dispatch) {
return effects.map(function (effect) {
if (effect) {
return effect(dispatch);
}
});
};
}
function ensureProgram(program) {
invariant(program, 'program must be truthy');
invariant(Array.isArray(program.init), 'program.init must be an array');
invariant(typeof program.update === 'function', 'program.update must be a function');
invariant(typeof program.view === 'function', 'program.view must be a function');
invariant(!program.done || typeof program.done === 'function', 'program.done must be a function if included');
}
function mapProgram(program, callback) {
ensureProgram(program);
invariant(typeof callback === 'function', 'callback must be a function');
var start = program.init;
var init = [start[0], mapEffect(start[1], callback)];
function update(msg, state) {
var change = program.update(msg, state);
return [change[0], mapEffect(change[1], callback)];
}
function view(state, dispatch) {
return program.view(state, function (msg) {
return dispatch(callback(msg));
});
}
return { init: init, update: update, view: view, done: program.done };
}
function batchPrograms(programs, containerView) {
invariant(Array.isArray(programs), 'programs must be an array');
invariant(typeof containerView === 'function', 'containerView must be a function');
var embeds = [];
var states = [];
var effects = [];
var programCount = programs.length;
var _loop = function _loop(i) {
var index = i;
var program = programs[index];
ensureProgram(program);
var embed = mapProgram(program, function (data) {
return { index: index, data: data };
});
embeds.push(embed);
states.push(embed.init[0]);
effects.push(embed.init[1]);
};
for (var i = 0; i < programCount; i++) {
_loop(i);
}
var init = [states, batchEffects(effects)];
function update(msg, state) {
var index = msg.index,
data = msg.data;
var change = embeds[index].update(data, state[index]);
var newState = state.slice(0);
newState[index] = change[0];
return [newState, change[1]];
}
function view(state, dispatch) {
var programViews = embeds.map(function (embed, index) {
return function () {
return embed.view(state[index], dispatch);
};
});
return containerView(programViews);
}
function done(state) {
for (var i = 0; i < programCount; i++) {
var _done = embeds[i].done;
if (_done) {
_done(state[i]);
}
}
}
return { init: init, update: update, view: view, done: done };
}
function assembleProgram(_ref) {
var data = _ref.data,
dataOptions = _ref.dataOptions,
logic = _ref.logic,
logicOptions = _ref.logicOptions,
_view = _ref.view,
viewOptions = _ref.viewOptions;
return Object.assign({
view: function view(model, dispatch) {
return _view(model, dispatch, viewOptions);
}
}, logic(data(dataOptions), logicOptions));
}
exports.mapEffect = mapEffect;
exports.batchEffects = batchEffects;
exports.mapProgram = mapProgram;
exports.batchPrograms = batchPrograms;
exports.assembleProgram = assembleProgram;