Atteindre le contenu

Créer une interface en ligne de commande avec NPM

Bower, Npm, Gulp, Git… En tant que développeur, le terminal est votre meilleur ami, et les interfaces en ligne de commande sont votre quotidien (en anglais « CLI », command line interface). Mais il n’en reste pas moins bon nombre de tâches répétitives, manuelles, laborieuses, qui vous agacent de plus en plus. Ne serait-il pas Ô combien agréable de pouvoir créer vos propres lignes de commandes pour automatiser tout cela? Eh bien c’est possible. Si si. Il existe plusieurs façons de le faire, mais nous allons nous intéresser à NPM, car je serais prêt à parier que vous avez déjà Node installé sur votre poste, et que vous parlez Javascript en dormant.

Dans cet article, nous allons couvrir le B.A.-BA de cette démarche, sur la base d’un exemple simple, mais d’autres suivront, dans lesquels nous verrons comment développer des outils un peu plus avancés.

Pour l’instant, donc, intéressons-nous à une commande qui permettrait de générer un nouveau projet selon votre architecture préférée. Car, on ne vas pas se mentir, n’y-a-t-il rien de plus agaçant que de refaire les même manips à chaque nouveau projet, et perdre ainsi plusieurs dizaine de minutes, avant même de coder la première ligne à véritable valeur ajoutée? Il existe certes des outils du marché qui le permettent déjà, à l’instar de Yeoman, mais vous allez voir que ce développement est très simple et vous permet vraiment d’avoir complètement la main sur le contenu et la configuration de ce modèle (ou template, boilerplate, starter-kit… appelez-le comme bon vous semble).

Allez, trève de blabla, et comme le dirait un certain D. T., sage parmi les sages, et fervent détracteur de la mégalomanie: « let’s make your workflows great again »!

1- Création et initialisation du package NPM

Commencez par créer le répertoire du projet, par exemple SimplXCLI, et lancer dans celui-ci l’initialisation NPM via votre terminal préféré, qui créera le manifest de votre package:

vous pouvez également envisager de créer un scope pour ce package

plus d’infos sur ce sujet ici.
(désolé, c’est dans la langue de Shakespeare, je n’ai pas trouvé de ressource en français qui soit aussi pertinente que la doc officielle de NPM… )

Et si vous êtes en train de créer un package qui sera utilisé en interne par votre équipe, sachez que vous pourrez aussi créer un package privé, mais cela nécessitera un compte payant.

Et nous voici donc avec un joli fichier package.json, qui devrait avoir à peu près cette tête:

 

2- Première commande

Il est désormais grand temps de passer aux choses sérieuses, et de créer un script à exécuter.

Créer un fichier index.js avec le code suivant:

le shebang de la première ligne est indispensable car ce script sera exécuté en ligne de commande, et nécessite donc cette directive d’interprétation. Plus d’infos ici.

Et ça marche ça? Essayons un petit:

Votre terminal devrait vous afficher ce qu’il pense de SimplX…! Et nous sommes bien d’accord avec lui…

Bon c’est bien joli tout ça, mais maintenant j’aimerais bien avoir une vraie commande qui en jette un peu plus que « node index.js ». Et la rendre accessible sur mon système de manière globale. Plaçons donc notre script dans un répertoire « bin », et indiquons à NPM quelle commande doit lui être associée, disons « simplx ». Dans package.json, rajouter:

Reste donc à indiquer à NPM de créer un lien symbolique depuis son répertoire de packages afin de faire connaître notre joli plugin à notre système, et donc rendre la commande exécutable dans le terminal, sans être nécessairement dans notre répertoire de développement.

(ça par contre, il faut le faire depuis ledit répertoire de développement, évidemment…). Notons que l’on pourrait ici également se contenter de faire un

mais il serait alors nécessaire de réitérer cette opération à chaque mise à jour du code, alors à quoi bon se compliquer la vie?

Reste plus qu’à tester tout ça, et à s’émerveiller bruyamment si possible, afin d’atirer l’attention des collègues, puis se gargariser un peu de ce doux moment de gloire. Si si. Ça ne mange pas de pain, et ça fait toujours plaisir.

