# Compilar y ejecutar un componente nativo del servidor

> Compila el componente de HTML confiado Total.js, crea un ejemplo, valida los mensajes, reconfigura y libera sus recursos.

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

`NEWCOMPONENT(html, [callback])` compila un **componente de servidor**, distinto de un jComponent del navegador. Acepta texto fuente que contenga `<script total>` o `<script node>`; sin callback devuelve una promesa. Un nombre carga `components/<name>.html`; una URL descarga el código fuente. Esta receta usa solo código en línea de confianza, sin código remoto ni declaraciones de npm.

El componente exportado aporta metadatos, valores por defecto de `config` y `make(instance,config)`. `component.create(overrides)` crea una instancia con los valores por defecto clonados. Declara `inputs:[{id,schema}]` para la transformación de la entrada. `instance.input(inputId,data,callback)` entrega un mensaje cuyos `.data` y `.error` reflejan la validación del esquema. **El manejador se ejecuta igualmente con una entrada no válida**, así que comprueba `message.error` antes de procesar. `message.send(outputId,data)` emite una salida; `message.destroy()` la termina.

`instance.reconfigure(values)` actualiza su configuración y llama sus hooks de configuración/salvación. `instance.remove()` llama los hooks del ciclo de vida y elimina la instancia; `component.remove()` elimina todos los casos y invoca desinstalación.

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