Proyecto Liqueed (6)

Anterior Post

Sigamos viendo algun test de test/personapi.js en el proyecto:

https://github.com/liquid-co-ops/liqueed

Hay entradas en la API que se llaman por PUT o POST, y reciben datos en el cuerpo del mensaje enviado. En Express, usando el middleware adecuado, ese mensaje es analizado y convertido en un objecto JSON, y puesto en el campo body del objeto request original. Pues bien, si nuestra entrada en la API usa ese campo, se lo tenemos que entregar en el test. Un ejemplo:

exports['login person'] = function (test) {
    test.async();
    
    var request = {
        body: {
            username: persons[1].username,
            password: persons[1].username
        }
    };

    var response = {
        send: function (model) {
            test.ok(model);
            test.equal(model.id, persons[1].id);
            test.equal(model.name, persons[1].name);
            test.equal(model.username, persons[1].username);
            
            test.done();
        }
    };
    
    controller.loginPerson(request, response);
};

Como antes, en el response ponemos la función send, que esperamos se invoque asincrónicamente para dar por ejecutado el test.

Otro ejemplo donde no sólo enviamos body sino también parámetros (esos parámetros en general están en la ruta, y Express los toma de ahí y nos lo deja en request.params:

exports['change password first person'] = function (test) {
    test.async();
    
    var request = {
		params : {
			id : persons[0].id.toString()
		},
        body: {
            password: 'new' + persons[0].username
        }
    };

    async()
    .then(function (data, next) {
        var response = {
            send: function (model) {
                test.ok(model);
                test.strictEqual(model, true);
                
                next(null, null);
            }
        };
        
        controller.updatePassword(request, response);
    })
    .then(function (data, next) {
        var request = {
            body: {
                username: persons[0].username,
                password: 'new' + persons[0].username
            }
        };

        var response = {
            send: function (model) {
                test.ok(model);
                test.equal(model.id, persons[0].id);
                test.equal(model.name, persons[0].name);
                test.equal(model.username, persons[0].username);
                
                test.done();
            }
        };
        
        controller.loginPerson(request, response);
    })
    .run();
};
 

Próximos posts: pruebas del controlador MVC, pruebas levantando el servidor, pruebas usando un DSL (Domain Specific Language)

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Posted in Express, JavaScript, Liqueed, NodeJs, Test-Driven Development | Comments Off

Proyecto Liqueed (5)

Anterior Post

Examinemos dos tests de test/personapi.js. El segundo test es:

exports['get persons'] = function (test) {
    test.async();
    
    var request = {};
    var response = {
        send: function (model) {
            test.ok(model);
            test.ok(Array.isArray(model));
            test.ok(model.length);
            test.ok(model[0].id);
            test.ok(model[0].name);
            test.done();
        }
    };
    
    controller.list(request, response);
};

Una vez ya armado el modelo de dominio (en el primer test), ahora podemos probar un método del controlador, el getPersons. Como necesita recibir request y response, le pasamos dos objetos armados a propósito, y que tienen lo que el controlador necesita. El response tiene definido un método send, que se espera sea invocado por la acción del controlador. Ahí es donde reside el test de lo retornado, y el test.done() que hace que el test termine exitosamente. Se espera que devuelva un modelo, un objeto JSON que sea un arreglo, que contenga algunos datos.

El tercer test es:

exports['get first person'] = function (test) {
    test.async();
    
    var request = {
        params: {
            id: persons[0].id.toString()
        }
    };

    var response = {
        send: function (model) {
            test.ok(model);
            test.equal(model.id, persons[0].id);
            test.equal(model.name, persons[0].name);
            test.done();
        }
    };
    
    controller.get(request, response);
};

Esta vez se necesita algo en el objeto request, un parámetro adicional indicando la clave primaria de la persona. Sigue habiendo un método send en el response armado para el test, que controla que se devuelvan los datos de la persona pedida.

Vemos que acá no se está invocando HTTP con GET o cosas similares. Estamos probando directamente el código del controlador. De hecho, el código fue escrito luego del tests, y se ejecutó por primera vez desde los tests, sin necesidad de levantar un servidor HTTP.

Próximo post: veremos la prueba de otros métodos de la API, pasándoles objetos, y pruebas del controlador MVC

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Posted in Express, JavaScript, Liqueed, NodeJs, Test-Driven Development | Comments Off

Proyecto Liqueed (4)

Anterior Post
Siguiente Post

Ya quedó claro en los posts anteriores que gran parte del proyecto:

https://github.com/liquid-co-ops/liqueed

ha sido armado siguiendo el flujo de trabajo de TDD (Test-Driven Development).

En el anterior post vimos un ejemplo de lógica de servicio, cómo quedó implementada siguiendo tests. Veamos hoy que hay controladores, módulos JavaScript que exponen métodos como acciones a mapear por Express, que exponen una API (Application Program Interface) hacia afuera. Por ejemplo, controllers\personapi.js, que comienza declarando:

'use strict';

var service = require('../services/person');

Vean que usa al servicio de personas.

Hay tests correspondientes, en test\personapi.js, que comienza importando los módulos que va a usar:

'use strict';

var controller = require('../controllers/personapi');

var loaddata = require('../utils/loaddata');
var db = require('../utils/db');
var async = require('simpleasync');

En el anterior posts, discutí que en JavaScript la granularidad que prefiero para correr los tests es el módulo, más que una función. Luego ejecuto los tests en orden, dentro de ese módulo. Acá aparece el primer test, que se ocupa de inicializar el modelo de dominio:

var persons;

exports['clear and load data'] = function (test) {
    var personService = require('../services/person');

    test.async();
    
    async()
    .then(function (data, next) { db.clear(next); })
    .then(function (data, next) { loaddata(next); })
    .then(function (data, next) { personService.getPersons(next); })
    .then(function (data, next) {
        persons = data;
        test.ok(persons);
        test.ok(persons.length);
        test.done();
    })
    .run();
};

Lo nuevo aca a entender, es el uso de simpleasync, en la variable async, un módulo que escribí hace un tiempo para encadenar funciones JavaScript. Cada función recibe: data, el resultado de la anterior función, y next, un callback de JavaScript que admite dos argumentos: err y data. La función que definamos en la cadena, puede tomar data como resultado bueno de la anterior función definida en la cadena, y entregar err en null, y el nuevo data para el siguiente eslabón. O puede entregar err, y data en null, si detecta algún problema. Vemos en el ejemplo de arriba, que personService.getPersons(next) invoca la recuperación de la lista de personas, y se le pasa next, como callback. Entonces, la siguiente función en la cadena recibe data como respuesta, y lo utiliza.

A pesar que parece que está usando una base de datos, lo asumido es usar un modelo en memoria. Tenemos que ver dónde está esa decisión, pero hoy nos basta saber que el modelo inicial está en el directorio principal, en formato JSON en testdata.json. Parte de este archivo:

{
    "projects": [
        {
            "name": "FaceHub",
            "periods": [
                { 
                    "name": "January 2014", 
                    "date": "2014-01-31", 
                    "amount": 100,
                    "assignments": [
                        { "from": "Alice", 
                            "to": "Bob", 
                            "amount": 50, 
                            "note": "Arrive earlier" },
                        { "from": "Alice", 
                            "to": "Charlie", 
                            "amount": 50 , 
                            "note": "Arrive earlier" },
                        { "from": "Bob", 
                            "to": "Alice", 
                            "amount": 60 , 
                            "note": "Arrive earlier" },
                        { "from": "Bob", 
                            "to": "Charlie", 
                            "amount": 40 , 
                            "note": "Arrive earlier" },
                        { "from": "Charlie", 
                            "to": "Alice", 
                            "amount": 35 , 
                            "note": "Arrive earlier" },
                        { "from": "Charlie", 
                            "to": "Bob", 
                            "amount": 65 , 
                            "note": "Arrive earlier" }
                    ]
                },
                { "name": "February 2014", 
                    "date": "2014-02-28", 
                    "amount": 100 }
            ],
            "team": [ "Alice", "Bob", "Charlie" ],
//....

Vemos que personapi.js como módulo, al final termina exportando las acciones que queremos consumir:

module.exports = {
    list: list,
    get: get,
    getProjects: getProjects,
    loginPerson: loginPerson,
    getPendingShareProjects:getPendingShareProjects,
    updatePassword: updatePassword
}

Veremos en próximos posts, el segundo y siguientes tests de la API de persona, y cómo las acciones se rutean con Express.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Posted in JavaScript, Liqueed, NodeJs, Test-Driven Development | Comments Off

Resoluciones del Nuevo Mes: Abril 2015

Es tiempo de revisar mis resoluciones de marzo, y escribir las nuevas para este mes:

– Mejorar ClojSharp [completo] ver repo
– Mejorar ScalaSharp [completo] ver repo
– Escribir posts sobre JavaScript e Inteligencia Artifical [pendiente]
– Primera versión publicada de ClojJS [parcial] ver repo
– Agregar soporte de módulos npm a ClojJS [pendiente]
– Primera versión publicada de BScript [parcial] ver repo
– Mejorar el emulador Chip8 [pendiente]
– Dar un curso de un día de NodeJS [completo]

También estuve trabajando en:

- Actualizar SimpleAsync, removiendo setImmediate [completo] ver repo
- Actualizar SimpleBus para usar SimpleUnit [completo] ver repo
- Mejorar AcquarellaJS detectando comentarios [completo] ver repo
- Mejorar SimpleArgs usando flags [completo] ver repo
- Mejorar DValues [completo] ver repo
- Actualizar Complexo para usar SimpleUnit en los tests [completo] ver repo
- Trabajar en Proyecto Liqueed [completo] ver repo

Mis resoluciones para este nuevo mes:

– Escribir posts sobre JavaScript e Inteligencia Artificial
- Mejorar ClojJS
- Agregar soporte de módulos npm a ClojJS
- Mejorar el emulador Chip8
- Mejorar BScript

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Posted in .NET, C#, JavaScript, NodeJs, Proyectos Open Source | Leave a comment

Proyecto Liqueed (3)

Post Anterior
Post Siguiente

Ya saben que soy un gran defensor de TDD (Test-Driven Development), que es un flujo de trabajo para el desarrollo de software, donde lo que vamos construyendo es a partir de escribir tests que describan lo que queremos, e implementar de la forma más simple lo que se pide en el tests. En el proyecto Liqueed se adoptó, para gran parte del código, esta forma de trabajo.

Por ejemplo, hay un archivo services\person.js, que es un módulo JavaScript, que maneja la lógica de las personas. Una persona puede participar en cero, uno o varios proyectos, tener puntos acumulados, votar, etc. Y el sistema tiene que mantener la lista de las personas, ubicarlas por id, por código de usuario, etc. Parte de esa lógica está en este módulo de servicio. Al armarlo, se fue escribiendo un test\person.js con los tests que describen la lógica a soportar. Al comienzo de ese archivo, se declaran:

'use strict';

var service = require('../services/person');
var pservice = require('../services/project');
var async = require('simpleasync');

Se usa el servicio person.js, y en algún test se usa también alguna lógica del servicio de proyectos. simpleasync es un módulo sencillo que escribí para encadenar la llamada de callbacks. Me resultó muy interesante escribirlo y me sirvió en varios proyectos.

Luego, se declaran dos variables de módulo, auxiliares, para reusar en varios tests. Son los ids de algunas personas de prueba a crear y usar:

var annaid;
var lauraid;

Para ejecutar los tests estoy usando simpleunit, otro módulo que escribí, de nuevo para practicar JavaScript, TDD y simplicidad. Está inspirado en nodeunit, pero es más simple. simpleunit ejecuta las funciones exportadas de un módulo, pasándole como argumento un objeto test, similar al assert de NodeJS.

El primer test de este archivo test\person.js ejercita el agregar una persona:

exports['add person'] = function (test) {
    test.async();

    service.addPerson({ name: 'Anna' }, function (err, result) {
        test.ok(!err);
        test.ok(result);
        annaid = result;
        test.done();
    });
};

Como es un callback cuya ejecución es asincrónica (con lo que la función exportada puede terminar ANTES que se cumpla la creación de la persona), hay que declarar test.async() para indicarle a simpleunit que tiene que esperar a que el test se corra completamente, y test.done() para indicar que se terminó la ejecución. En este test sólo se prueba que se devuelva un id de la nueva persona, y se lo guarda en una variable de módulo. Una cosa que me resultó fácil, pero que no se recomienda en otros casos (como C#), es el tener una secuencia de tests, es decir, que cada test pueda depender de haber ejecutado otros. Hasta ahora, en JavaScript, el nivel de aislamiento/corrida es el módulo de test, no la función de test. Pero veremos si alguna vez esto expone limitaciones.

Veamos un test más:

exports['get person by id'] = function (test) {
    test.async();

    service.getPersonById(annaid, function (err, result) {
        test.ok(!err);
        test.ok(result);
        test.equal(result.name, 'Anna');
        test.equal(result.id, annaid);
        test.equal(result.username, 'anna');
        test.done();
    });
};

Ahora, con el id generado en el anterior test, recuperamos a la persona, y comprobamos sus datos.

Vean que la serie de tests no presupone nada sobre el estado del dominio: puede haber o no otras personas, proyectos, etc. Vamos a ver también, que justo estos tests están usando un dominio en memoria, pero también hay tests que usan una base de datos de tests. Pero lo interesante del proyecto, usando TDD, es que al principio todo el dominio estaba en memoria, y solamente ya avanzado algún caso de uso, se pasó a implementar persistencia. Pueden ver la historia de commits en el repositorio para ver cómo el sistema fue creciendo, como un organismo, agregándole cosas poco a poco, sin pensar por adelantado, cambiando y refactorizando código de manera sencilla, y con confianza, al tener una batería de tests de mini-casos de uso.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Posted in JavaScript, Liqueed, NodeJs, Test-Driven Development | Comments Off

Resoluciones del Nuevo Mes: Marzo 2015

Tiempo de revisar el resultado de las resoluciones de febrero, y de escribir las del nuevo mes, marzo.

- Completar primera versión ClojJS [parcial] ver repo
- Completar primera versión BScript [parcial] ver repo
- Mejorar ClojSharp [completo] ver repo
- Mejorar ScalaSharp [completo] ver repo
- Completar primera versión emulador Chip8 [parcial] ver repo
- Escribir más posts sobre JavaScript e Inteligencia Artificial [pendiente]

Aunque ClojJS ya está avanzado, y tiene mucho funcionando, incluso algún ejemplo web simple, todavía le faltan algunas cosas, como resolver un require usando lo que esté instalado en node_modules y sea detectado como clojurescript usando el archivo clojjs.json. Quiero entonces darle un impulso más y dejarlo listo como primera versión.

Adicionalmente, estuve trabajando en:

- Comenzar SimpleDSL módulo node.js/javascript para definir verbos de un Domain-Specific Language [completo] ver repo
- Mejorar AjScript [completo] ver repo
- Mejorar AcquarellaJS [completo] ver repo
- Comenzar DValues repositorio de valores (a colectar desde dispositivos) [completo] ver repo

Entonces, las resoluciones para el nuevo mes son:

- Mejorar ClojSharp
- Mejorar ScalaSharp
- Escribir post sobre JavaScript e Inteligencia Artificial
- Publicar primera versión de ClojJS
- Agregar soporte de módulos npm a ClojJS
- Primera versión publicada de BScript
- Mejorar el emulador de Chip8
- Dar curso de un día sobre NodeJS

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Posted in .NET, C#, JavaScript, NodeJs, Proyectos Open Source | Leave a comment

Proyecto Liqueed (2)

Anterior Post
Siguiente Post

Como todo proyecto Node.js, el proyecto Liqueed, en

https://github.com/liquid-co-ops/liqueed

El contenido actual es:

{
  "name": "liqueed",
  "version": "0.0.2alpha",
  "private": true,
  "scripts": {
    "start": "node ./bin/www",
    "test": "simpleunit ./test ./testserver"
  },
  "dependencies": {
    "express": "~4.2.0",
    "static-favicon": "~1.0.0",
    "morgan": "~1.0.0",
    "cookie-parser": "~1.0.1",
    "body-parser": "~1.0.0",
    "debug": "~0.7.4",
    "ejs": "~0.8.5",
    "express-ejs-layouts": "^1.1.0",
    "ostore": "0.0.4",
    "simplelists": "0.0.4",
    "simpleasync": "0.0.5",
    "mongodb": "~1.4.19",
    "bcrypt-nodejs": "0.0.3",
    "express-session": "~1.9.3"
  },
  "devDependencies": {
    "simpleunit": "0.0.5",
    "simplejquery": "0.0.1",
    "zombie": "2.5.1"
  }
}

Es una aplicación privada, es decir, no se puede publicar en el repositorio público de npm.

Es una típica aplicación express, con código inicial generado con express-generator. El archivo bin\www tiene el código de lanzamiento de la aplicación. Tiene módulos express, como morgan, cookie-parser, body-parser, express-session, pero también algunos más que se usan en la implementación de la lógica interna del sistema:

– ostore: repositorio de simples objetos JavaScript en memoria, usado en varios tests y en la versión inicial, como persistencia en memoria, sin necesidad de usar una base de datos desde el principio.

– mongodb: el sistema final usa MongoDB como base NoSQL

– simplelists: un simple utilitario con funciones sobre listas (arreglos)

– simpleasync: una librería para encadenar llamadas asincrónicas sin morir en el intento.

– bcript-nodejs: módulo de encriptación escrito en JavaScript

Para los tests (armados siguiendo el flujo de trabajo de TDD, Test-Driven Development), uso:

– simpleunit: librería de test, basada en usar assert internamente, exportando los métodos a testear en cada archivo de test.

Para los tests de las páginas de la Single Page Application de public\index.html se usa:

– zombie: visita una página como si fuera un browser

Próximos temas en próximos posts: cómo está estructurada la lógica del servidor, los tests que se escribieron, exponer API, páginas MVC, persistencia, cliente SPA (Single Page Application).

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Posted in JavaScript, Liqueed, NodeJs, Proyectos Open Source | Comments Off

Programando para Internet of Things

Como saben, siempre practico programar todos los días, especialmente aplicando TDD (Test-Driven Development). Y si bien hay proyectos no públicos, la mayor parte de esa práctica la pueden ver en mi cuenta pública de GitHub. Y como escribí en el post de ayer, Node.js es una tecnología muy interesante, por su poder y simplicidad, para implementar muchas ideas que en otras tecnologías (Java, .NET, Scala, Ruby, Python, Clojure, Smalltalk) no me parece que sea tan fácil (aclaro lo de siempre: el precio a pagar por programar en el paraíso de Node.js son los “callbacks”).

Hay muchas ideas e implementaciones interesantes (en aplicaciones, proyectos, “startups”) dando vueltas. Pero un tema interesante que ya está entre nosotros, pero que va ir creciendo todavía más, es el tema Internet of Things. ¿Habrá lugar para que “startups” puedan luchar e imponerse en este campo? ¿será deglutido por Google, Apple, Microsoft? Veremos. Pero independientemente de eso, es época para programar e implementar ideas, en código abierto. Si se puede montar una “startup” encima de eso, mejor (pienso que para una “startup” lo principal es la EJECUCION: ideas hay a millones, e implementaciones hay a miles).

Mientras, algunas ideas (con alguna implementación incipiente en mis proyectos públicos de GitHub, ya vieron algunas ideas e implementaciones en mis charlas) (por supuesto, hay YA implementaciones, y también “startups”, pero siempre es interesante explorar por uno mismo un campo):

- Recolectar información de dispositivos, conectados a la red. Tener un repositorio de datos, enviados desde un SDK cliente para cada dispositivo. Luego, explotar esos datos.

- Aplicar Inteligencia Artificial (bueno, es un término amplio, lo admito, pero el mejor que tenemos por ahora) a todos esos datos, descubriendo patrones, aplicando “machine learning”, “deep learning”. Hábrán visto algunas implementaciones en JavaScript en mis proyectos

- Tomar decisiones, usando sistemas expertos u otros, y ejecutar comandos, acciones. De nuevo, habrán visto implementaciones mías en JavaScript/Node.js. Tener algo como IFTTT abierto, listo para usar, alimentado por eventos y datos colectados de Internet of Things.

- Aplicar para todo esto, computación distribuida, no solamente escalabilidad horizontal transparente en la nube. Hay mil estrategias para implementar, y Node.js es un vehículo interesante para experimentar. Luego, se puede pasar a un lenguaje y tecnología compilado, si hace falta ganar en rendimiento de serialización, por ejemplo.

Disculpen la auto-referencia a proyectos míos, pero quería pasar en limpio el panorama por el cual estoy haciendo esos proyectos.

Y además, me diviegto como logco! :-)

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Posted in Aplicaciones Distribuidas, Inteligencia Artificial, Internet of Things, JavaScript, NodeJs, Proyectos Open Source | Comments Off

Jornada Programando en Node.Js desde Cero, en Buenos Aires

Gracias a la gente del MUG (Microsoft User Group de Argentina), voy a dictar todo un día la jornada presencial:

http://www.mug-it.org.ar/Event.aspx?Event=218

Jueves 12 de Marzo, desde las 9:30hs hasta las 18:00hs, con intervalos.

La idea es que si vienen con una notebook y son programadores (.NET, o de otra tecnología), podamos ver juntos cómo es Node, programar algún código simple, aprender a usar y bajarse módulos. Entre el final de la mañana y el comienzo de la tarde, veremos programación web, usando algún ejemplo con Express. Después aparecerá un ejemplo con acceso a MongoDB, y hacia el final, visitaremos Socket.IO.

El temario es entonces:

1. Introducción a Node.js
1.1. Programación Javascript desde Node sobre el motor V8
1.2. Entrada/Salida asincrónica
1.3. Módulos
1.4. Manejador de paquetes npm
1.5. Elementos de Test-Driven Development
2. Programación Web con Node.js
2.1. Módulo HTTP
2.2. Manejo asincrónico
2.3. Acceso a MongoDB
3. Programación Web con Express
3.1. Concepto de Middleware
3.2. Lenguaje de Templates
3.3. Ejemplos con Páginas y Acceso a Datos
3.4. Programando con JSON
3.5. Elementos de Socket.IO

Veo a Node como la tecnología y ecosistema que mejor combina simplicidad con potencia. Es un aire fresco en la programación, ya sea web o de servicios expuestos por API, o distribuidos. Y realmente, el ecosistema de paquetes que tiene es el mejorcito con el que me he encontrado hasta ahora. El gran precio a pagar: usar y entender los “callback” en JavaScript, es el derecho de piso a pagar. He visto aplicaciones de startups y otras aplicaciones totalmente desarrolladas en Node.js, con buena escalabilidad y nivel de servicio. Hasta podrían usar .NET desde Node.js, aunque no es muy usado.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Posted in Buenos Aires, JavaScript, NodeJs | Comments Off

Enviando Mensaje a Slack con JavaScript/Node.js

Hace ya como un año o algo más, entró en mi radar Slack:

https://slack.com/

Leo ahí “Slack is a platform for team communication; everything in one place, instantly searcheable, available wherever you go”.

En general, soy algo excéptico a las herramientas en línea de este tipo, prefiero una combinación más simple. Para lo que dice arriba, me basta gmail y listas de correo por proyecto o equipo. Pero pueden leer la interesante historia del fundador de Slack y las ideas que hay detrás del emprendimiento en:

http://www.wired.com/2014/08/the-most-fascinating-profile-youll-ever-read-about-a-guy-and-his-boring-startup/

Mis enlaces sobre Slack en:

https://delicious.com/ajlopez/slack

Por ejemplo, pueden leer este artículo con tips sobre como usarlo:

https://medium.com/@slackhq/11-useful-tips-for-getting-the-most-of-slack-5dfb3d1af77

Ayer a la tarde me puse a explorar cómo enviar un mensaje, usando la API expuesta por Slack, desde Node.js (que me parece la tecnología más simple para este tipo de experimentos). Más info general de la API en:

https://api.slack.com/

Busqué en Google algún módulo de Node.js y encontré como primer resultado:

https://github.com/xoxco/node-slack

Lo instalé con NPM en un directorio de trabajo, y probé algo como:

var domain = process.env.SLACK_DOMAIN;
var token = process.env.SLACK_TOKEN;

var Slack = require('node-slack');
var slack = new Slack(domain, token);

var channel = process.argv[2];
var message = process.argv[3];

console.log('Sending message', message, 'to channel', channel);

slack.send({
    text: message,
    channel: '#' + channel,
    username: username
});

Se debe poner valores en las variables de ambiente SLACK_DOMAIN y SLACK_TOKEN. Cuando uno ingresa a un grupo de Slack, corresponde a un dominio. Por ejemplo, uno es https://squeakros.slack.com donde está la gente de Smalltalk Squeak Rosario. Otro es https://nodejsar.slack.com, la gente de Node.js Argentina. El token es por usuario y aplicación y lo podemos pedir en:

https://api.slack.com/web

Bien, el programa ejecutó sin problema con

node run.js general “Hello, world”

en Windows (o sea, el primer argumento luego de run.js, es el canal destino, sin el # (numeral), y el segundo argumento es el texto del mensaje). Pero no llegaba el mensaje. Tampoco daba error. Al fin, encontré el Pull Request:

https://github.com/xoxco/node-slack/pull/8

que parece que no fue integrado todavía al código original. Resulta que hace unos meses, cambió la API de Slack. El pull request sugerido usa otro forma de acceso, en vez de token usa una URL provista desde:

https://your-domain.slack.com/services/new/incoming-webhook

Usé la sugerencia que está en uno de los comentarios, pedir el node-slack directamente desde la dirección en GitHub del pull request, en el package.json que describe al proyecto y sus dependencias:

{
  "name": "slack-demo",
  "private": true,
  "version": "0.0.1",
  "dependencies": {
    "node-slack": "git://github.com/Dahlgren/node-slack.git#hook-url"
  }
}

Y el programa ahora usa esa URL, tomada desde una variable de ambiente:

var hookUrl = process.env.SLACK_WEBHOOK;
var username = process.env.SLACK_USER;

var Slack = require('node-slack');
//var slack = new Slack(domain, token);
var slack = new Slack(hookUrl);

var channel = process.argv[2];
var message = process.argv[3];

console.log('Sending message', message, 'to channel', channel);

slack.send({
    text: message,
    channel: '#' + channel,
    username: username
});

Todo funciona. Temas a investigar: ¿se podrá seguir usando dominio/token? ¿de qué manera? ¿hay otros módulos más actualizados? Por ahora, sigo experimento con este módulo.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Posted in JavaScript, NodeJs, Slack | Comments Off