Carga un módulo JavaScript desde una URL con IMPORT()
IMPORT(url, [callback]) descarga un archivo JavaScript, lo guarda en la carpeta tmp de la aplicación y devuelve lo que exporta el archivo (module.exports), como haría require(). Con un callback es callback(err, module, response); sin él, IMPORT() devuelve una promesa del módulo. La dirección se recuerda: llamar a IMPORT() de nuevo con la misma dirección no descarga el archivo otra vez, hace require del que está en tmp (y el archivo permanece allí entre reinicios, pero la memoria de «ya descargado» no: tras un reinicio se descarga de nuevo).
Esto ejecuta código que viene de la red con todos los derechos de tu aplicación. Importa solo desde una dirección que controles y a la que llegues con https, nunca una que te haya enviado un usuario o que cualquier otra persona pueda cambiar. El archivo es un módulo CommonJS. No se comprueba el estado de la respuesta: una dirección que responde 404 (o cualquier página de error) se guarda como si fuera el módulo, y require() lanza entonces un SyntaxError dentro de la descarga, de modo que en total5 0.0.19 el callback no se llama nunca y la promesa nunca se resuelve. Da siempre a IMPORT() un límite de tiempo propio, como hace la última ruta, y comprueba la dirección antes de depender de ella.
Aquí el archivo viene de una ruta de la misma aplicación, de modo que el ejemplo no necesita red. La ruta cuenta las descargas.
exports.install = function() {
ROUTE('GET /lib/tax/', lib);
ROUTE('POST /use/', use);
ROUTE('POST /use-twice/', use_twice);
ROUTE('POST /missing/', missing);
ROUTE('GET /downloads/', downloads);
};
let count = 0;
function lib($) {
count++;
$.plain('module.exports = { vat: function(price) { return Math.round(price * 121) / 100; } };');
}
function downloads($) {
$.json({ downloads: count });
}
function base() {
return 'http://127.0.0.1:' + CONF.$port;
}
async function use($) {
const tax = await IMPORT(base() + '/lib/tax/');
$.json({ price: tax.vat(100) });
}
function use_twice($) {
IMPORT(base() + '/lib/tax/', function(err, tax) {
$.json({ err: err ? err.toString() : null, price: tax ? tax.vat(200) : null });
});
}
async function missing($) {
// the address does not exist: the answer is the 404 page of the application
const winner = await Promise.race([
IMPORT(base() + '/lib/missing/').then(() => 'answered', () => 'answered'),
new Promise(resolve => setTimeout(() => resolve('no answer'), 1500))
]);
$.json({ result: winner });
}