# Composer et exécuter un composant de serveur

> Compilez le composant HTML de confiance Total.js, créez un exemple, validez les messages, reconfigurez-le et libérez ses ressources.

Framework: total5
Product: Total.js 5 (total5@0.0.19)
Language: fr
Content-SHA256: 07b32e73bce365701fdb984035c1cd538a0111708c2bd06583d0af180a9554b4
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: total5-installed@total5@0.0.19
Review: not-recorded

`NEWCOMPONENT(html, [callback])` compile un **composant serveur**, distinct d'un jComponent de navigateur. Il accepte un texte source contenant `<script total>` ou `<script node>` ; sans callback il renvoie une promesse. Un nom charge `components/<name>.html` ; une URL télécharge le source. Cette recette n'utilise que du code en ligne de confiance, sans source distante ni déclarations npm.

Le composant exporté fournit des métadonnées, les valeurs par défaut de `config` et `make(instance,config)`. `component.create(overrides)` crée une instance avec des valeurs par défaut clonées. Déclarez `inputs:[{id,schema}]` pour la transformation de l'entrée. `instance.input(inputId,data,callback)` livre un message dont `.data` et `.error` reflètent la validation du schéma. **Le gestionnaire s'exécute quand même sur une entrée invalide**, vérifiez donc `message.error` avant de traiter. `message.send(outputId,data)` émet une sortie ; `message.destroy()` la termine.

`instance.reconfigure(values)` met à jour sa configuration et appelle ses boucles de configuration/sauvegarde. `instance.remove()` appelle les boucles du cycle de vie et supprime l'exemple; `component.remove()` supprime toutes les instances et invite à désinstaller.

```js controllers/components.js
exports.install = function() {
	ROUTE('GET /native-component/', exercise);
};
async function exercise($) {
	try {
		var source = '<script total>exports.id="native-echo";exports.name="Native echo";exports.config={prefix:"one:"};exports.inputs=[{id:"input",schema:"*name:String"}];exports.make=function(instance,config){instance.message=function($){if($.error){$.send("invalid",{invalid:true});$.destroy();return;}$.send("output",{text:config.prefix+$.data.name});$.destroy();};instance.destroy=function(){MAIN.componentClosed=true;};};</script>';
		var component = await NEWCOMPONENT(source);
		component.debugger = false;
		var instance = component.create();
		var first = await new Promise(resolve => instance.input('input',{name:'Ann'},message => resolve(message.data)));
		var invalid = await new Promise(resolve => instance.input('input',{},message => resolve(message.data)));
		instance.reconfigure({prefix:'two:'});
		var second = await new Promise(resolve => instance.input('input',{name:'Bob'},message => resolve(message.data)));
		instance.remove();
		var rejected = false;
		try { await NEWCOMPONENT('<body>no backend script</body>'); } catch (e) { rejected = true; }
		$.json({first:first,invalid:invalid,second:second,remaining:component.instances.length,closed:MAIN.componentClosed,rejected:rejected});
	} catch (e) { $.invalid(e); }
}
```
