noflo
Version:
Flow-Based Programming environment for JavaScript
89 lines (73 loc) • 2.76 kB
text/coffeescript
# NoFlo - Flow-Based Programming for JavaScript
# (c) 2014-2017 Flowhub UG
# NoFlo may be freely distributed under the MIT license
#
# Ports collection classes for NoFlo components
{EventEmitter} = require 'events'
InPort = require './InPort'
OutPort = require './OutPort'
class Ports extends EventEmitter
model: InPort
constructor: (ports) ->
@ports = {}
return unless ports
for name, options of ports
@add name, options
add: (name, options, process) ->
if name is 'add' or name is 'remove'
throw new Error 'Add and remove are restricted port names'
unless name.match /^[a-z0-9_\.\/]+$/
throw new Error "Port names can only contain lowercase alphanumeric characters and underscores. '#{name}' not allowed"
# Remove previous implementation
@remove name if @ports[name]
if typeof options is 'object' and options.canAttach
@ports[name] = options
else
@ports[name] = new @model options, process
@[name] = @ports[name]
@emit 'add', name
@ # chainable
remove: (name) ->
throw new Error "Port #{name} not defined" unless @ports[name]
delete @ports[name]
delete @[name]
@emit 'remove', name
@ # chainable
exports.InPorts = class InPorts extends Ports
on: (name, event, callback) ->
throw new Error "Port #{name} not available" unless @ports[name]
@ports[name].on event, callback
once: (name, event, callback) ->
throw new Error "Port #{name} not available" unless @ports[name]
@ports[name].once event, callback
exports.OutPorts = class OutPorts extends Ports
model: OutPort
connect: (name, socketId) ->
throw new Error "Port #{name} not available" unless @ports[name]
@ports[name].connect socketId
beginGroup: (name, group, socketId) ->
throw new Error "Port #{name} not available" unless @ports[name]
@ports[name].beginGroup group, socketId
send: (name, data, socketId) ->
throw new Error "Port #{name} not available" unless @ports[name]
@ports[name].send data, socketId
endGroup: (name, socketId) ->
throw new Error "Port #{name} not available" unless @ports[name]
@ports[name].endGroup socketId
disconnect: (name, socketId) ->
throw new Error "Port #{name} not available" unless @ports[name]
@ports[name].disconnect socketId
# Port name normalization:
# returns object containing keys name and index for ports names in
# format `portname` or `portname[index]`.
exports.normalizePortName = (name) ->
port =
name: name
# Regular port
return port if name.indexOf('[') is -1
# Addressable port with index
matched = name.match /(.*)\[([0-9]+)\]/
return name unless matched?.length
port.name = matched[1]
port.index = matched[2]
return port