Skip to content

📅 SAISON B Semaine 1 Épisode 1 - DĂ©couverte de Node.js

📚 Notions du jour

  • NodeJS, c’est quoi ?
  • Les modules natifs, ces objets bien pratiques qu’on rĂ©cupĂšre grĂące Ă  import
  • le module Readline

🌐 Node.js, C’est Quoi ?

Aujourd’hui, je plonge dans un nouveau monde : le backend avec Node.js ! Jusqu’à prĂ©sent, j’utilisais JavaScript pour crĂ©er des interfaces dynamiques dans le navigateur (grĂące Ă  Svelte). Mais Node.js, c’est JavaScript cĂŽtĂ© serveur ! 🚀

En résumé :

  • Node.js est un environnement d’exĂ©cution pour JavaScript, qui permet de lancer du code hors du navigateur (sur un serveur, par exemple).
  • Il est asynchrone et Ă©vĂ©nementiel, ce qui le rend idĂ©al pour les applications qui nĂ©cessitent des requĂȘtes rĂ©seau, des fichiers, ou des bases de donnĂ©es.

Pourquoi utiliser Node.js ?

  • Un seul langage (JavaScript) pour le frontend et le backend.
  • Une communautĂ© Ă©norme et des milliers de modules disponibles via npm (Node Package Manager).
  • Performant grĂące Ă  son modĂšle non-bloquant (parfait pour les applications en temps rĂ©el).

📩 Les Modules Natifs : Des Outils PrĂȘts Ă  l’Emploi

Node.js vient avec des modules natifs (ou built-in modules), qui permettent d’effectuer des tĂąches courantes sans installer de dĂ©pendances externes. On les importe avec la syntaxe import <module> from "node:<module>".

Voici une sélection des modules les plus utiles, avec des exemples concrets pour chacun.

Module Utilité
fs Interagir avec le systÚme de fichiers (lire/écrire des fichiers).
path Manipuler les chemins de fichiers (indĂ©pendamment du systĂšme d’exploitation).
os Interagir avec le Systùme d’Exploitation.
http CrĂ©er un serveur web ou faire des requĂȘtes HTTP.
events Gérer des événements personnalisés.
readline Lire des entrées utilisateur depuis la console (ligne par ligne).

📁 Le Module fs : Manipuler le Systùme de Fichiers

Exemples d’Utilisation :
  1. Lire un fichier :
// Import the 'fs' module to work with files
import fs from 'node:fs';

// Read a file asynchronously
fs.readFile('example.txt', 'utf8', (err, data) => {
  if (err) {
    console.error("Error reading file:", err);
    return;
  }
  console.log("File content:", data);
});
  1. Écrire dans un fichier :
import fs from 'node:fs';

try {
  fs.writeFileSync('file.txt', 'Hello, Node.js !');
  console.log("File written successfully!");
} catch (err) {
  console.error("File write error :", err);
}
  1. Lister les fichiers d’un dossier :
import fs from 'node:fs';

fs.readdir('.', (err, files) => {
  if (err) {
    console.error("Error :", err);
    return;
  }
  console.log("Files in the directory :", files);
});

Cas d’usage :

  • Sauvegarder des donnĂ©es utilisateur.
  • Lire des fichiers de configuration.
  • Traiter des logs ou des exports.

đŸ—ș Le Module path : GĂ©rer les Chemins de Fichiers

Le module path permet de manipuler les chemins de fichiers de maniĂšre cross-platform (compatible Windows, Linux, macOS). Plus besoin de se soucier des / ou \ !

Exemples d’Utilisation :
// Import the 'path' module to handle file paths
import path from 'node:path';

// Join path segments to create a cross-platform path
const filePath = path.join('folder', 'subfolder', 'file.txt');
console.log("Constructed path:", filePath);
// Output (on Unix): "folder/subfolder/file.txt"
// Output (on Windows): "folder\subfolder\file.txt"
  1. Construire un chemin absolu :
// Import the 'path' module to handle file paths
import path from 'node:path';

// Join path segments to create a cross-platform path
const fullPath = path.join(__dirname, 'directory', 'file.txt');
console.log("Full path:", fullPath);
// Output (on Unix) : "/absolute/path/directory/file.txt"
// Output (on Windows) : "C:\absolute\path\directory\file.txt"
  1. Extraire le nom de fichier d’un chemin :
