UNPKG

fbp-protocol-client

Version:
154 lines (133 loc) 4.2 kB
isBrowser = () -> return !(typeof(process) != 'undefined' && process.execPath && process.execPath.indexOf('node') != -1) EventEmitter = if isBrowser() then require('emitter') else require('events').EventEmitter WebSocketServer = require('websocket').server http = require 'http' path = require 'path' normalizePorts = (ports) -> defaults = type: 'any' description: '' addressable: false required: false if not ports.length? ports = [ ports ] normalizePort = (port) -> normal = {} for k,v of normal normal[k] = v for k,v of port normal[k] = v return normal return (normalizePort p for p in ports) # TODO: implement array ports such that each connection gets its own index, # and that data send on a specific index is only sent to that connection class PseudoComponent extends EventEmitter constructor: () -> @_receiveFunc = null @ports = inPorts: {} outPorts: {} inports: (p) -> @ports.inPorts = normalizePorts p return this outports: (p) -> @ports.outPorts = normalizePorts p return this receive: (f) -> @receiveFunc = f return this send: (port, event, index, payload) -> @emit 'output', port, event, index, payload _receive: (port, event, index, payload) -> send = () => @send.apply this, arguments @receiveFunc port, event, index, payload, send class PseudoRuntime extends EventEmitter constructor: (httpServer) -> @connections = [] @wsServer = new WebSocketServer { httpServer: httpServer } @wsServer.on 'request', (request) => connection = request.accept 'noflo', request.origin @connections.push(connection); connection.on 'message', (message) => @handleMessage message, connection connection.on 'close', () => if @connections.indexOf(connection) == -1 return @connections.splice @connections.indexOf(connection), 1 handleMessage: (message, connection) -> return if not message.type == 'utf8' try msg = JSON.parse(message.utf8Data); catch e return if msg.protocol == 'runtime' && msg.command == 'getruntime' rt = type: 'remote-subgraph-test' version: '0.4' capabilities: ['protocol:runtime'] msg = { protocol: 'runtime', command: 'runtime', payload: rt } connection.sendUTF JSON.stringify msg @sendPorts() else if msg.protocol == 'runtime' && msg.command == 'packet' @receivePacket msg.payload, connection setComponent: (component) -> @component = component @component.on 'output', (port, event, index, payload) => packet = port: port event: event payload: payload index: index @sendPacket packet receivePacket: (p) -> @component._receive p.port, p.event, p.index, p.payload sendPacket: (p) -> msg = protocol: 'runtime' command: 'packet' payload: p @sendAll msg sendPorts: () -> msg = protocol: 'runtime' command: 'ports' payload: @component.ports @sendAll msg sendAll: (msg) -> msg = JSON.stringify msg for connection in @connections connection.sendUTF msg component = (name) -> c = new PseudoComponent name return c Echo = () -> c = component('Echo') .inports({ id: 'in', description: 'Data to echo' }) .outports({ id: 'out', description: 'Echoed data' }) .receive (port, index, event, payload, send) -> send 'out', index, event, payload createServer = (port, callback) -> server = new http.Server runtime = new PseudoRuntime server runtime.setComponent Echo() server.listen port, (err) -> return callback err, server createNoFloServer = (port, callback) -> runtime = require('noflo-runtime-websocket'); baseDir = path.join __dirname, '../' server = http.createServer () -> options = baseDir: baseDir captureOutput: false, catchExceptions: false rt = runtime server, options server.listen port, () -> return callback null, server module.exports = Echo: Echo Component: PseudoComponent Server: PseudoRuntime createServer: createServer createNoFloServer: createNoFloServer