ForgeTotal.js 5
sv

Total.js 5

Bygg ett flöde av komponenter med Flow.load() och kör det med exec()

Total.js 5 · total5@0.0.19 flowflowstreamcomponentsautomation Körd med Total.js 5

En FlowStream är ett litet program gjort av komponenter (lådor med ingångar och utgångar) och kopplingar mellan dem. Total.js kör det inuti din applikation: ett meddelande går in i en komponent, komponenten skickar resultat till sina utgångar och kopplingarna för dem till nästa komponenter. Samma schema är det som Flow-designern i Total.js ritar; här är det skrivet för hand.

Flow.load(schema, [callback]) startar en FlowStream och ger callbacken (err, instance). Schemat är ett objekt:

  • id och name: id är nyckeln i Flow.instances (Flow.instances.demo); utan id skapas ett slumpmässigt.
  • components: ett objekt med källkoden för varje komponent, som text. Texten är ett skript, <script total>...</script> (formen som designern sparar).
  • design: komponenternas instanser. Varje har ett id, component som den använder, sin config och connections, ett objekt vars nycklar är utgångs-id och vars värden är listor av { id, index }: instansen och ingångs-id som får det som skickas till den utgången.
  • variables: värden som komponenter kan läsa.

En komponent är en modul: exports.id, exports.name, exports.inputs och exports.outputs (listor av { id, name }), exports.config (standardvärdena) och exports.make = function(instance, config). I make() sätter komponenten instance.message = function($) {}, som tar emot varje meddelande: $.data är datan, $.send(outputid, data) skickar den till en utgång och $.destroy() avslutar ett meddelande som inte går längre.

För att använda flödet från din kod skickar instance.exec({ id, data, callback }) data till instansen id och anropar callback(err, message) när meddelandet tar slut; det sista meddelandet i kedjan är message (så message.data är det den sista komponenten fick). instance.reconfigure(id, config) ändrar konfigurationen för en körande instans och Flow.remove(id) stoppar FlowStream och glömmer den. FlowStream är samma objekt som Flow: två namn för hanteraren.

En komponent är kod som körs med alla applikationens rättigheter (i samma tråd om inte schemat säger worker). Ladda aldrig ett schema eller en komponent som en besökare kan skriva.

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) });
}