const fileName = path.basename('/path/to/file.txt');
console.log("File name:", fileName); // "file.txt"
  1. RĂ©cupĂ©rer l’extension d’un fichier :
const ext = path.extname('file.txt');
console.log("Extension:", ext); // ".txt"

Cas d’usage :

  • Construire des chemins dynamiques dans une application.
  • Valider ou parser des chemins utilisateur.
  • Évite les problĂšmes de compatibilitĂ© entre Windows, Linux et macOS.

🌍 Le Module os : Interagir avec le Systùme d’Exploitation

Le module os fournit des informations sur le systĂšme d’exploitation et l’environnement d’exĂ©cution. IdĂ©al pour adapter le comportement de votre application en fonction de la plateforme.

Exemples d’Utilisation :
  1. RĂ©cupĂ©rer le systĂšme d’exploitation :
import os from 'node:os';

console.log("OS:", os.platform());
// "linux", "win32", "darwin" (macOS), etc.
  1. Connaütre l’architecture du processeur :
console.log("Architecture :", os.arch());
// "x64", "arm64", etc.
  1. Obtenir des informations sur la mémoire :
console.log("Memory:", os.totalmem() / 1024 / 1024, "Mb");
console.log("Free memory :", os.freemem() / 1024 / 1024, "Mb");
  1. Récupérer les interfaces réseau :
console.log("Networks:", os.networkInterfaces());
// Print IP addresses, MAC addresses, etc.
  1. ConnaĂźtre le rĂ©pertoire personnel de l’utilisateur :
console.log("User folder:", os.homedir());
// "/home/user" (Linux/macOS) or "C:\Users\user" (Windows)

Cas d’usage :

  • Adapter le comportement de l’application en fonction de l’OS (ex: chemins de fichiers, commandes systĂšme).
  • Optimiser les performances en fonction des ressources disponibles (CPU, mĂ©moire).
  • Personnaliser l’expĂ©rience utilisateur (ex: langue, rĂ©pertoire de sauvegarde).

🔠 Le Module readline : Lire des EntrĂ©es Utilisateur en Console

Le module readline permet de lire des entrĂ©es utilisateur depuis le terminal, ligne par ligne. C’est parfait pour crĂ©er des interfaces en ligne de commande (CLI) ou des scripts interactifs.


📖 Exemple : Un Script Interactif avec readline

// Import the 'readline' module to read user input
import * as readline from 'node:readline';

// Create an interface to read from stdin and write to stdout
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

// Ask the user a question
rl.question("What's your name? ", (name) => {
  console.log(`Hello, ${name}!`);

  // Close the interface
  rl.close();
});

Explications :

  1. readline.createInterface : CrĂ©e une interface pour lire depuis stdin (l’entrĂ©e standard) et Ă©crire vers stdout (la sortie standard).
  2. rl.question : Pose une question Ă  l’utilisateur et attend sa rĂ©ponse.

Cas d’usage :

  • CrĂ©er un menu interactif en ligne de commande.
  • Automatiser des tĂąches avec des questions/rĂ©ponses (ex: configuration d’un projet).

💡 Pourquoi Utiliser les Modules Natifs ?

  1. Pas de dépendances externes : Moins de risques de vulnérabilités ou de conflits de versions.
  2. Performances optimisées : Ces modules sont compilés avec Node.js, donc trÚs rapides.
  3. Portabilité : Fonctionnent sur tous les systÚmes (Windows, Linux, macOS).
  4. Documentation officielle : Bien documentĂ©s et maintenus par l’équipe Node.js.

💡 Ce Que J’ai Appris Aujourd’hui

  1. Node.js Ă©tend JavaScript au backend : Plus besoin d’un navigateur pour exĂ©cuter du JS !
  2. Les modules natifs sont des outils puissants pour des tùches courantes (fichiers, chemins, entrées/sorties).
  3. readline permet de créer des scripts interactifs en ligne de commande, idéal pour des outils CLI ou des prototypes rapides.

⌚ Challenge du jour : "Hit MO'chine" – Un Outil en Ligne de Commande avec Node.js !


đŸŽ€ PrĂ©sentation du Challenge

Vous vous souvenez de cette émission des années 90 qui présentait le classement du Hit Parade ?
Aujourd’hui, on va crĂ©er un outil en ligne de commande (CLI) pour Charlu et Lili, deux prĂ©sentateurs fictifs qui veulent afficher les 10 premiĂšres entrĂ©es du hit-parade. L’objectif est de rĂ©aliser un script Node.js qui interagit avec l’utilisateur via la console, en utilisant le systĂšme Ă©vĂ©nementiel de Node.js et le module readline.

Fonctionnalités demandées :

  1. Afficher un message d’accueil : "Que souhaitez-vous faire ?".
  2. Répondre à 3 commandes :

  3. chante : Affiche un message personnalisé.

  4. classement : Affiche les 10 premiĂšres entrĂ©es du Top 50 (Ă  partir d’un tableau fourni).
  5. quitter : Ferme le programme.

  6. Bonus : Ajouter une commande position n pour afficher l’entrĂ©e Ă  la position n du classement (ex: position 5 affiche le Hit en position 5 du classement).


🎯 Objectif du Challenge

Créer un script interactif en Node.js qui :

  • Utilise le module readline pour lire les entrĂ©es utilisateur.
  • GĂšre des Ă©vĂ©nements pour rĂ©pondre aux commandes.
  • Affiche des donnĂ©es dynamiques (le classement du Top 50).

Les données nous sont fournies sous forme de tableau JavaScript nommé hitParade


📌 Étapes RĂ©alisĂ©es

1ïžâƒŁ Initialisation du Projet et Import des Modules

Objectif : Dans le fichier index.mjs déjà fournit, importer les modules nécessaires (readline).

Mon code :

index.mjs
// Import the 'readline' module and 'stdin', 'stdout' processes to handle user input
import { stdin, stdout } from "node:process";
import * as readline from "node:readline";

// Create the readline interface
const rl = readline.createInterface({
  input: stdin,
  output: stdout
});

2ïžâƒŁ Afficher le Message d’Accueil et GĂ©rer les Commandes

Objectif : Demander Ă  l’utilisateur "Que souhaitez-vous faire ?" et Ă©couter ses rĂ©ponses pour dĂ©clencher les actions correspondantes.

Mon code :

index.mjs
/**
 * The main question prompt displayed to the user.
 * @type {string}
 */
const question = `Que souhaitez-vous faire ?
- Tapez 'chante' pour que Charlu & Lili chantent le générique de Hit MO'chine,
- Tapez 'classement' pour afficher le classement des 10 premiers Hits du Top 50,
- Tapez 'position <n>' oĂč <n> reprĂ©sente la position de la chanson que vous souhaitez afficher (un nombre compris entre 1 et 10).
- Tapez 'quitter' pour quitter.
`;

/**
 * The jingle played when the user selects 'chante'.
 * @type {string}
 */
const jingle = "Je m'appelle Charlu, je m'appelle Lili, vous ĂȘtes chez O'clock !";

/**
 * Initializes the readline interface and handles user input events.
 */
const rl = readline.createInterface({ input: stdin, output: stdout });

// Display the main question prompt to the user
console.log(question);

/**
 * Event listener for each line of user input.
 * Handles different commands: 'chante', 'classement' and 'quitter'.
 */
rl.on('line', (userAnswer) => {
  switch(userAnswer.toLowerCase()) {
    // If the user input is equal to 'chante'
    case "chante":
      // Display the jingle into the console
      console.log(`\n${jingle}\n`);
      break;
    // If the user input is equal to 'classement'
    case "classement":
      // Display the Hit Parade ranking into the console
      console.log(`\nVoici le classement des 10 premiers Hits du Top 50 :`);
      hitParade.forEach((element, index) => {
        console.log(`${index + 1}. ${element}`);
      });
      console.log("");
      break;
    // If the user input is equal to 'quitter'
    case "quitter":
      // Display a goodbye message
      console.log("\nAu revoir !");
      rl.close(); // Close properly the readline handler
      return; // Stop the function
    // Else, display an error message
    default:
      console.error("\nJe n'ai pas compris votre demande.")
  }
  // Re-display the question prompt after each command
  console.log(question);
});

3ïžâƒŁ Bonus : afficher l’entrĂ©e Ă  la position n du classement

Bonus : Commande position n :

  • Utilisation des expressions rĂ©guliĂšres pour dĂ©tecter la commande. Lors de la correction, l'enseignant a utilisĂ© la mĂ©thode startsWith()mais j'ai voulu essayer les expressions rĂ©guliĂšres pour m'entraĂźner.
  • Extraction du numĂ©ro avec split().
  • Recherche de l’entrĂ©e correspondante dans le tableau hitParade.

