Utilizamos cookies propias y de terceros. [Más información sobre las cookies].
Política de cookies
Proyecto AjpdSoft

· Inicio
· Buscar
· Contactar
· Cookies
· Descargas
· Foros
· Historia
· Nosotros
· Temas
· Top 10
· Trucos
· Tutoriales
· Wiki

JavaScript HTML: Copia ficheros asíncrona JavaScript, cómo compilar JavaScript a ejecutable
Java


Tutorial donde mostramos cómo crear un JavaScript que permite copiar una o varias carpetas de ficheros origen en uno o varios destinos de forma asíncrona, ejecutando varias copias concurrentemente. Explicamos también cómo usar Node.js para interpretar el JavaScript y cómo usar JXcore para generar un ejecutable .exe a partir del fichero JavaScript, permitiendo de esta forma ejecutar el JavaScript en cualquier PC sin necesidad de instalar software de terceros.



Funcionamiento y utilidad del código JavaScript

El código JavaScript que mostraremos a continuación usa un fichero con formato JSON donde se introducen las carpetas origen a copiar y los distintos destinos de copia. Un ejemplo del contenido de este fichero JSON que llamaremos "actualizar.json":

Funcionamiento y utilidad del código JavaScript

{
	"FACTURACION": {
		"origen": "\\\\servidor\\software\\Facturacion",
		"destinos": {
		  "Domingo Días Festivos": "\\\\PC44\\c$\\Users\\Domingo\\Facturacion",
		  "Juan Ramón Fuentes Limpias": "\\\\PC40\\c$\\Users\\Juan\\Facturacion",
		  "Servidor Facturación": "\\\\SRVFACTURACION\\Facturacion"
    }
  },
  "CONTABILIDAD": {
    "origen": "\\\\servidor\\software\\Contabilidad",
    "destinos": {
      "Fernando Alonso": "\\\\PC66\\c$\\Users\\Fernando\\Contabilidad",
      "Servidor Contabilidad": "\\\\SRVCONTA\\Contabilidad"
	   }
  }	
}

Básicamente se introduce un nombre para el grupo de copia, por ejemplo "FACTURACION" y a continuación se establece un origen y los destinos de copia. En el ejemplo anterior se copiarán los ficheros de la carpeta:

\\servidor\\software\\Facturacion

a los equipos:

\\PC44\c$\Users\Domingo\Facturacion
\
\PC40\c$\Users\Juan\Facturacion
\\SRVFACTURACION\Facturacion

Y también se copiará el contenido de la carpeta:

\\servidor\software\Contabilidad

a los equipos:

\\PC66\c$\Users\Fernando\Contabilidad
\\SRVCONTA\Contabilidad

Como vemos este ejemplo que mostraremos a continuación puede ser útil para actualizar aplicaciones de escritorio cliente/servidor pues permite especificar varios orígenes (varias carpetas) y varios destinos a los que copiar los orígenes. Además de que gracias al método asíncrono, el script copiará varios ficheros a la vez (hasta el límite establecido por concurrency).

Este script en JavaScript también realizará un ping inicial a cada destino de copia para comprobar si está disponible. Dicho ping también lo lanzará en modo asíncrono, lanzando varios ping a la vez, hasta el límite establecido por concurrency.

 

Código JavaScript para copiar carpetas a varios destinos de forma asíncrona

A continuación mostramos el código del script completo en JavaScript que permitirá leer el fichero JSON de configuración para copiar los ficheros de las carpetas origen a los destinos especificados. Además de realizar un ping a todos los equipos destino para verificar su disponibilidad:

Código JavaScript para copiar carpetas a varios destinos asíncrona

El siguiente código puede descargarse gratuitamente pulsando aquí:

var colors = require('colors');
var pad = require('pad');
var path = require('path');
var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs"));
var ping = require('ping-bluebird');
var Dict = require("collections/dict");
var mkdirp = require("mkdirp-then");
var config = require('./actualizar.json');

//Array donde se registran los ficheros en uso
var ficherosEnUso = []; 


//Diccionario [host, bool] que almacena para cada 
//servidor destino el estado de conexión
var hostsDestino = new Dict(); 

//Obtiene el agrumento que identifica la aplicación 
//a actualizar. Si no se especifica actualiza todos los
//que aparezcan en el fichero de configuración
var appParaActualizar = null;

if (process.argv.length > 0) 
{
	var arg0 = process.argv[0].toLowerCase();
    //Si se ejecuta con node.exe, el segundo 
	//parámetro es el nombre del .js y el tercero 
	//el nombre de la aplicación a actualizar
    if (arg0.indexOf("node") > -1 && 
	    process.argv.length > 2) appParaActualizar = process.argv[2];
    //Si se ejecuta utilizando el .js 
	   //empaquetado en un ejecutable con JX, el segundo parámetro 
	   //es el nombre de la aplicación a actualizar
    else if (arg0.indexOf("node") == -1 && 
	    process.argv.length > 1)  appParaActualizar = process.argv[1];
}

if (appParaActualizar != null) 
{
    console.log("Actualizando " + appParaActualizar);
} 
else 
{
    console.log("Actualizando todas las aplicaciones.");
}

