Creando programas de línea de comandos con node

Una de las cosas que he hecho últimamente, es instalar un servidor con una Raspberry Pi v2 en casa para acceder desde fuera usando OpenVPN. Pero para que fuera accesible siempre a través del mismo dominio necesitaba una forma de actualizar el registro DNS y quería hacerlo con mi propio dominio y no con ddns, no-ip o similares así que hice un programa en node que hiciera esto por mi aprovechando la API de OVH.

Requisitos

  • Node instalado (y el gestor de paquetes de node npm).
  • Aunque lo haremos aquí se supone que ya tienes tú archivo package.json creado.

Preparativos

Creamos el archivo package.json:

# npm init

Cabecera de nuestro ejecutable

En el script node que queremos que funcione como si de un binario se tratara deberemos de emular a los bash scripts e incluir los caracteres Shebang que caracteriza a los scripts ejecutables, haciendo llamar al interprete nodejs en este caso.

#! /usr/bin/env node

Definiendo cuál será nuestro ejecutable

Los archivos package.json tienen varios parámetros, todos muy bien documentados. Y entre ellos hay dos que son los que nos interesan bin y preferGlobal.

Bin

Bin nos permite definir todos los “symlinks” (enlaces simbólicos) que creará npm en /usr/local/bin/ al archivo node que le definamos. Por ejemplo suponiendo que queramos que dos archivos de nuestro paquete tengan enlaces simbólicos y suponiendo que se van a llamar nodeinout (un programa que basicamente todos los parámetros que le pasemos los devuelve uno por uno) y otro nodecat que lee y saca al stout todo el contenido de un archivo de texto. Por supuesto que los programas no existen y si existen es fruto de la casualidad pues es solo para alimentar el ejemplo.

Para que estos comandos existan debemos de modificar nuestro package.json actual:

{
  "name": "node-cli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "author": "Gabriel Trabanco Llano <gtrabanco@fwok.org> (http://gabi.com.es)",
  "license": "ISC"
}

Y AÑADIR por ejemplo después de license (en cualquier sitio entre los {} “corchetes”):

  "license": "ISC",
  "bin": {
    "nodeinout": "inout.js",
    "nodecat"  : "nodecat.js"
  }

Como véis es muy sencillo, si tuvieramos el archivo javascript (.js) en otro directorio tan solo deberíamos añadir la ruta relativa desde el archivo package.json.

PreferGlobal

El parámetro preferGlobal es de tipo booleano e indica que es un programa de línea de comandos que preferiblemente debe instalarse de manera global (npm install -g), lo cual según la documentación no impedirá que los usuarios puedan instalarlo localmente pero si falla habrá un dato más ahí a la hora de hacer comprobaciones. Lo añadimos igualmente en cualquier parte dentro de {} (los corchetes), por ejemplo:

  "license": "ISC",
  "preferGlobal": true,
  "bin": {
    "nodeinout": "inout.js",
    "nodecat"  : "nodecat.js"
  }

Documentación (man)

Otro de los parámetros posibles es man que permite definir la ruta a un archivo de documentación que luego estará disponible para nuestro programa desde el terminal haciendo man nombre_programa.

No voy a explicar más al respecto, si quieren ver como funciona pueden ver [el cliente que he hecho][dyndns] para lo de los DNS en github. Deben fijarse en el package.json y en el directorio man.

Después según la documentación oficial sobre este parámetro (man), deben de tener en cuenta varias cosas a la hora de nombrar el archivo. Mejor usen la documentación en npmjs (en inglés).

El formato del archivo de documentación pueden verlo en el pie de página. 1

Probando que funciona

Cuando estéis desarrollando vuestro programa, si queréis probar que crea los enlaces correctamente podéis usar el comando:

# npm link

Si después deseáis quitar los enlaces que os ha creado:

# npm unlink

Ejemplo

Como ejemplo, podéis ver la aplicación de línea de comandos que hice para actualizar el registro DNS. Se llama DynHost, si preferís, podéis verlo directamente en el registro npmjs.

Conclusiones

Es sencillo crear programas de línea de comandos con node, pero hay que tener en cuenta estas cosas ya que varía un poco de un desarrollo normal de una página web.

Por otro lado, si queréis que vuestro script acepte parámetros os remito nuevamente a mi proyecto en github y veáis un ejemplo real y funcionando de yargs, una excelente librería que he decidido usar para esta labor.