et la magie devrait opérer, le terminal devrait toujours penser autant de bien de nous, et le faire savoir. Et devant les yeux ébahis de votre public en délire, vous pourrez également continuer à flamber un peu en exécutant cette même commande depuis n’importe quel répertoire… C’est bien de cela que Freddie parlait… It’s a kind of magic. Juré craché.

 

3- Et une commande qui ne serait pas totalement inutile? C’est possible?

Essayons désormais d’écrire une commande qui fait un peu plus qu’un simple console.log().

Pour les besoins de cet article, nous avons créé un template de projet extrêmement simple, que nous avons hébergé sur Github: https://github.com/simplx-fr/basic-html5-boil.

Évidemment l’intérêt de créer un plugin pour générer un projet aussi simple est très (NdlR: jamais d’euphémisme chez SimplX)  limité, mais devient beaucoup plus pertinent si vous avez une structure personnalisée complexe, pour Angular JS par exemple. Le cas échéant, il vous suffira de l’héberger vous aussi sur Github (ou équivalent), et de changer l’adresse du repository pour construire votre propre générateur de projet.

Comme nous sommes très contents de notre premier script et que nous ne voudrions vraiment SURTOUT pas le perdre, nous allons tout simplement créer une deuxième commande, liée à un nouveau fichier JS. (et mettre à jour le nom de la première commande, pour un peu plus de clarté). Pour cela, commençons par créer le fichier generator.js, dans le répertoire /bin/ toujours, puis mettons à jour package.json:

Dans generator.js, créons un script simple, afin de vérifier dans un premier temps que tout cela fonctionne:

puis essayons d’exécuter les deux commandes dans le terminal:

Magnifique. Commençons donc à créer le script qui va nous permettre de créer un nouveau projet à partir du template Github. Un petit « git clone » devrait faire l’affaire.

Pour exécuter une commande shell dans notre script, nous allons utiliser le package NPM shelljs

Dans generator.js, commençons par importer ce nouveau module

Puis appelons sa méthode exec() pour exécuter la commande git (cloner le projet, et le renommer en « new-project » par exemple)

generator.js ressemble donc désormais à cela:

Pour tester, rien de plus simple, placez vous dans le répertoire de votre choix, puis exécutez

Le répertoire du nouveau project devrait apparaître. C’est tout de même bien fait….

NB: si vos collègues sont toujours là et n’en n’ont pas encore marre de vous voir frimer, c’est le moment de briller encore un peu… C’est cadeau. On est comme ça chez SimplX.

 

4- Se protéger de l’erreur d’inattention… ou de la cuite de la veille…

Une dernière petite étape que je juge relativement importante, pour éviter de pousser votre travail futur sur ce projet dans le repository du template original, il peut être pertinent de supprimer la remote de base, « origin ». Pour ce faire, mettez à jour la commande dans generator.js:

 

5- Publier son oeuvre, fièrement

Si cela n’est pas encore fait, créez un compte sur npm, puis, depuis le répertoire de votre magnifique package, exécutez

Encore une fois, vous pourrez si vous le souhaitez vous affranchir de l’option « public », mais il vous faudra pour cela un compte payant.

Plus de détails sur la publication d’un package NPM ici.

 

6- Ou la conclusion a une douce odeur de victoire

Voilà. Vous venez de créer votre première CLI avec NPM. Champagne. Certes, l’intérêt des fonctionnalités implémentées ici reste encore assez limité, mais il ne s’agit que d’un point de départ, et les possibilités d’évolutions sont presque infinies. Nous verrons notamment dans de prochains articles comment rajouter des arguments à nos commandes (pour spécifier le nom du projet par exemple), générer de nouveaux fichiers dynamiquement (créer un contrôleur Angular par exemple), ou bien encore créer un formulaire en ligne de commande pour guider l’utilisateur dans l’utilisation du plugin….

Alors… happy coding, and stay tuned!

Commenter en premier

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *