Avoir accès à ses utilitaires en ligne de commande (CLI) est un quotidien dans nos métiers et un avantage indéniable. Ce n'est pas nouveau et cela existe depuis la nuit des temps. Tout utilisateur d'Unix voue un culte particulier à son terminal.
J'ai récemment eu à développer un utilitaire en Node.js/iojs, j'ai donc voulu avec cet article déblayer un peu le terrain et présenter quelques utilitaires très pratiques.
Deux postulats avant de commencer :
Avant de commencer à coder, il va tout d'abord falloir créer deux fichiers qui seront nécessaires et obligatoires :
// création du dossier
$ mkdir putaindecode-cli && cd putaindecode-cli
// création de index.js
$ touch index.js
// création de package.json
$ touch package.json
Le fichier index.js
va se présenter comme ceci :
#!/usr/bin/env node
// Cette ligne ou shebang permet de définir l'interpréteur de notre script, à savoir `node`
// notre fameux hello world
console.log("Hello world")
Pour notre fichier package.json
, deux méthodes possibles pour l'écrire, soit
en faisant npm init
puis suivre les instructions, soit adapter ce JSON :
{
"name": "putaindecode-cli",
"version": "0.1.0",
"description": "Putaindecode cli",
"keywords": [
"cli",
"npm"
],
"author": "magsout",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/putaindecode/putaindecode-cli.git"
},
"engines": {
"node": ">=0.10"
},
"homepage":"https://github.com/putaindecode-cs/putaindecode-cli"
"bugs": {
"url": "https://github.com/putaindecode-cs/putaindecode-cli/issues"
},
"files": [
"index.js"
],
"dependencies": {},
"devDependencies": {},
"bin": {
"putaindecode": "index.js"
}
}
La ligne importante à ne surtout pas oublier :
"bin": {
"putaindecode-cli": "index.js"
}
Elle permettra de déterminer le script à exécuter lorsque la commande
putaindecode-cli
sera lancée.
Si on vulgarise un peu le principe, en installant le script, le fichier
index.js
sera renommé en putaindecode-cli.js
et sera copié dans le
répertoire adéquat (cela dépend de l'OS).
Lorsque la commande putaindecode-cli
sera exécutée, le shell va chercher le
fichier exécutable en utilisant les répertoires listés dans la variable PATH.
Si on suit ce raisonnement, l'installation d'un script écrasera automatiquement l'ancienne version ou tout script de même nom.
Pour s'assurer qu'il n'existe pas d'autres commandes portant le même nom, il est
conseillé d'utiliser la commande : which putaindecode-cli
qui ne retournera
rien s'il n'y a aucun résultat :
#putaindecode-cli ne retourne aucun résultat
$ which putaindecode-cli
#node est installé et accessible au path suivant
$ which node
/usr/local/bin/node
Afin de vérifier que le script fonctionne correctement, il suffit tout
simplement d'exécuter dans le répertoire la commande : ./index.js
.
Une erreur de droit ? Un petit chmod pour arranger ça : chmod +x index.js
.
À ce stade, si tout fonctionne bien, Hello World
va s'afficher.
Par contre, exécuter notre script de la sorte n'est pas très pratique, d'autant plus qu'il sera nécessaire de connaître à chaque fois le chemin vers le fichier.
Il serait beaucoup plus simple de pouvoir exécuter le script comme une commande.
Comme pour tout package npm, cela se fait avec npm install
.
// installation en global du script
$ npm install -g
// exécution de la commande
$ putaindecode-cli
// résultat de la commande
Hello world
Le script est maintenant accessible partout sur l'OS grâce à la commande
putaindecode-cli
. L'installation en global n'est pas absolument pas
nécessaire, tout dépend de l'intérêt de votre script. Il est d'ailleurs souvent
préférable de l'installer en local dans un projet avec --save
ou --save-dev
.
La puissance de NPM
provient de son nombre impressionnant de packages mis à
disposition.
Pour gagner du temps et éviter d'avoir à recoder la roue. Le script
putaindecode-cli
va avoir besoin de trois choses :
commander
Pour les commandes avec en prime la gestion des arguments et de l'aide, commander est tout a fait adapté et répondra pratiquement à tous nos besoins.
Il est simple d'utilisation et très bien maintenu.
Voici un exemple de ce qu'on peut faire :
/* Default */
program.version(pkg.version);
/* command */
program
.command("command")
.alias("c")
.description(" command does something")
.option("-v, --verbose", "Verbose")
.option("-f, --force", "Force installation")
.action(commandAction)
.on("--help", function() {
console.log(" Example:");
console.log();
console.log(" command does something");
console.log(" $ putaindecode-cli command");
console.log("");
});
/* help */
program.on("--help", function() {
console.log(" Examples:");
console.log();
console.log(" command do something");
console.log(" $ putaindecode-cli command");
console.log("");
console.log(" Force command does something");
console.log(" $ putaindecode-cli command -f");
console.log("");
});
program.parse(process.argv);
/* help by default */
if (!program.args.length) program.help();
chalk
Null besoin de faire un cours sur les couleurs, mais l'affichage d'une notice est bien plus pertinent avec sa couleur associée. C'est à ce moment qu'entre en jeu chalk. Relativement simple à mettre en place et à utiliser :
var chalk = require("chalk");
/* var */
var error = chalk.bold.red;
var warn = chalk.yellow;
var success = chalk.green;
var notice = chalk.blue;
/* code */
console.log(warn("No command"));
console.log(notice("file modified !"));
exit
Peu importe comment s'exécute son code, il est important de bien savoir
maitriser l'arrêt de son script. Pour ça, process.exit()
nous sera bien utile.
Dans le cas d'une erreur, la valeur de exit
doit systématiquement être
supérieure à 0, et donc bien naturellement en cas de succès, elle doit être
égale à 0.
Voici une
liste des valeurs de
exit
et de leurs correspondances.
Si vous souhaitez voir quelques exemples de projets avec des commandes et des mises en situations intéressantes, allez faire un tour sur ces projets :
Je vous invite également à visionner la vidéo de Clement Delafargue qui a fait une présentation sur le sujet en début d'année.
À partir de là on dispose d'une bonne base pour refaire le monde et accroître la flemme du développeur que l'on est en automatisant tout plein de tâches.