UNPKG

noflo

Version:

Flow-Based Programming environment for JavaScript

1,463 lines (1,421 loc) 48.7 kB
(function() { var IP, InternalSocket, OutPortWrapper, StreamReceiver, StreamSender, checkDeprecation, checkWirePatternPreconditions, checkWirePatternPreconditionsInput, checkWirePatternPreconditionsParams, debug, getGroupContext, getInputData, getOutputProxy, handleInputCollation, isArray, legacyWirePattern, platform, populateParams, processApiWirePattern, reorderBuffer, setupBracketForwarding, setupControlPorts, setupErrorHandler, setupSendDefaults, utils, slice = [].slice, hasProp = {}.hasOwnProperty; StreamSender = require('./Streams').StreamSender; StreamReceiver = require('./Streams').StreamReceiver; InternalSocket = require('./InternalSocket'); IP = require('./IP'); platform = require('./Platform'); utils = require('./Utils'); debug = require('debug')('noflo:helpers'); isArray = function(obj) { if (Array.isArray) { return Array.isArray(obj); } return Object.prototype.toString.call(arg) === '[object Array]'; }; exports.MapComponent = function(component, func, config) { platform.deprecated('noflo.helpers.MapComponent is deprecated. Please port to Process API'); if (!config) { config = {}; } if (!config.inPort) { config.inPort = 'in'; } if (!config.outPort) { config.outPort = 'out'; } if (!component.forwardBrackets) { component.forwardBrackets = {}; } component.forwardBrackets[config.inPort] = [config.outPort]; return component.process(function(input, output) { var data, groups, outProxy; if (!input.hasData(config.inPort)) { return; } data = input.getData(config.inPort); groups = getGroupContext(component, config.inPort, input); outProxy = getOutputProxy([config.outPort], output); func(data, groups, outProxy); return output.done(); }); }; exports.WirePattern = function(component, config, proc) { var inPorts, outPorts, ref, setup; inPorts = 'in' in config ? config["in"] : 'in'; if (!isArray(inPorts)) { inPorts = [inPorts]; } outPorts = 'out' in config ? config.out : 'out'; if (!isArray(outPorts)) { outPorts = [outPorts]; } if (!('error' in config)) { config.error = 'error'; } if (!('async' in config)) { config.async = false; } if (!('ordered' in config)) { config.ordered = true; } if (!('group' in config)) { config.group = false; } if (!('field' in config)) { config.field = null; } if (!('forwardGroups' in config)) { config.forwardGroups = false; } if (config.forwardGroups) { if (typeof config.forwardGroups === 'string') { config.forwardGroups = [config.forwardGroups]; } if (typeof config.forwardGroups === 'boolean') { config.forwardGroups = inPorts; } } if (!('receiveStreams' in config)) { config.receiveStreams = false; } if (config.receiveStreams) { throw new Error('WirePattern receiveStreams is deprecated'); } if (!('sendStreams' in config)) { config.sendStreams = false; } if (config.sendStreams) { throw new Error('WirePattern sendStreams is deprecated'); } if (config.async) { config.sendStreams = outPorts; } if (!('params' in config)) { config.params = []; } if (typeof config.params === 'string') { config.params = [config.params]; } if (!('name' in config)) { config.name = ''; } if (!('dropInput' in config)) { config.dropInput = false; } if (!('arrayPolicy' in config)) { config.arrayPolicy = { "in": 'any', params: 'all' }; } config.inPorts = inPorts; config.outPorts = outPorts; checkDeprecation(config, proc); if (config.legacy || (typeof process !== "undefined" && process !== null ? (ref = process.env) != null ? ref.NOFLO_WIREPATTERN_LEGACY : void 0 : void 0)) { platform.deprecated('noflo.helpers.WirePattern legacy mode is deprecated'); setup = legacyWirePattern; } else { setup = processApiWirePattern; } return setup(component, config, proc); }; processApiWirePattern = function(component, config, func) { setupControlPorts(component, config); setupSendDefaults(component); setupBracketForwarding(component, config); component.ordered = config.ordered; return component.process(function(input, output, context) { var data, errorHandler, groups, outProxy, postpone, resume; if (!checkWirePatternPreconditions(config, input, output)) { return; } component.params = populateParams(config, input); data = getInputData(config, input); groups = getGroupContext(component, config.inPorts[0], input); outProxy = getOutputProxy(config.outPorts, output); debug("WirePattern Process API call with", data, groups, component.params, context.scope); postpone = function() { throw new Error('noflo.helpers.WirePattern postpone is deprecated'); }; resume = function() { throw new Error('noflo.helpers.WirePattern resume is deprecated'); }; if (!config.async) { errorHandler = setupErrorHandler(component, config, output); func.call(component, data, groups, outProxy, postpone, resume, input.scope); if (output.result.__resolved) { return; } errorHandler(); output.done(); return; } errorHandler = setupErrorHandler(component, config, output); return func.call(component, data, groups, outProxy, function(err) { errorHandler(); return output.done(err); }, postpone, resume, input.scope); }); }; checkDeprecation = function(config, func) { if (config.group) { platform.deprecated('noflo.helpers.WirePattern group option is deprecated. Please port to Process API'); } if (config.field) { platform.deprecated('noflo.helpers.WirePattern field option is deprecated. Please port to Process API'); } if (func.length > 4) { platform.deprecated('noflo.helpers.WirePattern postpone and resume are deprecated. Please port to Process API'); } if (!config.async) { platform.deprecated('noflo.helpers.WirePattern synchronous is deprecated. Please port to Process API'); } }; setupControlPorts = function(component, config) { var j, len, param, ref, results; ref = config.params; results = []; for (j = 0, len = ref.length; j < len; j++) { param = ref[j]; results.push(component.inPorts[param].options.control = true); } return results; }; setupBracketForwarding = function(component, config) { var inPort, inPorts, j, k, len, len1, outPort, ref; component.forwardBrackets = {}; if (!config.forwardGroups) { return; } inPorts = config.inPorts; if (isArray(config.forwardGroups)) { inPorts = config.forwardGroups; } for (j = 0, len = inPorts.length; j < len; j++) { inPort = inPorts[j]; component.forwardBrackets[inPort] = []; ref = config.outPorts; for (k = 0, len1 = ref.length; k < len1; k++) { outPort = ref[k]; component.forwardBrackets[inPort].push(outPort); } if (component.outPorts.error) { component.forwardBrackets[inPort].push('error'); } } }; setupErrorHandler = function(component, config, output) { var errorHandler, errors, failHandler, sendErrors; errors = []; errorHandler = function(e, groups) { if (groups == null) { groups = []; } platform.deprecated('noflo.helpers.WirePattern error method is deprecated. Please send error to callback instead'); errors.push({ err: e, groups: groups }); return component.hasErrors = true; }; failHandler = function(e, groups) { if (e == null) { e = null; } if (groups == null) { groups = []; } platform.deprecated('noflo.helpers.WirePattern fail method is deprecated. Please send error to callback instead'); if (e) { errorHandler(e, groups); } sendErrors(); return output.done(); }; sendErrors = function() { if (!errors.length) { return; } if (config.name) { output.sendIP('error', new IP('openBracket', config.name)); } errors.forEach(function(e) { var grp, j, k, len, len1, ref, ref1, results; ref = e.groups; for (j = 0, len = ref.length; j < len; j++) { grp = ref[j]; output.sendIP('error', new IP('openBracket', grp)); } output.sendIP('error', new IP('data', e.err)); ref1 = e.groups; results = []; for (k = 0, len1 = ref1.length; k < len1; k++) { grp = ref1[k]; results.push(output.sendIP('error', new IP('closeBracket', grp))); } return results; }); if (config.name) { output.sendIP('error', new IP('closeBracket', config.name)); } component.hasErrors = false; return errors = []; }; component.hasErrors = false; component.error = errorHandler; component.fail = failHandler; return sendErrors; }; setupSendDefaults = function(component) { var portsWithDefaults; portsWithDefaults = Object.keys(component.inPorts.ports).filter(function(p) { if (!component.inPorts[p].options.control) { return false; } if (!component.inPorts[p].hasDefault()) { return false; } return true; }); return component.sendDefaults = function() { platform.deprecated('noflo.helpers.WirePattern sendDefaults method is deprecated. Please start with a Network'); return portsWithDefaults.forEach(function(port) { var tempSocket; tempSocket = InternalSocket.createSocket(); component.inPorts[port].attach(tempSocket); tempSocket.send(); tempSocket.disconnect(); return component.inPorts[port].detach(tempSocket); }); }; }; populateParams = function(config, input) { var idx, j, k, len, len1, paramPort, params, ref, ref1; if (!config.params.length) { return; } params = {}; ref = config.params; for (j = 0, len = ref.length; j < len; j++) { paramPort = ref[j]; if (input.ports[paramPort].isAddressable()) { params[paramPort] = {}; ref1 = input.attached(paramPort); for (k = 0, len1 = ref1.length; k < len1; k++) { idx = ref1[k]; if (!input.hasData([paramPort, idx])) { continue; } params[paramPort][idx] = input.getData([paramPort, idx]); } continue; } params[paramPort] = input.getData(paramPort); } return params; }; reorderBuffer = function(buffer, matcher) { var brackets, idx, ip, j, k, len, len1, results, substream, substreamBrackets, substreamIdx; substream = null; brackets = []; substreamBrackets = []; for (idx = j = 0, len = buffer.length; j < len; idx = ++j) { ip = buffer[idx]; if (ip.type === 'openBracket') { brackets.push(ip.data); substreamBrackets.push(ip); continue; } if (ip.type === 'closeBracket') { brackets.pop(); if (substream) { substream.push(ip); } if (substreamBrackets.length) { substreamBrackets.pop(); } if (substream && !substreamBrackets.length) { break; } continue; } if (!matcher(ip, brackets)) { substreamBrackets = []; continue; } substream = substreamBrackets.slice(0); substream.push(ip); } substreamIdx = buffer.indexOf(substream[0]); if (substreamIdx === 0) { return; } buffer.splice(substreamIdx, substream.length); substream.reverse(); results = []; for (k = 0, len1 = substream.length; k < len1; k++) { ip = substream[k]; results.push(buffer.unshift(ip)); } return results; }; handleInputCollation = function(data, config, input, port, idx) { var buf; if (!config.group && !config.field) { return; } if (config.group) { buf = input.ports[port].getBuffer(input.scope, idx); reorderBuffer(buf, function(ip, brackets) { var grp, j, len, ref; ref = input.collatedBy.brackets; for (idx = j = 0, len = ref.length; j < len; idx = ++j) { grp = ref[idx]; if (brackets[idx] !== grp) { return false; } } return true; }); } if (config.field) { data[config.field] = input.collatedBy.field; buf = input.ports[port].getBuffer(input.scope, idx); return reorderBuffer(buf, function(ip) { return ip.data[config.field] === data[config.field]; }); } }; getInputData = function(config, input) { var data, idx, j, k, len, len1, port, ref, ref1; data = {}; ref = config.inPorts; for (j = 0, len = ref.length; j < len; j++) { port = ref[j]; if (input.ports[port].isAddressable()) { data[port] = {}; ref1 = input.attached(port); for (k = 0, len1 = ref1.length; k < len1; k++) { idx = ref1[k]; if (!input.hasData([port, idx])) { continue; } handleInputCollation(data, config, input, port, idx); data[port][idx] = input.getData([port, idx]); } continue; } if (!input.hasData(port)) { continue; } handleInputCollation(data, config, input, port); data[port] = input.getData(port); } if (config.inPorts.length === 1) { return data[config.inPorts[0]]; } return data; }; getGroupContext = function(component, port, input) { var ref, ref1; if (((ref = input.result.__bracketContext) != null ? ref[port] : void 0) == null) { return []; } if ((ref1 = input.collatedBy) != null ? ref1.brackets : void 0) { return input.collatedBy.brackets; } return input.result.__bracketContext[port].filter(function(c) { return c.source === port; }).map(function(c) { return c.ip.data; }); }; getOutputProxy = function(ports, output) { var outProxy; outProxy = {}; ports.forEach(function(port) { return outProxy[port] = { connect: function() {}, beginGroup: function(group, idx) { var ip; ip = new IP('openBracket', group); ip.index = idx; return output.sendIP(port, ip); }, send: function(data, idx) { var ip; ip = new IP('data', data); ip.index = idx; return output.sendIP(port, ip); }, endGroup: function(group, idx) { var ip; ip = new IP('closeBracket', group); ip.index = idx; return output.sendIP(port, ip); }, disconnect: function() {} }; }); if (ports.length === 1) { return outProxy[ports[0]]; } return outProxy; }; checkWirePatternPreconditions = function(config, input, output) { var attached, idx, inputsOk, j, k, len, len1, packetsDropped, paramsOk, port, ref; paramsOk = checkWirePatternPreconditionsParams(config, input); inputsOk = checkWirePatternPreconditionsInput(config, input); if (config.dropInput && !paramsOk) { packetsDropped = false; ref = config.inPorts; for (j = 0, len = ref.length; j < len; j++) { port = ref[j]; if (input.ports[port].isAddressable()) { attached = input.attached(port); if (!attached.length) { continue; } for (k = 0, len1 = attached.length; k < len1; k++) { idx = attached[k]; while (input.has([port, idx])) { packetsDropped = true; input.get([port, idx]).drop(); } } continue; } while (input.has(port)) { packetsDropped = true; input.get(port).drop(); } } if (packetsDropped) { output.done(); } } return inputsOk && paramsOk; }; checkWirePatternPreconditionsParams = function(config, input) { var attached, j, len, param, ref, withData; ref = config.params; for (j = 0, len = ref.length; j < len; j++) { param = ref[j]; if (!input.ports[param].isRequired()) { continue; } if (input.ports[param].isAddressable()) { attached = input.attached(param); if (!attached.length) { return false; } withData = attached.filter(function(idx) { return input.hasData([param, idx]); }); if (config.arrayPolicy.params === 'all') { if (withData.length !== attached.length) { return false; } continue; } if (!withData.length) { return false; } continue; } if (!input.hasData(param)) { return false; } } return true; }; checkWirePatternPreconditionsInput = function(config, input) { var attached, bracketsAtPorts, checkBrackets, checkPacket, checkPort, j, len, port, ref, withData; if (config.group) { bracketsAtPorts = {}; input.collatedBy = { brackets: [], ready: false }; checkBrackets = function(left, right) { var bracket, idx, j, len; for (idx = j = 0, len = left.length; j < len; idx = ++j) { bracket = left[idx]; if (right[idx] !== bracket) { return false; } } return true; }; checkPacket = function(ip, brackets) { var bracketId, bracketsToCheck; bracketsToCheck = brackets.slice(0); if (config.group instanceof RegExp) { bracketsToCheck = bracketsToCheck.slice(0, 1); if (!bracketsToCheck.length) { return false; } if (!config.group.test(bracketsToCheck[0])) { return false; } } if (input.collatedBy.ready) { return checkBrackets(input.collatedBy.brackets, bracketsToCheck); } bracketId = bracketsToCheck.join(':'); if (!bracketsAtPorts[bracketId]) { bracketsAtPorts[bracketId] = []; } if (bracketsAtPorts[bracketId].indexOf(port) === -1) { bracketsAtPorts[bracketId].push(port); } if (config.inPorts.indexOf(port) !== config.inPorts.length - 1) { return true; } if (bracketsAtPorts[bracketId].length !== config.inPorts.length) { return false; } if (input.collatedBy.ready) { return false; } input.collatedBy.ready = true; input.collatedBy.brackets = bracketsToCheck; return true; }; } if (config.field) { input.collatedBy = { field: void 0, ready: false }; } checkPort = function(port) { var buf, dataBrackets, hasData, hasMatching, ip, j, len, portBrackets; if (!config.group && !config.field) { return input.hasData(port); } if (config.group) { portBrackets = []; dataBrackets = []; hasMatching = false; buf = input.ports[port].getBuffer(input.scope); for (j = 0, len = buf.length; j < len; j++) { ip = buf[j]; if (ip.type === 'openBracket') { portBrackets.push(ip.data); continue; } if (ip.type === 'closeBracket') { portBrackets.pop(); if (portBrackets.length) { continue; } if (!hasData) { continue; } hasMatching = true; continue; } hasData = checkPacket(ip, portBrackets); continue; } return hasMatching; } if (config.field) { return input.hasStream(port, function(ip) { if (!input.collatedBy.ready) { input.collatedBy.field = ip.data[config.field]; input.collatedBy.ready = true; return true; } return ip.data[config.field] === input.collatedBy.field; }); } }; ref = config.inPorts; for (j = 0, len = ref.length; j < len; j++) { port = ref[j]; if (input.ports[port].isAddressable()) { attached = input.attached(port); if (!attached.length) { return false; } withData = attached.filter(function(idx) { return checkPort([port, idx]); }); if (config.arrayPolicy['in'] === 'all') { if (withData.length !== attached.length) { return false; } continue; } if (!withData.length) { return false; } continue; } if (!checkPort(port)) { return false; } } return true; }; OutPortWrapper = (function() { function OutPortWrapper(port1, scope1) { this.port = port1; this.scope = scope1; } OutPortWrapper.prototype.connect = function(socketId) { if (socketId == null) { socketId = null; } return this.port.openBracket(null, { scope: this.scope }, socketId); }; OutPortWrapper.prototype.beginGroup = function(group, socketId) { if (socketId == null) { socketId = null; } return this.port.openBracket(group, { scope: this.scope }, socketId); }; OutPortWrapper.prototype.send = function(data, socketId) { if (socketId == null) { socketId = null; } return this.port.sendIP('data', data, { scope: this.scope }, socketId, false); }; OutPortWrapper.prototype.endGroup = function(group, socketId) { if (socketId == null) { socketId = null; } return this.port.closeBracket(group, { scope: this.scope }, socketId); }; OutPortWrapper.prototype.disconnect = function(socketId) { if (socketId == null) { socketId = null; } return this.endGroup(socketId); }; OutPortWrapper.prototype.isConnected = function() { return this.port.isConnected(); }; OutPortWrapper.prototype.isAttached = function() { return this.port.isAttached(); }; return OutPortWrapper; })(); legacyWirePattern = function(component, config, proc) { var _wp, baseTearDown, closeGroupOnOuts, collectGroups, disconnectOuts, fn, fn1, gc, j, k, l, len, len1, len2, len3, len4, m, n, name, port, processQueue, ref, ref1, ref2, ref3, ref4, resumeTaskQ, sendGroupToOuts, setParamsScope; if (!('gcFrequency' in config)) { config.gcFrequency = 100; } if (!('gcTimeout' in config)) { config.gcTimeout = 300; } collectGroups = config.forwardGroups; if (collectGroups !== false && config.group) { collectGroups = true; } ref = config.inPorts; for (j = 0, len = ref.length; j < len; j++) { name = ref[j]; if (!component.inPorts[name]) { throw new Error("no inPort named '" + name + "'"); } } ref1 = config.outPorts; for (k = 0, len1 = ref1.length; k < len1; k++) { name = ref1[k]; if (!component.outPorts[name]) { throw new Error("no outPort named '" + name + "'"); } } disconnectOuts = function() { var l, len2, p, ref2, results; ref2 = config.outPorts; results = []; for (l = 0, len2 = ref2.length; l < len2; l++) { p = ref2[l]; if (component.outPorts[p].isConnected()) { results.push(component.outPorts[p].disconnect()); } else { results.push(void 0); } } return results; }; sendGroupToOuts = function(grp) { var l, len2, p, ref2, results; ref2 = config.outPorts; results = []; for (l = 0, len2 = ref2.length; l < len2; l++) { p = ref2[l]; results.push(component.outPorts[p].beginGroup(grp)); } return results; }; closeGroupOnOuts = function(grp) { var l, len2, p, ref2, results; ref2 = config.outPorts; results = []; for (l = 0, len2 = ref2.length; l < len2; l++) { p = ref2[l]; results.push(component.outPorts[p].endGroup(grp)); } return results; }; component.requiredParams = []; component.defaultedParams = []; component.gcCounter = 0; component._wpData = {}; _wp = function(scope) { if (!(scope in component._wpData)) { component._wpData[scope] = {}; component._wpData[scope].groupedData = {}; component._wpData[scope].groupedGroups = {}; component._wpData[scope].groupedDisconnects = {}; component._wpData[scope].outputQ = []; component._wpData[scope].taskQ = []; component._wpData[scope].params = {}; component._wpData[scope].completeParams = []; component._wpData[scope].receivedParams = []; component._wpData[scope].defaultsSent = false; component._wpData[scope].disconnectData = {}; component._wpData[scope].disconnectQ = []; component._wpData[scope].groupBuffers = {}; component._wpData[scope].keyBuffers = {}; component._wpData[scope].gcTimestamps = {}; } return component._wpData[scope]; }; component.params = {}; setParamsScope = function(scope) { return component.params = _wp(scope).params; }; processQueue = function(scope) { var flushed, key, stream, streams, tmp; while (_wp(scope).outputQ.length > 0) { streams = _wp(scope).outputQ[0]; flushed = false; if (streams === null) { disconnectOuts(); flushed = true; } else { if (config.outPorts.length === 1) { tmp = {}; tmp[config.outPorts[0]] = streams; streams = tmp; } for (key in streams) { stream = streams[key]; if (stream.resolved) { stream.flush(); flushed = true; } } } if (flushed) { _wp(scope).outputQ.shift(); } if (!flushed) { return; } } }; if (config.async) { if ('load' in component.outPorts) { component.load = 0; } component.beforeProcess = function(scope, outs) { if (config.ordered) { _wp(scope).outputQ.push(outs); } component.load++; component.emit('activate', component.load); if ('load' in component.outPorts && component.outPorts.load.isAttached()) { component.outPorts.load.send(component.load); return component.outPorts.load.disconnect(); } }; component.afterProcess = function(scope, err, outs) { processQueue(scope); component.load--; if ('load' in component.outPorts && component.outPorts.load.isAttached()) { component.outPorts.load.send(component.load); component.outPorts.load.disconnect(); } return component.emit('deactivate', component.load); }; } component.sendDefaults = function(scope) { var l, len2, param, ref2, tempSocket; if (component.defaultedParams.length > 0) { ref2 = component.defaultedParams; for (l = 0, len2 = ref2.length; l < len2; l++) { param = ref2[l]; if (_wp(scope).receivedParams.indexOf(param) === -1) { tempSocket = InternalSocket.createSocket(); component.inPorts[param].attach(tempSocket); tempSocket.send(); tempSocket.disconnect(); component.inPorts[param].detach(tempSocket); } } } return _wp(scope).defaultsSent = true; }; resumeTaskQ = function(scope) { var results, task, temp; if (_wp(scope).completeParams.length === component.requiredParams.length && _wp(scope).taskQ.length > 0) { temp = _wp(scope).taskQ.slice(0); _wp(scope).taskQ = []; results = []; while (temp.length > 0) { task = temp.shift(); results.push(task()); } return results; } }; ref2 = config.params; for (l = 0, len2 = ref2.length; l < len2; l++) { port = ref2[l]; if (!component.inPorts[port]) { throw new Error("no inPort named '" + port + "'"); } if (component.inPorts[port].isRequired()) { component.requiredParams.push(port); } if (component.inPorts[port].hasDefault()) { component.defaultedParams.push(port); } } ref3 = config.params; fn = function(port) { var inPort; inPort = component.inPorts[port]; return inPort.handle = function(ip) { var event, index, payload, scope; event = ip.type; payload = ip.data; scope = ip.scope; index = ip.index; if (event !== 'data') { return; } if (inPort.isAddressable()) { if (!(port in _wp(scope).params)) { _wp(scope).params[port] = {}; } _wp(scope).params[port][index] = payload; if (config.arrayPolicy.params === 'all' && Object.keys(_wp(scope).params[port]).length < inPort.listAttached().length) { return; } } else { _wp(scope).params[port] = payload; } if (_wp(scope).completeParams.indexOf(port) === -1 && component.requiredParams.indexOf(port) > -1) { _wp(scope).completeParams.push(port); } _wp(scope).receivedParams.push(port); return resumeTaskQ(scope); }; }; for (m = 0, len3 = ref3.length; m < len3; m++) { port = ref3[m]; fn(port); } component.dropRequest = function(scope, key) { if (key in _wp(scope).disconnectData) { delete _wp(scope).disconnectData[key]; } if (key in _wp(scope).groupedData) { delete _wp(scope).groupedData[key]; } if (key in _wp(scope).groupedGroups) { return delete _wp(scope).groupedGroups[key]; } }; gc = function() { var current, key, len4, n, ref4, results, scope, val; component.gcCounter++; if (component.gcCounter % config.gcFrequency === 0) { ref4 = Object.keys(component._wpData); results = []; for (n = 0, len4 = ref4.length; n < len4; n++) { scope = ref4[n]; current = new Date().getTime(); results.push((function() { var ref5, results1; ref5 = _wp(scope).gcTimestamps; results1 = []; for (key in ref5) { val = ref5[key]; if ((current - val) > (config.gcTimeout * 1000)) { component.dropRequest(scope, key); results1.push(delete _wp(scope).gcTimestamps[key]); } else { results1.push(void 0); } } return results1; })()); } return results; } }; ref4 = config.inPorts; fn1 = function(port) { var inPort, needPortGroups; inPort = component.inPorts[port]; needPortGroups = collectGroups instanceof Array && collectGroups.indexOf(port) !== -1; return inPort.handle = function(ip) { var data, foundGroup, g, groupLength, groups, grp, i, index, key, len5, len6, len7, len8, o, obj, out, outs, payload, postpone, postponedToQ, q, r, ref5, ref6, ref7, ref8, reqId, requiredLength, resume, s, scope, t, task, tmp, u, whenDone, whenDoneGroups, wrp; index = ip.index; payload = ip.data; scope = ip.scope; if (!(port in _wp(scope).groupBuffers)) { _wp(scope).groupBuffers[port] = []; } if (!(port in _wp(scope).keyBuffers)) { _wp(scope).keyBuffers[port] = null; } switch (ip.type) { case 'openBracket': if (payload === null) { return; } _wp(scope).groupBuffers[port].push(payload); if (config.forwardGroups && (collectGroups === true || needPortGroups) && !config.async) { return sendGroupToOuts(payload); } break; case 'closeBracket': _wp(scope).groupBuffers[port] = _wp(scope).groupBuffers[port].slice(0, _wp(scope).groupBuffers[port].length - 1); if (config.forwardGroups && (collectGroups === true || needPortGroups) && !config.async) { closeGroupOnOuts(payload); } if (_wp(scope).groupBuffers[port].length === 0) { if (config.inPorts.length === 1) { if (config.async || config.StreamSender) { if (config.ordered) { _wp(scope).outputQ.push(null); return processQueue(scope); } else { return _wp(scope).disconnectQ.push(true); } } else { return disconnectOuts(); } } else { foundGroup = false; key = _wp(scope).keyBuffers[port]; if (!(key in _wp(scope).disconnectData)) { _wp(scope).disconnectData[key] = []; } for (i = o = 0, ref5 = _wp(scope).disconnectData[key].length; 0 <= ref5 ? o < ref5 : o > ref5; i = 0 <= ref5 ? ++o : --o) { if (!(port in _wp(scope).disconnectData[key][i])) { foundGroup = true; _wp(scope).disconnectData[key][i][port] = true; if (Object.keys(_wp(scope).disconnectData[key][i]).length === config.inPorts.length) { _wp(scope).disconnectData[key].shift(); if (config.async || config.StreamSender) { if (config.ordered) { _wp(scope).outputQ.push(null); processQueue(scope); } else { _wp(scope).disconnectQ.push(true); } } else { disconnectOuts(); } if (_wp(scope).disconnectData[key].length === 0) { delete _wp(scope).disconnectData[key]; } } break; } } if (!foundGroup) { obj = {}; obj[port] = true; return _wp(scope).disconnectData[key].push(obj); } } } break; case 'data': if (config.inPorts.length === 1 && !inPort.isAddressable()) { data = payload; groups = _wp(scope).groupBuffers[port]; } else { key = ''; if (config.group && _wp(scope).groupBuffers[port].length > 0) { key = _wp(scope).groupBuffers[port].toString(); if (config.group instanceof RegExp) { reqId = null; ref6 = _wp(scope).groupBuffers[port]; for (q = 0, len5 = ref6.length; q < len5; q++) { grp = ref6[q]; if (config.group.test(grp)) { reqId = grp; break; } } key = reqId ? reqId : ''; } } else if (config.field && typeof payload === 'object' && config.field in payload) { key = payload[config.field]; } _wp(scope).keyBuffers[port] = key; if (!(key in _wp(scope).groupedData)) { _wp(scope).groupedData[key] = []; } if (!(key in _wp(scope).groupedGroups)) { _wp(scope).groupedGroups[key] = []; } foundGroup = false; requiredLength = config.inPorts.length; if (config.field) { ++requiredLength; } for (i = r = 0, ref7 = _wp(scope).groupedData[key].length; 0 <= ref7 ? r < ref7 : r > ref7; i = 0 <= ref7 ? ++r : --r) { if (!(port in _wp(scope).groupedData[key][i]) || (component.inPorts[port].isAddressable() && config.arrayPolicy["in"] === 'all' && !(index in _wp(scope).groupedData[key][i][port]))) { foundGroup = true; if (component.inPorts[port].isAddressable()) { if (!(port in _wp(scope).groupedData[key][i])) { _wp(scope).groupedData[key][i][port] = {}; } _wp(scope).groupedData[key][i][port][index] = payload; } else { _wp(scope).groupedData[key][i][port] = payload; } if (needPortGroups) { _wp(scope).groupedGroups[key][i] = utils.unique(slice.call(_wp(scope).groupedGroups[key][i]).concat(slice.call(_wp(scope).groupBuffers[port]))); } else if (collectGroups === true) { _wp(scope).groupedGroups[key][i][port] = _wp(scope).groupBuffers[port]; } if (component.inPorts[port].isAddressable() && config.arrayPolicy["in"] === 'all' && Object.keys(_wp(scope).groupedData[key][i][port]).length < component.inPorts[port].listAttached().length) { return; } groupLength = Object.keys(_wp(scope).groupedData[key][i]).length; if (groupLength === requiredLength) { data = (_wp(scope).groupedData[key].splice(i, 1))[0]; if (config.inPorts.length === 1 && inPort.isAddressable()) { data = data[port]; } groups = (_wp(scope).groupedGroups[key].splice(i, 1))[0]; if (collectGroups === true) { groups = utils.intersection.apply(null, utils.getValues(groups)); } if (_wp(scope).groupedData[key].length === 0) { delete _wp(scope).groupedData[key]; } if (_wp(scope).groupedGroups[key].length === 0) { delete _wp(scope).groupedGroups[key]; } if (config.group && key) { delete _wp(scope).gcTimestamps[key]; } break; } else { return; } } } if (!foundGroup) { obj = {}; if (config.field) { obj[config.field] = key; } if (component.inPorts[port].isAddressable()) { obj[port] = {}; obj[port][index] = payload; } else { obj[port] = payload; } if (config.inPorts.length === 1 && component.inPorts[port].isAddressable() && (config.arrayPolicy["in"] === 'any' || component.inPorts[port].listAttached().length === 1)) { data = obj[port]; groups = _wp(scope).groupBuffers[port]; } else { _wp(scope).groupedData[key].push(obj); if (needPortGroups) { _wp(scope).groupedGroups[key].push(_wp(scope).groupBuffers[port]); } else if (collectGroups === true) { tmp = {}; tmp[port] = _wp(scope).groupBuffers[port]; _wp(scope).groupedGroups[key].push(tmp); } else { _wp(scope).groupedGroups[key].push([]); } if (config.group && key) { _wp(scope).gcTimestamps[key] = new Date().getTime(); } return; } } } if (config.dropInput && _wp(scope).completeParams.length !== component.requiredParams.length) { return; } outs = {}; ref8 = config.outPorts; for (s = 0, len6 = ref8.length; s < len6; s++) { name = ref8[s]; wrp = new OutPortWrapper(component.outPorts[name], scope); if (config.async || config.sendStreams && config.sendStreams.indexOf(name) !== -1) { wrp; outs[name] = new StreamSender(wrp, config.ordered); } else { outs[name] = wrp; } } if (config.outPorts.length === 1) { outs = outs[config.outPorts[0]]; } if (!groups) { groups = []; } groups = (function() { var len7, results, t; results = []; for (t = 0, len7 = groups.length; t < len7; t++) { g = groups[t]; if (g !== null) { results.push(g); } } return results; })(); whenDoneGroups = groups.slice(0); whenDone = function(err) { var disconnect, len7, out, outputs, t; if (err) { component.error(err, whenDoneGroups, 'error', scope); } if (typeof component.fail === 'function' && component.hasErrors) { component.fail(null, [], scope); } outputs = outs; if (config.outPorts.length === 1) { outputs = {}; outputs[port] = outs; } disconnect = false; if (_wp(scope).disconnectQ.length > 0) { _wp(scope).disconnectQ.shift(); disconnect = true; } for (name in outputs) { out = outputs[name]; if (config.forwardGroups && config.async) { for (t = 0, len7 = whenDoneGroups.length; t < len7; t++) { i = whenDoneGroups[t]; out.endGroup(); } } if (disconnect) { out.disconnect(); } if (config.async || config.StreamSender) { out.done(); } } if (typeof component.afterProcess === 'function') { return component.afterProcess(scope, err || component.hasErrors, outs); } }; if (typeof component.beforeProcess === 'function') { component.beforeProcess(scope, outs); } if (config.forwardGroups && config.async) { if (config.outPorts.length === 1) { for (t = 0, len7 = groups.length; t < len7; t++) { g = groups[t]; outs.beginGroup(g); } } else { for (name in outs) { out = outs[name]; for (u = 0, len8 = groups.length; u < len8; u++) { g = groups[u]; out.beginGroup(g); } } } } exports.MultiError(component, config.name, config.error, groups, scope); debug("WirePattern Legacy API call with", data, groups, component.params, scope); if (config.async) { postpone = function() {}; resume = function() {}; postponedToQ = false; task = function() { setParamsScope(scope); return proc.call(component, data, groups, outs, whenDone, postpone, resume, scope); }; postpone = function(backToQueue) { if (backToQueue == null) { backToQueue = true; } postponedToQ = backToQueue; if (backToQueue) { return _wp(scope).taskQ.push(task); } }; resume = function() { if (postponedToQ) { return resumeTaskQ(); } else { return task(); } }; } else { task = function() { setParamsScope(scope); proc.call(component, data, groups, outs, null, null, null, scope); return whenDone(); }; } _wp(scope).taskQ.push(task); resumeTaskQ(scope); return gc(); } }; }; for (n = 0, len4 = ref4.length; n < len4; n++) { port = ref4[n]; fn1(port); } baseTearDown = component.tearDown; component.tearDown = function(callback) { component.requiredParams = []; component.defaultedParams = []; component.gcCounter = 0; component._wpData = {}; component.params = {}; return baseTearDown.call(component, callback); }; return component; }; exports.GroupedInput = exports.WirePattern; exports.CustomError = function(message, options) { var err; err = new Error(message); return exports.CustomizeError(err, options); }; exports.CustomizeError = function(err, options) { var key, val; for (key in options) { if (!hasProp.call(options, key)) continue; val = options[key]; err[key] = val; } return err; }; exports.MultiError = function(component, group, errorPort, forwardedGroups, scope) { var baseTearDown; if (group == null) { group = ''; } if (errorPort == null) { errorPort = 'error'; } if (forwardedGroups == null) { forwardedGroups = []; } if (scope == null) { scope = null; } platform.deprecated('noflo.helpers.MultiError is deprecated. Send errors to error port instead'); component.hasErrors = false; component.errors = []; if (component.name && !group) { group = component.name; } if (!group) { group = 'Component'; } component.error = function(e, groups) { if (groups == null) { groups = []; } component.errors.push({ err: e, groups: forwardedGroups.concat(groups) }); return component.hasErrors = true; }; component.fail = function(e, groups) { var error, grp, j, k, l, len, len1, len2, ref, ref1, ref2; if (e == null) { e = null; } if (groups == null) { groups = []; } if (e) { component.error(e, groups); } if (!component.hasErrors) { return; } if (!(errorPort in component.outPorts)) { return; } if (!component.outPorts[errorPort].isAttached()) { return; } if (group) { component.outPorts[errorPort].openBracket(group, { scope: scope }); } ref = component.errors; for (j = 0, len = ref.length; j < len; j++) { error = ref[j]; ref1 = error.groups; for (k = 0, len1 = ref1.length; k < len1; k++) { grp = ref1[k]; component.outPorts[errorPort].openBracket(grp, { scope: scope }); } component.outPorts[errorPort].data(error.err, { scope: scope }); ref2 = error.groups; for (l = 0, len2 = ref2.length; l < len2; l++) { grp = ref2[l]; component.outPorts[errorPort].closeBracket(grp, { scope: scope }); } } if (group) { component.outPorts[errorPort].closeBracket(group, { scope: scope }); } component.hasErrors = false; return component.errors = []; }; baseTearDown = component.tearDown; component.tearDown = function(callback) { component.hasErrors = false; component.errors = []; return baseTearDown.call(component, callback); }; return component; }; }).call(this);