Mon code final avec la gestion de la position 'n' :

index.mjs
// Import required modules from Node.js
import { stdin, stdout } from "node:process";
import * as readline from "node:readline";

/**
 * Array containing the top 10 songs in the hit parade, ordered from first to last.
 * @type {string[]}
 */
const hitParade = [
  `Jain - Come`,
  `Matt Simons - Catch & Realease`,
  `Twety One Pilots - Stressed Out`,
  `Justin Bieber - Love Yourself`,
  `Kids United - On écrit sur les murs`,
  `Rihanna - Work`,
  `Julian Perretta - Miracle`,
  `Yall - Hundred Miles`,
  `Kendji Girac - No Me MirĂšs MĂ s`,
  `Feder - Blind (feat. Emmi)`
];


/**
 * The main question prompt displayed to the user.
 * @type {string}
 */
const question = `Que souhaitez-vous faire ?
- Tapez 'chante' pour que Charlu & Lili chantent le générique de Hit MO'chine,
- Tapez 'classement' pour afficher le classement des 10 premiers Hits du Top 50,
- Tapez 'position <n>' oĂč <n> reprĂ©sente la position de la chanson que vous souhaitez afficher (un nombre compris entre 1 et 10).
- Tapez 'quitter' pour quitter.
`;

/**
 * The jingle played when the user selects 'chante'.
 * @type {string}
 */
const jingle = "Je m'appelle Charlu, je m'appelle Lili, vous ĂȘtes chez O'clock !";

/**
 * Extracts the rank number from the user's input string.
 * @param {string} userInput - The input string from the user (e.g., "position 3").
 * @returns {number} The rank number requested by the user.
 */
function getRankFromUserInput(userInput) {
  const positionSplit = userInput.split(" ");
  return Number(positionSplit[1]);
}

/**
 * Retrieves the song from the hit parade based on the user's requested rank.
 * @param {string} position - The input string containing the rank (e.g., "position 3").
 * @returns {string} The song at the requested rank.
 */
function getHitFromRank(position) {
  const rank = getRankFromUserInput(position);
  const rankIndex = rank - 1;
  return hitParade[rankIndex];
}

/**
 * Initializes the readline interface and handles user input events.
 */
const rl = readline.createInterface({ input: stdin, output: stdout });

// Display the main question prompt to the user
console.log(question);

/**
 * Event listener for each line of user input.
 * Handles different commands: 'chante', 'classement', 'position <n>', and 'quitter'.
 */
rl.on('line', (userAnswer) => {
  // Check if the user requested a specific position
  if (userAnswer.match(/^position [1-9]$|^position 10$/)) {
    const hitRank = getHitFromRank(userAnswer);
    console.log(`Hit classé n°${getRankFromUserInput(userAnswer)} : ${hitRank}`);
  } else {
    switch(userAnswer.toLowerCase()) {
      // If the user input is equal to 'chante'
      case "chante":
        // Display the jingle into the console
        console.log(`\n${jingle}\n`);
        break;
      // If the user input is equal to 'classement'
      case "classement":
        // Display the Hit Parade ranking into the console
        console.log(`\nVoici le classement des 10 premiers Hits du Top 50 :`);
        hitParade.forEach((element, index) => {
          console.log(`${index + 1}. ${element}`);
        });
        console.log("");
        break;
      // If the user input is equal to 'quitter'
      case "quitter":
        // Display a goodbye message
        console.log("\nAu revoir !");
        rl.close(); // Close properly the readline handler
        return; // Stop the function
      // Else, display an error message
      default:
        console.error("\nJe n'ai pas compris votre demande.")
    }
  }
  // Re-display the question prompt after each command
  console.log(question);
});

đŸ–„ïž Rendu Final du Programme

Rendu final du challenge du jour.


💡 Ce Que J’ai Appris avec ce Challenge

  1. Utiliser readline pour créer des interfaces en ligne de commande interactives.
  2. Gérer les entrées utilisateur de maniÚre asynchrone avec des callbacks.
  3. Découper et analyser des commandes (ex: position 5) pour extraire des informations.
  4. Fermer proprement un programme avec rl.close().