ForgeTotal.js 5
pl

Total.js 5

Zbuduj przepływ komponentów przez Flow.load() i uruchom go przez exec()

Total.js 5 · total5@0.0.19 flowflowstreamcomponentsautomation Uruchomiono z Total.js 5

FlowStream to mały program złożony z komponentów (pudełek z wejściami i wyjściami) i połączeń między nimi. Total.js uruchamia go wewnątrz Twojej aplikacji: wiadomość wchodzi do jednego komponentu, komponent wysyła wyniki na swoje wyjścia, a połączenia niosą je do kolejnych komponentów. Ten sam schemat rysuje projektant Flow w Total.js; tu jest napisany ręcznie.

Flow.load(schema, [callback]) uruchamia FlowStream i daje callbackowi (err, instance). Schemat to obiekt:

  • id i name: id to klucz w Flow.instances (Flow.instances.demo); bez id tworzone jest losowe.
  • components: obiekt z kodem źródłowym każdego komponentu jako tekstem. Tekst to skrypt, <script total>...</script> (forma zapisywana przez projektanta).
  • design: instancje komponentów. Każda ma id, używany component, swoje config i connections, obiekt, którego kluczami są id wyjść, a wartościami listy { id, index }: instancja i id wejścia, które otrzymują to, co jest wysyłane na to wyjście.
  • variables: wartości, które komponenty mogą czytać.

Komponent to moduł: exports.id, exports.name, exports.inputs i exports.outputs (listy { id, name }), exports.config (wartości domyślne) oraz exports.make = function(instance, config). W make() komponent ustawia instance.message = function($) {}, która odbiera każdą wiadomość: $.data to dane, $.send(outputid, data) wysyła je na wyjście, a $.destroy() kończy wiadomość, która nie idzie dalej.

Aby użyć przepływu z kodu, instance.exec({ id, data, callback }) wysyła data do instancji id i wywołuje callback(err, message), gdy wiadomość się kończy; ostatnia wiadomość łańcucha to message (więc message.data to to, co otrzymał ostatni komponent). instance.reconfigure(id, config) zmienia konfigurację działającej instancji, a Flow.remove(id) zatrzymuje FlowStream i o nim zapomina. FlowStream to ten sam obiekt co Flow: dwie nazwy menedżera.

Komponent to kod uruchamiany ze wszystkimi uprawnieniami aplikacji (w tym samym wątku, chyba że schemat mówi worker). Nigdy nie ładuj schematu ani komponentu, który może napisać odwiedzający.

definitions/flow.js
const upper = `<script total>
exports.id = 'upper';
exports.name = 'Upper case';
exports.inputs = [{ id: 'input', name: 'Input' }];
exports.outputs = [{ id: 'output', name: 'Output' }];
exports.config = { prefix: '' };
exports.make = function(instance, config) {
	instance.message = function($) {
		$.send('output', config.prefix + String($.data).toUpperCase());
	};
};
</script>`;

const collect = `<script total>
exports.id = 'collect';
exports.name = 'Collect';
exports.inputs = [{ id: 'input', name: 'Input' }];
exports.make = function(instance) {
	instance.message = function($) {
		MAIN.collected.push($.data);
		$.destroy();
	};
};
</script>`;

MAIN.collected = [];

MAIN.flow = null;

Flow.load({
	id: 'demo',
	name: 'Demo',
	components: { upper: upper, collect: collect },
	design: {
		a: { id: 'a', component: 'upper', config: { prefix: '> ' }, connections: { output: [{ id: 'b', index: 'input' }] } },
		b: { id: 'b', component: 'collect', config: {}, connections: {} }
	},
	variables: {}
}, function(err, instance) {
	MAIN.flow = instance;
});
controllers/flow.js
exports.install = function() {
	ROUTE('GET /shout/', shout);
	ROUTE('POST /prefix/ @json', prefix);
	ROUTE('GET /collected/', collected);
	ROUTE('GET /info/', info);
	ROUTE('POST /stop/', stop);
};

function shout($) {
	if (!MAIN.flow)
		return $.invalid('The flow is not running');
	MAIN.flow.exec({ id: 'a', data: $.query.text, callback: (err, message) => $.json({ result: message ? message.data : null }) });
}

function prefix($) {
	MAIN.flow.reconfigure('a', { prefix: $.body.prefix });
	$.json({ ok: true });
}

function collected($) {
	$.json(MAIN.collected);
}

function info($) {
	$.json({ flows: Object.keys(Flow.instances), instances: Object.keys(MAIN.flow.flow.meta.flow), same: Flow === FlowStream });
}

function stop($) {
	Flow.remove('demo');
	MAIN.flow = null;
	$.json({ flows: Object.keys(Flow.instances) });
}