//Comprueba la conectividad de los destinos con ping
Promise.map(Object.keys(config), function (app) 
{
 if (appParaActualizar == null || appParaActualizar == app) 
	{
     console.log("\nComprobando conectividad para %s:" . 
		    black.bgWhite, app);
     var destinos = [];
     var destinosApp = config[app]['destinos'];
     for (var key in destinosApp) 
		{
         var destino = destinosApp[key].toLowerCase();
         //Se comprueba la conectividad de los servidores de los destinos 
			//Los destinos locales no los comprueba (P.ej: c:)
         if (destino.indexOf(":") == -1) 
			{
             var host = destino.replace("\\\\", "").split('\\')[0];
             destinos.push(destino);
             if (!hostsDestino.has(host)) 
				{
                 hostsDestino.add(false, host);
             }
         }
     }
        //Realiza un Ping de forma asíncrona para cada servidor destino
        return Promise.map(hostsDestino.keys(), function (host) 
		{
            return ping(host, 
			{
                timeout: 1
            }).then(function (res) 
			{
                var respuesta = res.alive ? 
				    " conectado ".green : " desconectado ".red;
                console.log(pad(res.host, 15) + " " + respuesta);
                hostsDestino.set(res.host, res.alive);
            }).reflect();
        });
    }
}, {concurrency: 20})
    .then(function (object) 
	{
        //Copia a los destinos que tienen conectividad
        return Promise.map(Object.keys(config), function (app) 
		{
            if (appParaActualizar == null || appParaActualizar == app) 
			{
                console.log("\nIniciando la copia para %s:".black.bgWhite, app);
                var destinos = []; //Array de rutas de los destinos
                var destinosApp = config[app]['destinos'];
                for (var key in destinosApp) 
				{
                    var destino = destinosApp[key].toLowerCase();
                    //Si es una copia local añade el destino. P.e: c:\...
                    if (destino.indexOf(':') > -1) 
					{
                        destinos.push(destino);
                 } 
					else 
					{
                        //Añade la ruta del destino si hay conectividad 
						//con el servidor de destino
                        var host = destino.replace("\\\\", "").split('\\')[0];

                     if (hostsDestino.get(host, false)) 
						{
                            destinos.push(destino);
                     }
                    }
                }
                if (destinos.length > 0) 
				{
                    // Lanza el proceso de copia de la applicación a los destinos
                    return copiarDirectorio(config[app].origen, 
					    config[app].origen, destinos);
              }
            }
        }, {
            concurrency: 100
        });
    }).then(function () 
	{
        console.log("\nResultado:".black.bgWhite);

        //Imprime la información sobre la conectividad 
		//de los destinos de las copias en pantalla
        if (hostsDestino.values().some(function (conectado, index) 
		{
            return conectado;
        })) 
		{
            console.log("\nDestinos con conectividad:".bold);
            hostsDestino.forEach(function (conectado, servidor) 
			{
                if (conectado)
                    console.log(pad(" ", 4) + "%s", servidor);
            });
        }
        if (hostsDestino.values().some(function (conectado, index) 
		{
            return !conectado;
        })) 
		{
            console.error("\nDestinos sin conectividad:".bold);
            hostsDestino.forEach(function (conectado, servidor) 
			{
                if (!conectado)
                    console.error(pad(" ", 4) + "%s", servidor);
            });
        }

        //Muestra los ficheros que no se han copiado debido 
		//a que estaban en uso
        if (ficherosEnUso.length > 0) 
		{
            console.error("\nFicheros en uso:".bold);
            ficherosEnUso.forEach(function (ruta) 
			{
                console.error(pad(" ", 4) + "%s", ruta);
            });
        }
    });

// Funciones auxiliares
/**
 * Función que lee el contenido de un directorio origen 
 * recursivamente y lo copia en uno o varios destinos, 
 * todo de forma asíncrona.
 * @param directorio Directorio actual cuyos ficheros se 
 * copian a los destinos. Inicialemnte es el mismo que 
 * el origen. Conforme va recorriendo recursivamente 
 * los subdirectorios este parámetro cambia indicando 
 * el directorio actual que esta copiando.
 * @param origen Directorio raíz de la aplicación que 
 * se copia. No varía en cada iteración recursiva.
 * @param destinos Array de rutas de las carpetas de 
 * destino. No varía en cada iteración recursiva.
 * @returns {Function}
 */
function copiarDirectorio(directorio, origen, destinos) 
{
    //Lee el contenido del directorio. Por cada fichero 
	//encontrado ejecuta lo siguiente
    return fs.readdirAsync(directorio).map(function (fichero) 
	{
        var ruta = path.join(directorio, fichero);
        //Obtiene la información del fichero/directorio
        return fs.statAsync(ruta).then(function (informaciónFichero) 
		{
            //Si es directorio lo copia recursivamente
            if (informaciónFichero.isDirectory())
                return copiarDirectorio(ruta, origen, destinos);
            else 
			{
                //Si es fichero lo carga en memoria
                console.log(pad("Leyendo", 15).yellow + 
				    ruta.replace(origen, '').gray);
                return fs.readFileAsync(ruta).catch(function ignore(err) 
				{
                })
                    .then(function (contenido) 
					{
                        //Escribe de forma asíncrona el fichero actual 
						//en cada destino
                        return Promise.map(destinos, 
						    function (prefijoDestino, index, length) 
							{
                            //Anida la ruta relativa del fichero que está
							//copiando a la ruta absoluta de la raíz del destino
                            var destino = path.join(prefijoDestino, 
							    ruta.replace(origen, ''));
                            //Crea el directorio de destino si no existe
                            return mkdirp(path.dirname(destino)).then(function () 
							{
                                console.log(pad("Escribiendo", 15).green + destino);
                                //Escribe el fichero cargado en memoria en el destino
                                return fs.writeFileAsync(destino, contenido).then(
                                    function onFulfilled(value) 
									{
                                        return {
                                            state: 'fulfilled',
                                            value: value
                                        };
                                    },
                                    function onRejected(reason) 
									{
                                        if (reason.code == "EBUSY") 
										{
                                            ficherosEnUso.push(reason.path);
                                        } 
										else 
										{
                                            console.error("%s", reason.message);
                                        }
                                        //Ignora el rechazo devolviendo fulfilled
                                        return {
                                            state: 'fulfilled',
                                            value: false
                                        };
                                    });
                            }, 
							function onRejected(reason) 
							{
                                console.error("%s no ha podido ser creada", reason.path);
                                //Ignora el rechazo devolviendo fulfilled
                                return {
                                    state: 'fulfilled',
                                    value: false
                                };
                            });
                        });
                    }, 
					function onRejected(reason) 
					{
                        console.error("%s no ha podido ser leido." + reason.path);
                        //Ignora el rechazo devolviendo fulfilled
                        return {
                            state: 'fulfilled',
                            value: false
                        };
                    });
            }
        });
    }, {concurrency: 20});
}

process.on('uncaughtException', function (err) 
{
    console.error((new Date).toUTCString() + 
	    ' Excepción no controlada: '.red, err.message);
});

process.on('unhandledRejection', function (reason, p) 
{
    if (reason.code == "EBUSY") 
	{
        console.error(reason.path + " está en uso.");
    } 
	else 
	{
        console.error("Error: " + reason.message);
    }
});

Será suficiente con copiar el código anterior en un fichero de texto plano sin formato y llamarlo, por ejemplo, actualizar.js.

 

Cómo interpretar y ejecutar JavaScript mediante Node.js

Una vez creado el fichero JavaScript como hemos indicando anteriormente, ahora tendremos que ejecutarlo para que realice su función. A continuación explicamos los pasos a seguir para interpretar o ejecutar un fichero JavaScript desde fuera de un navegador, desde nuestro equipo de escritorio, como si se tratara de una aplicación o comando Windows. Para ello usaremos la herramienta Node.js que es de libre distribución y sirve, entre otras cosas, para interpretar código JavaScript desde fuera del navegador.

Qué es Node.js

Antes de continuar con nuestro script vamos a aportar un poco de teoría sobre Node.js, que nos ayudará a entender para qué sirve y cuáles son sus características. Node.js es un entorno en tiempo de ejecución multiplataforma, de código abierto, para la capa del servidor (pero no limitándose a ello) basado en el lenguaje de programación ECMAScript, asíncrono, con I/O de datos en una arquitectura orientada a eventos y basado en el motor V8 de Google. Fue creado con el enfoque de ser útil en la creación de programas de red altamente escalables, como por ejemplo, servidores web.

Node.js es similar en su propósito a Twisted o Tornado de Python, Perl Object Environment de Perl, React de PHP, libevent o libev de C, EventMachine de Ruby, vibe.d de D y de Java existe Apache MINA, Netty, Akka, Vert.x, Grizzly o Xsocket. Al contrario que la mayoría del código JavaScript, no se ejecuta en un navegador, sino en el servidor. Node.js implementa algunas especificaciones de CommonJS. Node.js incluye un entorno REPL para depuración interactiva.

Algunos aspectos técnicos interesantes de Node.js:

  • Paralelismo: Node.js funciona con un modelo de evaluación de un único hilo de ejecución, usando entradas y salidas asíncronas las cuales pueden ejecutarse concurrentemente en un número de hasta cientos de miles sin incurrir en costos asociados al cambio de contexto. Este diseño de compartir un único hilo de ejecución entre todas las solicitudes atiende a necesidades de aplicaciones altamente concurrentes, en el que toda operación que realice entradas y salidas debe tener una función callback. Un inconveniente de este enfoque de único hilo de ejecución es que Node.js requiere de módulos adicionales como cluster para escalar la aplicación con el número de núcleos de procesamiento de la máquina en la que se ejecuta.
  • V8: es el ambiente de ejecución para JavaScript creado para Google Chrome. Es software libre desde 2008, está escrito en C++ y compila el código fuente JavaScript en código de máquina en lugar de interpretarlo en tiempo real. Node.js contiene libuv para manejar eventos asíncronos. Libuv es una capa de abstracción de funcionalidades de redes y sistemas de archivo en sistemas Windows y sistemas basados en POSIX como Linux, Mac OS X y Unix. El cuerpo de operaciones de base de Node.js está escrito en JavaScript con métodos de soporte escritos en C++.
  • Módulos: Node.js incorpora varios "módulos básicos" compilados en el propio binario, como por ejemplo el módulo de red, que proporciona una capa para programación de red asíncrona y otros módulos fundamentales, como por ejemplo Path, FileSystem, Buffer, Timers y el de propósito más general Stream. Es posible utilizar módulos desarrollados por terceros, ya sea como archivos ".node" precompilados, o como archivos en JavaScript plano. Los módulos JavaScript se implementan siguiendo la especificación CommonJS para módulos, utilizando una variable de exportación para dar a estos scripts acceso a funciones y variables implementadas por los módulos. Los módulos de terceros pueden extender Node.js o añadir un nivel de abstracción, implementando varias utilidades middleware para utilizar en aplicaciones web, como por ejemplo los frameworks connect y express. Pese a que los módulos pueden instalarse como archivos simples, normalmente se instalan utilizando el Node Package Manager (npm) que nos facilitará la compilación, instalación y actualización de módulos así como la gestión de las dependencias. Además, los módulos que no se instalen en el directorio por defecto de módulos de Node necesitarán la utilización de una ruta relativa para poder encontrarlos.
  • Desarrollo homogéneo entre cliente y servidor. Node.js puede ser combinado con una base de datos documental (por ejemplo, MongoDB o CouchDB) y JSON lo que permite desarrollar en un ambiente de desarrollo JavaScript unificado. Con la adaptación de los patrones para desarrollo del lado del servidor tales como MVC y sus variantes MVP, MVVM, etc. Node.js facilita la reutilización de código del mismo modelo de interfaz entre el lado del cliente y el lado del servidor.
  • Lazo de eventos. Node.js se registra con el sistema operativo y cada vez que un cliente establece una conexión se ejecuta un callback. Dentro del ambiente de ejecución de Node.js, cada conexión recibe una pequeña asignación de espacio de memoria dinámico, sin tener que generar un hilo de trabajo. A diferencia de otros servidores dirigidos por eventos, el lazo de manejo de eventos de Node.js no es llamado explícitamente sino que se activa al final de cada ejecución de una función de callback. El lazo de manejo de eventos se termina cuando ya no quedan eventos por atender.

 

Instalar Node.js en un equipo Windows

En primer lugar descargaremos el instalador apropiado para nuestro sistema operativo de la web oficial de Node.js, para ello accederemos a la URL:

https://nodejs.org/en

Y descargaremos la versión estable, en nuestro caso "v5.0.0 Stable":

Instalar Node.js en un equipo Windows

Guardaremos el fichero node-v5.0.0-x64.msi:

Instalar Node.js en un equipo Windows

Ejecutaremos el fichero descaragado:

Instalar Node.js en un equipo Windows

Es posible que nos muestre un mensaje de advertencia de seguridad, pulsaremos "Ejecutar":

Instalar Node.js en un equipo Windows

Se iniciará el asistente de instalación de Node.js, pulsaremos "Next":

Instalar Node.js en un equipo Windows

Leeremos los términos de licencia, si estamos de acuerdo marcaremos "I accept the terms in the Licence Agreement" y pulsaremos "Next":

Instalar Node.js en un equipo Windows

Pulsaremos "Next":

Instalar Node.js en un equipo Windows

Se instalarán las siguientes herramientas:

  • Node.js runtime.
  • npm package manager.
  • Online documentation shorcuts.
  • Se añadirá a la variable PATH del sistema la ruta de instalación para ejecutar estas herramientas desde cualquier carpeta.

Pulsaremos "Install" para iniciar la instalación de Node.js:

Instalar Node.js en un equipo Windows

El asistente nos indicará que Node.js ha sido instalado correctamente en nuestro equipo:

Instalar Node.js en un equipo Windows

 

Crear fichero JSON package.json de configuración del paquete con Node.js

Una vez instalado Node.js en nuestro equipo podremos usar sus comandos para interpretar y ejecutar código JavaScript. Antes de ejecutar nuestro script de ejemplo JavaScript actualizar.js deberemos obtener todas las librerías que hayamos necesitado (incluidas en la cláusula require) y crear el fichero package.json, necesario para la ejecución de un fichero JavaScript con Node.js. Para crear el fichero package.json usaremos Node.js, abriremos una ventana de MS-DOS (línea de comandos de Windows), para ello pulsaremos en el botón Inicio y escribiremos "cmd", nos mostrará la herramienta de shell, pulsaremos con el botón derecho del ratón sobre ella y seleccionaremos "Ejecutar como administrador":

Crear fichero JSON package.json de configuración del paquete con Node.js

Ahora nos posicionaremos en la carpeta donde tengamos el fichero actualizar.js, en nuestro caso ejecutaremos los siguientes comandos MS-DOS:

cd..

cd..

cd AjpdSoft_JavaScript

Una vez posicionados en la carpeta con el fichero actualizar.js ejecutaremos el siguiente comando usando el paquete "npm":

npm init

Crear fichero JSON package.json de configuración del paquete con Node.js

Nos pedirá una serie de datos (podemos dejar todos los de defecto pulsando INTRO), nos pedirá el nombre de la aplicación (name), la versión (version), la descripción (description), punto de entrada (entry point) que pode defecto suele ser el nombre del fichero .js, palabras clave, autor, licencia, etc. Introduciremos cada dato y pulsaremos INTRO. Al finalizar la captura de datos nos preguntará si es correcto (Is this ok?), pulsaremos INTRO:

Crear fichero JSON package.json de configuración del paquete con Node.js

El comando anterior nos habrá creado el fichero package.json:

Crear fichero JSON package.json de configuración del paquete con Node.js

Pulsa aquí para ver un ejemplo de contenido de fichero package.json creado por la herramienta npm.

 

Descarga de las dependencias, librerías adicionales con Node.js

Si nuestro script JavaScript incluye dependencias (require) deberemos especificarlas en el fichero package.json y descargar los ficheros de cada dependencia. Para hace esto de forma automática podemos usar Node.js. En primer lugar consultaremos las dependencias que hemos usado en nuestro .js, en nuestro caso:

var colors = require('colors');
var pad = require('pad');
var path = require('path');
var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs"));
var ping = require('ping-bluebird');
var Dict = require("collections/dict");
var mkdirp = require("mkdirp-then");
var config = require('./actualizar.json');

y ejecutaremos el siguiente comando (siempre en la carpeta donde se encuenta el fichero JavaScript):

npm install colors pad path bluebird fs ping-bluebird collections mkdirp-then --save

Descarga de las dependencias, librerías adicionales con Node.js

Si todo es correcto Node.js con el paquete npm descargará en una subcarpeta de nuestro proyecto todos los ficheros necesarios de cada librería o paquete usado por nuestro fichero JavaScript, mostrando el siguiente resultado:

Descarga de las dependencias, librerías adicionales con Node.js

Pulsar aquí para ver la salida del comando npm install colors pad path bluebird fs ping-bluebird collections mkdirp-then --save.

Además, el comando anterior habrá editado el fichero package.json y habrá añadido las dependencias correspondientes. También habrá creado la subcarpeta "node_modules" con los ficheros de cada librería referenciada.

Podemos consultar el contenido del fichero package.json que puede abrirse con cualquier editor de texto plano sin formato:

Descarga de las dependencias, librerías adicionales con Node.js

Vemos que ha añadido "dependencies" y todas las librerías de los requiere del fichero JavaScript que hayamos indicado que se descarguen con el comando anterior:

Descarga de las dependencias, librerías adicionales con Node.js

El contenido de la subcarpeta "node_modules":

Descarga de las dependencias, librerías adicionales con Node.js

 

Ejecutar JavaScript con Node.js

Una vez que hemos añadido las dependencias al fichero package.json y hemos descargado los ficheros .js necesarios para estas dependencias, como hemos indicado en pasos anteriores, podremos ejecutar nuestro script. Para ello usaremos el siguiente comando (siempre en el directorio donde tenemos el script .js, el fichero package.json y los ficheros de dependencias):

node actualizar.js

Nota importante: nuestro script no funcionará si no encuentra el fichero "actualizar.json" donde, como hemos explicado aquí, se especifican los orígenes y destinos de copia de cada carpeta y sus ficheros.

Un ejemplo de salida de la ejecución de nuestro script actualizar.js:

Ejecutar JavaScript con Node.js

Como vemos el script primero comprueba la disponibilidad de los equipos destino, haciendo un ping. Si no responde no intenta la copia, si responde intenta realizar la copia. Al finalizar el script muestra el resultado de la copia, los destinos que han tenido conectividad y los que no.

 

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

El proceso anterior puede ser un poco tedioso si queremos ejecutar nuestro JavaScript en otros equipos, tendríamos que instalar Node.js y usar el comando "node xxx.js" para ejecutar el script. Para evitar esto, existe una herramienta gratuita llamada JXcore que permite encapsular todo lo necesario en un ejecutable para que nuestro script puede ejecutarse en cualquier PC sin necesidad de instalar software adicional.

A continuación vamos a explicar cómo generar un fichero ejecutable a partir de un fichero JavaScript. Para ello necesitaremos tener instalado en nuestro equipo Node.js, como indicamos aquí y también necesitaremos JXcore. JXcore es una herramienta que a partir de Node.js permite generar un ejecutable embebido con todo lo necesario para que nuestra aplicación JavaScript pueda funcionar en cualquier PC sin necesidad de instalar Node.js ni ningún otro software. Con JXcore generaremos un .exe (ejecutable) a partir del .js (JavaScript).

Para descargar e instalar JXcore accederemos a la URL:

http://jxcore.com/downloads

En nuestro caso pulsaremos "Download" en Windows Setup (32/64/SM/V8):

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

Guardaremos el archivo jx_winsetup.zip:

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

Lo descomprimiremos:

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

Ejecutaremos el fichero JXcore_setup.exe:

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

Se iniciará el asistente de instalación de JXcore, pulsaremos "Next":

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

Leeremos los términos de liciencia, si estamos de acuerdo marcaremos "I accept the agreement" y pulsaremos "Next":

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

Elegiremos la carpeta de instalación y pulsaremos "Next":

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

A continuación podremos elegir el ambiente de ejecución a instalar, en nuestro caso "V8 x64":

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

Elegiremos el nombre para la carpeta que se creará en la barra de tareas y pulsaremos "Next":

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

Es recomendable marcar la opción "Add application directory to environment PATH variable" para poder ejecutar el comando "jx" desde cualquier carpeta del equipo:

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

Comprobaremos las opciones elegidas, si son correctas puldaremos "Install" para instalar definitivamente JXcore:

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

Tras la instalación el asistente nos indicará que JXcore ha sido instalado correctamente. Pulsaremos "Finish":

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

Una vez instalado JXcore ya podremos usar el comando "jx" para generar el ejecutable a partir del fichero JavaScritp y sus dependencias. Para ello abriremos una ventana de MS-DOS (como hemos explicado anteriormente) y accederemos a la carpeta donde tengamos el fichero de scritp JavaScript, en nuestro caso:

C:/AjpdSoft_JavaScript

Una vez en la carpeta ejecutaremos el siguiente comando:

jx package actualizar.js -native -add actualizar.js,node_modules

(teniendo en cuenta que en nuestro caso el fichero de script JavaScript se llama actualizar.js)

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

Si todo es correcto y se ha generado el fichero ejecutable .exe a partir del .js nos mostrará el mensaje [OK] compiled file is ready (C:\AjpdSoft_JavaScript\actualizar.exe).

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

Y podremos comprobar que en la carpeta del script JavaScript se ha generado el fichero actualizar.exe que ahora podrá funcionar en cualquier equipo sin necesidad de instalar Node.js ni de descargar las librerías adicionales pues van embebida en el ejecutable:

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

Y como decimos, podremos ejecutar el fichero actualizar.exe que se comportará como el fichero actualizar.js y sus librerías dependientes. En el caso de nuestro script de ejemplo podremos pasarle como parámetro al ejecutable el nombre del grupo de origen y destinos a utilizar que viene dado en el fichero actualizar.json:

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

El contenido del fichero actaulizar.json de ejemplo del que ha leído la información el fichero actualizar.exe:

Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js

 

Anexo

  • Salida comando npm init:
C:/AjpdSoft_JavaScript>npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help json` for definitive documentation on these fields
and exactly what they do.
Use `npm install  --save` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
name: (AjpdSoft_JavaScript) AjpdSoft_Actualizar
Sorry, name can no longer contain capital letters.
name: (AjpdSoft_JavaScript) ajpdsoft_actualizar
version: (1.0.0) 1.0
Invalid version: "1.0"
version: (1.0.0) 1.0.0
description: Actualizar ficheros
entry point: (actualizar.js)
test command:
git repository:
keywords: actualizar copy ficheros copia
author: AjpdSoft
license: (ISC)
About to write to C:/AjpdSoft_JavaScript/package.json:

{
  "name": "ajpdsoft_actualizar",
  "version": "1.0.0",
  "description": "Actualizar ficheros",
  "main": "actualizar.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "actualizar",
    "copy",
    "ficheros",
    "copia"
  ],
  "author": "AjpdSoft",
  "license": "ISC"
}
Is this ok? (yes)
  

  • Fichero package.json creado por la herramienta npm:

    {
    "name": "ajpdsoft_actualizar",
    "version": "1.0.0",
    "description": "Actualizar ficheros",
    "main": "actualizar.js",
    "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
    },
    "keywords": [
    "actualizar",
    "copy",
    "ficheros",
    "copia"
    ],
    "author": "AjpdSoft",
    "license": "ISC",
    "dependencies": {
    "bluebird": "^3.0.5",
    "collections": "^1.2.4",
    "colors": "^1.1.2",
    "fs": "0.0.2",
    "mkdirp-then": "^1.1.0",
    "pad": "^1.0.0",
    "path": "^0.12.7",
    "ping-bluebird": "0.0.2"
    }
    }
  • Salida comando npm install colors pad path bluebird fs ping-bluebird collections mkdirp-then --save:


    ajpdsoft_actualizar@1.0.0 C:/AjpdSoft_JavaScript
    ??? bluebird@3.0.5
    ??? collections@1.2.4
    ? ??? weak-map@1.0.5
    ??? colors@1.1.2
    ??? fs@0.0.2
    ??? mkdirp-then@1.1.0
    ? ??? mkdirp@0.5.1
    ? ? ??? minimist@0.0.8
    ? ??? native-or-bluebird@1.2.0
    ??? pad@1.0.0
    ??? path@0.12.7
    ? ??? process@0.11.2
    ? ??? util@0.10.3
    ? ??? inherits@2.0.1
    ??? ping-bluebird@0.0.2
    ??? bluebird@2.10.2
    npm WARN EPACKAGEJSON ajpdsoft_actualizar@1.0.0 No repository field.

  • Resultado ejecución comando jx package actualizar.js -native -add actualizar.js,node_modules
    Processing the folder..
    JXP project file (actualizar.jxp) is ready.
    preparing the JX file..
    Compiling actualizar 1.0
    adding script actualizar.js
    adding script node_modules\bluebird\js\browser\bluebird.js
    adding script node_modules\bluebird\js\browser\bluebird.min.js
    adding script node_modules\bluebird\js\release\any.js
    adding script node_modules\bluebird\js\release\assert.js
    adding script node_modules\bluebird\js\release\async.js
    adding script node_modules\bluebird\js\release\bind.js
    adding script node_modules\bluebird\js\release\bluebird.js
    adding script node_modules\bluebird\js\release\call_get.js
    adding script node_modules\bluebird\js\release\cancel.js
    adding script node_modules\bluebird\js\release\catch_filter.js
    adding script node_modules\bluebird\js\release\context.js
    adding script node_modules\bluebird\js\release\debuggability.js
    adding script ....node_modules\bluebird\js\release\direct_resolve.js
    adding script node_modules\bluebird\js\release\each.js
    adding script node_modules\bluebird\js\release\errors.js
    adding script node_modules\bluebird\js\release\es5.js
    adding script node_modules\bluebird\js\release\filter.js
    adding script node_modules\bluebird\js\release\finally.js
    adding script node_modules\bluebird\js\release\generators.js
    adding script node_modules\bluebird\js\release\join.js
    adding script node_modules\bluebird\js\release\map.js
    adding script node_modules\bluebird\js\release\method.js
    adding script node_modules\bluebird\js\release\nodeback.js
    adding script node_modules\bluebird\js\release\nodeify.js
    adding script node_modules\bluebird\js\release\promise.js
    adding script node_modules\bluebird\js\release\promise_array.js
    adding script node_modules\bluebird\js\release\promisify.js
    adding script node_modules\bluebird\js\release\props.js
    adding script node_modules\bluebird\js\release\queue.js
    adding script node_modules\bluebird\js\release\race.js
    adding script node_modules\bluebird\js\release\reduce.js
    adding script node_modules\bluebird\js\release\schedule.js
    adding script node_modules\bluebird\js\release\settle.js
    adding script node_modules\bluebird\js\release\some.js
    adding script ....ules\bluebird\js\release\synchronous_inspection.js
    adding script node_modules\bluebird\js\release\thenables.js
    adding script node_modules\bluebird\js\release\timers.js
    adding script node_modules\bluebird\js\release\using.js
    adding script node_modules\bluebird\js\release\util.js
    adding script node_modules\bluebird\package.json
    adding script node_modules\collections\collections.js
    adding script node_modules\collections\deque.js
    adding script node_modules\collections\dict.js
    adding script node_modules\collections\fast-map.js
    adding script node_modules\collections\fast-set.js
    adding script node_modules\collections\generic-collection.js
    adding script node_modules\collections\generic-map.js
    adding script node_modules\collections\generic-order.js
    adding script node_modules\collections\generic-set.js
    adding script node_modules\collections\heap.js
    adding script node_modules\collections\iterator.js
    adding script node_modules\collections\lfu-map.js
    adding script node_modules\collections\lfu-set.js
    adding script node_modules\collections\list.js
    adding script node_modules\collections\listen\array-changes.js
    adding script node_modules\collections\listen\map-changes.js
    adding script ....ode_modules\collections\listen\property-changes.js
    adding script node_modules\collections\listen\range-changes.js
    adding script node_modules\collections\lru-map.js
    adding script node_modules\collections\lru-set.js
    adding script node_modules\collections\map.js
    adding script node_modules\collections\multi-map.js
    adding script node_modules\collections\package.json
    adding script node_modules\collections\set.js
    adding script node_modules\collections\shim-array.js
    adding script node_modules\collections\shim-function.js
    adding script node_modules\collections\shim-object.js
    adding script node_modules\collections\shim-regexp.js
    adding script node_modules\collections\shim.js
    adding script node_modules\collections\sorted-array-map.js
    adding script node_modules\collections\sorted-array-set.js
    adding script node_modules\collections\sorted-array.js
    adding script node_modules\collections\sorted-map.js
    adding script node_modules\collections\sorted-set.js
    adding script node_modules\collections\tree-log.js
    adding script node_modules\collections\weak-map.js
    adding script node_modules\colors\examples\normal-usage.js
    adding script node_modules\colors\examples\safe-string.js
    adding script node_modules\colors\lib\colors.js
    adding script node_modules\colors\lib\custom\trap.js
    adding script node_modules\colors\lib\custom\zalgo.js
    adding script node_modules\colors\lib\extendStringPrototype.js
    adding script node_modules\colors\lib\index.js
    adding script node_modules\colors\lib\maps\america.js
    adding script node_modules\colors\lib\maps\rainbow.js
    adding script node_modules\colors\lib\maps\random.js
    adding script node_modules\colors\lib\maps\zebra.js
    adding script node_modules\colors\lib\styles.js
    adding script node_modules\colors\lib\system\supports-colors.js
    adding script node_modules\colors\package.json
    adding script node_modules\colors\safe.js
    adding script node_modules\colors\themes\generic-logging.js
    adding script node_modules\fs\index.js
    adding script node_modules\fs\package.json
    adding script node_modules\inherits\inherits.js
    adding script node_modules\inherits\inherits_browser.js
    adding script node_modules\inherits\package.json
    adding script node_modules\inherits\test.js
    adding script node_modules\minimist\example\parse.js
    adding script node_modules\minimist\index.js
    adding script node_modules\minimist\package.json
    adding script node_modules\minimist\test\dash.js
    adding script node_modules\minimist\test\default_bool.js
    adding script node_modules\minimist\test\dotted.js
    adding script node_modules\minimist\test\long.js
    adding script node_modules\minimist\test\parse.js
    adding script node_modules\minimist\test\parse_modified.js
    adding script node_modules\minimist\test\short.js
    adding script node_modules\minimist\test\whitespace.js
    adding script node_modules\mkdirp\bin\cmd.js
    adding script node_modules\mkdirp\examples\pow.js
    adding script node_modules\mkdirp\index.js
    adding script node_modules\mkdirp\package.json
    adding script node_modules\mkdirp\test\chmod.js
    adding script node_modules\mkdirp\test\clobber.js
    adding script node_modules\mkdirp\test\mkdirp.js
    adding script node_modules\mkdirp\test\opts_fs.js
    adding script node_modules\mkdirp\test\opts_fs_sync.js
    adding script node_modules\mkdirp\test\perm.js
    adding script node_modules\mkdirp\test\perm_sync.js
    adding script node_modules\mkdirp\test\race.js
    adding script node_modules\mkdirp\test\rel.js
    adding script node_modules\mkdirp\test\return.js
    adding script node_modules\mkdirp\test\return_sync.js
    adding script node_modules\mkdirp\test\root.js
    adding script node_modules\mkdirp\test\sync.js
    adding script node_modules\mkdirp\test\umask.js
    adding script node_modules\mkdirp\test\umask_sync.js
    adding script node_modules\mkdirp-then\index.js
    adding script node_modules\mkdirp-then\package.json
    adding script node_modules\native-or-bluebird\index.js
    adding script node_modules\native-or-bluebird\package.json
    adding script node_modules\native-or-bluebird\promise.js
    adding script node_modules\pad\lib\colors.js
    adding script node_modules\pad\lib\index.js
    adding script node_modules\pad\package.json
    adding script node_modules\pad\samples\left.js
    adding script node_modules\pad\samples\right.js
    adding script node_modules\path\package.json
    adding script node_modules\path\path.js
    adding script node_modules\ping-bluebird\examples\example.js
    adding script node_modules\ping-bluebird\examples\example2.js
    adding script node_modules\ping-bluebird\index.js
    adding script node_modules\ping-bluebird\lib\ping-promise.js
    adding script ....ebird\node_modules\bluebird\js\browser\bluebird.js
    adding script ....d\node_modules\bluebird\js\browser\bluebird.min.js
    adding script ....ping-bluebird\node_modules\bluebird\js\main\any.js
    adding script ....g-bluebird\node_modules\bluebird\js\main\assert.js
    adding script ....ng-bluebird\node_modules\bluebird\js\main\async.js
    adding script ....ing-bluebird\node_modules\bluebird\js\main\bind.js
    adding script ....bluebird\node_modules\bluebird\js\main\bluebird.js
    adding script ....bluebird\node_modules\bluebird\js\main\call_get.js
    adding script ....g-bluebird\node_modules\bluebird\js\main\cancel.js
    adding script ....rd\node_modules\bluebird\js\main\captured_trace.js
    adding script ....bird\node_modules\bluebird\js\main\catch_filter.js
    adding script ....-bluebird\node_modules\bluebird\js\main\context.js
    adding script ....ird\node_modules\bluebird\js\main\debuggability.js
    adding script ....rd\node_modules\bluebird\js\main\direct_resolve.js
    adding script ....ing-bluebird\node_modules\bluebird\js\main\each.js
    adding script ....g-bluebird\node_modules\bluebird\js\main\errors.js
    adding script ....ping-bluebird\node_modules\bluebird\js\main\es5.js
    adding script ....g-bluebird\node_modules\bluebird\js\main\filter.js
    adding script ....-bluebird\node_modules\bluebird\js\main\finally.js
    adding script ....uebird\node_modules\bluebird\js\main\generators.js
    adding script ....ing-bluebird\node_modules\bluebird\js\main\join.js
    adding script ....ping-bluebird\node_modules\bluebird\js\main\map.js
    adding script ....g-bluebird\node_modules\bluebird\js\main\method.js
    adding script ....-bluebird\node_modules\bluebird\js\main\nodeify.js
    adding script ....bluebird\node_modules\bluebird\js\main\progress.js
    adding script ....-bluebird\node_modules\bluebird\js\main\promise.js
    adding script ....ird\node_modules\bluebird\js\main\promise_array.js
    adding script ....\node_modules\bluebird\js\main\promise_resolver.js
    adding script ....luebird\node_modules\bluebird\js\main\promisify.js
    adding script ....ng-bluebird\node_modules\bluebird\js\main\props.js
    adding script ....ng-bluebird\node_modules\bluebird\js\main\queue.js
    adding script ....ing-bluebird\node_modules\bluebird\js\main\race.js
    adding script ....g-bluebird\node_modules\bluebird\js\main\reduce.js
    adding script ....bluebird\node_modules\bluebird\js\main\schedule.js
    adding script ....g-bluebird\node_modules\bluebird\js\main\settle.js
    adding script ....ing-bluebird\node_modules\bluebird\js\main\some.js
    adding script ....modules\bluebird\js\main\synchronous_inspection.js
    adding script ....luebird\node_modules\bluebird\js\main\thenables.js
    adding script ....g-bluebird\node_modules\bluebird\js\main\timers.js
    adding script ....ng-bluebird\node_modules\bluebird\js\main\using.js
    adding script ....ing-bluebird\node_modules\bluebird\js\main\util.js
    adding script ....s\ping-bluebird\node_modules\bluebird\package.json
    adding script node_modules\ping-bluebird\package.json
    adding script node_modules\ping-bluebird\test\test.js
    adding script node_modules\process\browser.js
    adding script node_modules\process\index.js
    adding script node_modules\process\package.json
    adding script node_modules\process\test.js
    adding script node_modules\util\package.json
    adding script node_modules\util\support\isBuffer.js
    adding script node_modules\util\support\isBufferBrowser.js
    adding script node_modules\util\test\browser\inspect.js
    adding script node_modules\util\test\browser\is.js
    adding script node_modules\util\test\node\debug.js
    adding script node_modules\util\test\node\format.js
    adding script node_modules\util\test\node\inspect.js
    adding script node_modules\util\test\node\log.js
    adding script node_modules\util\test\node\util.js
    adding script node_modules\util\util.js
    adding script node_modules\weak-map\package.json
    adding script node_modules\weak-map\weak-map.js
    adding asset node_modules\bluebird\changelog.md
    adding asset node_modules\bluebird\LICENSE
    adding asset node_modules\bluebird\README.md
    adding asset node_modules\collections\.editorconfig
    adding asset node_modules\collections\CHANGES.md
    adding asset node_modules\collections\FUTURE.md
    adding asset node_modules\collections\LICENSE.md
    adding asset node_modules\collections\README.md
    adding asset node_modules\colors\LICENSE
    adding asset node_modules\colors\ReadMe.md
    adding asset node_modules\inherits\LICENSE
    adding asset node_modules\inherits\README.md
    adding asset node_modules\minimist\.travis.yml
    adding asset node_modules\minimist\LICENSE
    adding asset node_modules\minimist\readme.markdown
    adding asset node_modules\mkdirp\.travis.yml
    adding asset node_modules\mkdirp\bin\usage.txt
    adding asset node_modules\mkdirp\LICENSE
    adding asset node_modules\mkdirp\readme.markdown
    adding asset node_modules\mkdirp-then\History.md
    adding asset node_modules\mkdirp-then\LICENSE
    adding asset node_modules\mkdirp-then\README.md
    adding asset node_modules\native-or-bluebird\LICENSE
    adding asset node_modules\native-or-bluebird\README.md
    adding asset node_modules\pad\.npmignore
    adding asset node_modules\pad\LICENSE
    adding asset node_modules\pad\README.md
    adding asset node_modules\path\.npmignore
    adding asset node_modules\path\LICENSE
    adding asset node_modules\path\README.md
    adding asset node_modules\ping-bluebird\.npmignore
    adding asset ....es\ping-bluebird\node_modules\bluebird\changelog.md
    adding asset ....modules\ping-bluebird\node_modules\bluebird\LICENSE
    adding asset ....dules\ping-bluebird\node_modules\bluebird\README.md
    adding asset node_modules\ping-bluebird\README.md
    adding asset node_modules\process\LICENSE
    adding asset node_modules\process\README.md
    adding asset node_modules\util\.npmignore
    adding asset node_modules\util\.travis.yml
    adding asset node_modules\util\.zuul.yml
    adding asset node_modules\util\LICENSE
    adding asset node_modules\util\README.md
    adding asset node_modules\weak-map\README.md
    ..
    [OK] compiled file is ready (C:\AjpdSoft_JavaScript\actualizar.exe)

 

 

Artículos relacionados

 

Créditos

Idea original y código fuente JavaScript realizado por Alejandro Centenero para Proyecto AjpdSoft.
Artículo realizado por Alonsojpd miembro fundador del Proyecto AjpdSoft.

Artículo en inglés.


Anuncios


Enviado el Miércoles, 18 noviembre a las 20:52:13 por ajpdsoft
Visita nuestro nuevo sitio web con programas y contenidos actualizados: Proyecto A