UNPKG

noflo

Version:

Flow-Based Programming environment for JavaScript

270 lines (255 loc) 7.71 kB
(function() { var ComponentLoader, Graph, IP, Network, getType, internalSocket, normalizeOptions, normalizeOutput, prepareInputMap, prepareNetwork, runNetwork, sendOutputMap; ComponentLoader = require('./ComponentLoader').ComponentLoader; Network = require('./Network').Network; IP = require('./IP'); internalSocket = require('./InternalSocket'); Graph = require('fbp-graph').Graph; normalizeOptions = function(options, component) { if (!options) { options = {}; } if (!options.name) { options.name = component; } if (options.loader) { options.baseDir = options.loader.baseDir; } if (!options.baseDir && process && process.cwd) { options.baseDir = process.cwd(); } if (!options.loader) { options.loader = new ComponentLoader(options.baseDir); } if (!options.raw) { options.raw = false; } return options; }; prepareNetwork = function(component, options, callback) { return options.loader.load(component, function(err, instance) { var def, graph, inPorts, network, nodeName, outPorts, port; if (err) { return callback(err); } graph = new Graph(options.name); nodeName = options.name; graph.addNode(nodeName, component); inPorts = instance.inPorts.ports || instance.inPorts; outPorts = instance.outPorts.ports || instance.outPorts; for (port in inPorts) { def = inPorts[port]; graph.addInport(port, nodeName, port); } for (port in outPorts) { def = outPorts[port]; graph.addOutport(port, nodeName, port); } graph.componentLoader = options.loader; network = new Network(graph, options); return network.connect(function(err) { if (err) { return callback(err); } return callback(null, network); }); }); }; runNetwork = function(network, inputs, options, callback) { var inPorts, inSockets, outPorts, outSockets, process, received; process = network.getNode(options.name); inPorts = Object.keys(network.graph.inports); inSockets = {}; inPorts.forEach(function(inport) { inSockets[inport] = internalSocket.createSocket(); return process.component.inPorts[inport].attach(inSockets[inport]); }); received = []; outPorts = Object.keys(network.graph.outports); outSockets = {}; outPorts.forEach(function(outport) { outSockets[outport] = internalSocket.createSocket(); process.component.outPorts[outport].attach(outSockets[outport]); return outSockets[outport].on('ip', function(ip) { var res; res = {}; res[outport] = ip; return received.push(res); }); }); network.once('end', function() { var port, socket; for (port in outSockets) { socket = outSockets[port]; process.component.outPorts[port].detach(socket); } outSockets = {}; inSockets = {}; return callback(null, received); }); return network.start(function(err) { var i, inputMap, len, port, results, value; if (err) { return callback(err); } results = []; for (i = 0, len = inputs.length; i < len; i++) { inputMap = inputs[i]; results.push((function() { var results1; results1 = []; for (port in inputMap) { value = inputMap[port]; if (IP.isIP(value)) { inSockets[port].post(value); continue; } results1.push(inSockets[port].post(new IP('data', value))); } return results1; })()); } return results; }); }; getType = function(inputs, network) { var key, maps, value; if (typeof inputs !== 'object') { return 'simple'; } if (Array.isArray(inputs)) { maps = inputs.filter(function(entry) { return getType(entry, network) === 'map'; }); if (maps.length === inputs.length) { return 'sequence'; } return 'simple'; } if (!Object.keys(inputs).length) { return 'simple'; } for (key in inputs) { value = inputs[key]; if (!network.graph.inports[key]) { return 'simple'; } } return 'map'; }; prepareInputMap = function(inputs, inputType, network) { var inPort, map; if (inputType === 'sequence') { return inputs; } if (inputType === 'map') { return [inputs]; } inPort = Object.keys(network.graph.inports)[0]; if (network.graph.inports["in"]) { inPort = 'in'; } map = {}; map[inPort] = inputs; return [map]; }; normalizeOutput = function(values, options) { var current, i, len, packet, previous, result; if (options.raw) { return values; } result = []; previous = null; current = result; for (i = 0, len = values.length; i < len; i++) { packet = values[i]; if (packet.type === 'openBracket') { previous = current; current = []; previous.push(current); } if (packet.type === 'data') { current.push(packet.data); } if (packet.type === 'closeBracket') { current = previous; } } if (result.length === 1) { return result[0]; } return result; }; sendOutputMap = function(outputs, resultType, options, callback) { var errors, i, key, len, map, mappedOutputs, outputKeys, packets, port, result, val, withValue; errors = outputs.filter(function(map) { return map.error != null; }).map(function(map) { return map.error; }); if (errors.length) { return callback(normalizeOutput(errors, options)); } if (resultType === 'sequence') { return callback(null, outputs.map(function(map) { var key, res, val; res = {}; for (key in map) { val = map[key]; if (options.raw) { res[key] = val; continue; } res[key] = normalizeOutput([val], options); } return res; })); } mappedOutputs = {}; for (i = 0, len = outputs.length; i < len; i++) { map = outputs[i]; for (key in map) { val = map[key]; if (!mappedOutputs[key]) { mappedOutputs[key] = []; } mappedOutputs[key].push(val); } } outputKeys = Object.keys(mappedOutputs); withValue = outputKeys.filter(function(outport) { return mappedOutputs[outport].length > 0; }); if (withValue.length === 0) { return callback(null); } if (withValue.length === 1 && resultType === 'simple') { return callback(null, normalizeOutput(mappedOutputs[withValue[0]], options)); } result = {}; for (port in mappedOutputs) { packets = mappedOutputs[port]; result[port] = normalizeOutput(packets, options); } return callback(null, result); }; exports.asCallback = function(component, options) { options = normalizeOptions(options, component); return function(inputs, callback) { return prepareNetwork(component, options, function(err, network) { var inputMap, resultType; if (err) { return callback(err); } resultType = getType(inputs, network); inputMap = prepareInputMap(inputs, resultType, network); return runNetwork(network, inputMap, options, function(err, outputMap) { if (err) { return callback(err); } return sendOutputMap(outputMap, resultType, options, callback); }); }); }; }; }).call(this);