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.
- Código JavaScript para copiar carpetas a varios destinos de forma asíncrona.
- Cómo interpretar y ejecutar JavaScript mediante Node.js.
- Cómo generar un ejecutable a partir de un JavaScript con JXcore y Node.js.
- Anexo.
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»:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "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:
El siguiente código puede descargarse gratuitamente pulsando aquí:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 |
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. Inicialmente 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:
Y descargaremos la versión estable, en nuestro caso «v5.0.0 Stable»:
Guardaremos el fichero node-v5.0.0-x64.msi:
Ejecutaremos el fichero descaragado:
Es posible que nos muestre un mensaje de advertencia de seguridad, pulsaremos «Ejecutar»:
Se iniciará el asistente de instalación de Node.js, pulsaremos «Next»:
Leeremos los términos de licencia, si estamos de acuerdo marcaremos «I accept the terms in the Licence Agreement» y pulsaremos «Next»:
Pulsaremos «Next»:
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:
El asistente nos indicará que Node.js ha sido instalado correctamente en nuestro equipo:
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»:
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
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:
Pulsa aquí para ver la salida comando npm init.
El comando anterior nos habrá creado el fichero package.json:
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
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:
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:
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:
El contenido de la subcarpeta «node_modules»:
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:
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):
Guardaremos el archivo jx_winsetup.zip:
Lo descomprimiremos:
Ejecutaremos el fichero JXcore_setup.exe:
Se iniciará el asistente de instalación de JXcore, pulsaremos «Next»:
Leeremos los términos de liciencia, si estamos de acuerdo marcaremos «I accept the agreement» y pulsaremos «Next»:
Elegiremos la carpeta de instalación y pulsaremos «Next»:
A continuación podremos elegir el ambiente de ejecución a instalar, en nuestro caso «V8 x64»:
Elegiremos el nombre para la carpeta que se creará en la barra de tareas y pulsaremos «Next»:
Es recomendable marcar la opción «Add application directory to environment PATH variable» para poder ejecutar el comando «jx» desde cualquier carpeta del equipo:
Comprobaremos las opciones elegidas, si son correctas puldaremos «Install» para instalar definitivamente JXcore:
Tras la instalación el asistente nos indicará que JXcore ha sido instalado correctamente. Pulsaremos «Finish»:
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)
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).
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:
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:
El contenido del fichero actaulizar.json de ejemplo del que ha leído la información el fichero actualizar.exe:
Anexo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
{ "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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 |
Processing the folder.. JXP project file (actualizar.jxp) is ready. preparing the JX file.. Compiling actualizar 1.0 adding script actualizar.js ... 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) |