Skip to content

Instantly share code, notes, and snippets.

@petersirka
Forked from molda/VisualFlow.js
Created February 15, 2017 18:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save petersirka/e35be43cc732588a76618517670a8be7 to your computer and use it in GitHub Desktop.
Save petersirka/e35be43cc732588a76618517670a8be7 to your computer and use it in GitHub Desktop.
require('total.js').http('debug');
var util = require('util');
var EventEmitter = require('events');
// jen na test
var WSCONTROLLER = {
send: function(data){ console.log(data)}
}
// instance aktivních komponent
global.COMPONENTS = {};
function VisualFlow() {
var self = this;
// registrované komponenty z kterých se vytvářejí jednotlivé instance
self.components = {};
return self;
}
VisualFlow.prototype.registerComponent = function(name, fn) {
var self = this;
self.components[name] = fn;
return self;
};
VisualFlow.prototype.getComponent = function(name) {
return this.components[name];
};
// při změně v designéru zavoláme u všech komponent událost `close`, např. hhtpcomponent odstraní routu
VisualFlow.prototype.reset = function(name) {
Object.keys(COMPONENTS).forEach(function(comp) {
COMPONENTS[comp].emit('close');
});
COMPONENTS = {};
};
// při změně v designéru vytvoříme instance všech komponent
VisualFlow.prototype.instantiateComponents = function(components) {
var self = this;
// možná to bude chtít timeout????
self.reset();
if(!components || !components.length) return;
components.forEach(function(comp) {
// tohle by se mělo asi dělat už v designéru, name se zobrazí jako vlastní popis komponenty
if (comp.name === '')
comp.name = comp.component;
var c = self.getComponent(comp.component);
if(!c) return WSCONTROLLER.send({ target: 'debugwindow', type: 'error', msg: 'Unknown component:' + comp.component });
COMPONENTS[comp.id] = c.call(new Component(comp));
});
};
global.VISUALFLOW = global.VF = new VisualFlow();
//
function Component(config) {
var self = this;
U.extend(self, config);
}
util.inherits(Component, EventEmitter);
Component.prototype.send = function(msg) {
// pokud je msg Array a položky v connections taky tak se každá položka z msg posílá na jiný výstup
// connections by mělo vypadat nějak takhle
// [ ['id1', id2], ['id3'], ['id4']]
// a msg [{...}, {...}, {...}]
// takže např. msg[0] se pošle do komponenty id1 a id2
// msg[1] se pošle do komponenty id3
// msg[2] se pošle do komponenty id4
var isArray = msg instanceof Array;
var connections = this.connections || [];
if (connections.length) {
for (var i = 0; i < connections.length; i++) {
var w = connections[i];
if (w instanceof Array && isArray) {
for (var j = 0; j < w.length; i++) {
var m = msg[j];
//if (!(m instanceof Message)) m = new Message(m);
COMPONENTS[w[j]].emit('msg', m);
}
} else {
//if (!(msg instanceof Message)) msg = new Message(msg);
COMPONENTS[w].emit('msg', msg);
}
}
}
};
/*
pro odesílání statusu do designéru
např. u websocket(nebo mqtt) klienta, jestli je připojen nebo ne
*/
Component.prototype.status = function(status) {
// odešle status přes websocket do designéru
// např. -> status === {text: 'Connected', color: 'green'}
WSCONTROLLER.send({ target: this.id, type: 'status', msg: status });
return this;
};
/*
pro odesílání erroru do debug okna v designéru
*/
Component.prototype.error = function(error) {
// odešle error přes websocket do designéru
WSCONTROLLER.send({ target: 'debugwindow', type: 'error', msg: error });
return this;
};
/*
pro odesílání `msg` do debug okna v designéru
*/
Component.prototype.debug = function(msg) {
// odešle error přes websocket do designéru
WSCONTROLLER.send({ target: 'debugwindow', type: 'debug', msg: msg });
return this;
};
// function Message(m) {
// var msg = {};
// msg.id = UID();
// console.log('MSG', m);
// // if(typeof m === 'object')
// // U.extend(msg, m);
// // else
// msg.payload = m;
// return msg;
// }
// definice komponenty - hhtp route
function httpcomponent() {
var self = this;
if (!self.conf.url || self.conf.url === '')
return self.error('httpcomponent-error-no-url-provided');
var flags = [self.conf.method.toLowerCase()].concat(self.conf.flags || []);
F.route(self.conf.url, function() {
console.log('Incomming request');
self.send({ controller: this });
}, flags);
// při změně v designéru je potřeba odstranit routu
self.on('close', function() {
F.routes.web.forEach(function(route, i, routes) {
if (route.name === self.conf.url && route.method === self.conf.method)
routes.splice(i, 1);
});
Object.keys(F.temporary.other).forEach(function(key) {
if (key.startsWith('#' + self.conf.url) || key === self.conf.url) {
delete F.temporary.other[key];
}
});
});
return self;
}
VISUALFLOW.registerComponent('http', httpcomponent);
// definice komponenty - http response
function httpresponsecomponent() {
var self = this;
self.on('msg', function(msg) {
console.log('Responding to request');
msg.controller.json(msg.payload);
});
return self;
}
VISUALFLOW.registerComponent('httpresponse', httpresponsecomponent);
// definice komponenty - funkce
function functioncomponent(conf) {
var self = this;
self.on('msg', function(msg) {
console.log('Funkce');
msg = self.conf.fn(msg);
self.send(msg);
});
return self;
}
VISUALFLOW.registerComponent('function', functioncomponent);
// definice komponenty - debug
function debugcomponent(conf) {
var self = this;
self.on('msg', function(msg) {
console.log('DEBUG', msg.payload);
self.debug(msg);
});
return self;
}
VISUALFLOW.registerComponent('debug', debugcomponent);
// data z designéru - mohli by se ukládat do DB nebo jen do souboru components.json a načítali by se po (re)startu
VISUALFLOW.instantiateComponents([
{
component: 'http',
name: 'Incomming HTTP request',
id: '1',
connections: ['3', '4'], // id komponent kam se má dál poslat msg
conf: {
url: '/test', // config z designéru
method: 'GET' // config z designéru
}
},
{
component: 'debug',
name: 'Debug',
id: '4',
connections: []
},
{
component: 'httpresponse',
name: 'HTTP response',
id: '2',
connections: []
},
{
component: 'function',
name: 'Set "hello" to payload',
id: '3',
connections: ['2'],
conf: {
fn: function(msg) { msg.payload = 'Hello';
return msg; } // config z designéru - fn je funkce napsaná v designéru byl by to string, který by se musel `eval` ale na zkoušku to je takhle
}
}
]);
// http komponenta při requestu pošle controller dál jako msg.controller, připojený komponenty jsou `funkce` a `debug`
// z komponenty `funkce` jdou data dál do komponenty `httpresponse`
// funkce - httpresponse
// /
// http
// \
// debug
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment