Apprenez à créer un outil CLI (Command Line Interface) de gestionnaire de tâches avec Node.js et MongoDB. Ce didacticiel couvrira les bases de la création d'un outil CLI, du stockage des données dans MongoDB et de la mise en œuvre des opérations CRUD de base.
Bonjour à tous 👋 Dans ce tutoriel, vous apprendrez à créer un outil simple Task Manager CLI (Command Line Interface). Cela signifie que vous pouvez utiliser des commandes pour créer, afficher, mettre à jour ou supprimer vos tâches.
Nous allons construire cet outil CLI en utilisant NodeJS . Nous utiliserons également MongoDB comme base de données pour stocker toutes nos tâches. Enfin, nous utiliserons quelques packages utiles de npm :
Avant de plonger dans le vif du sujet, je veux que vous sachiez que vous pouvez trouver le code complet de ce projet sur GitHub. Si vous n'êtes pas sûr de quelque chose dans le code, vous pouvez toujours vous y référer à la version finale.
Configuration du projet
Bienvenue dans la première section de ce manuel ! Ici, nous allons mettre en place notre projet.
Cela implique quelques étapes simples : créer un nouveau répertoire, configurer le package.jsonfichier et installer les packages npm nécessaires tels que chalk, Inquirer, Commander et d'autres dont nous parlerons bientôt. Nous organiserons également le projet en créant des dossiers.
Avant de plonger dans le vif du sujet, assurons-nous que NodeJS est installé sur votre système. Vous pouvez obtenir la dernière version LTS sur ce site Web : https://nodejs.org/en .
Pour vérifier si Node est correctement installé, tapez cette commande : node --version. Si vous voyez un numéro de version, vous êtes prêt ! Sinon, vous devez résoudre les erreurs.
Une fois NodeJS opérationnel, créez un nouveau dossier nommé « todo ». Vous pouvez utiliser votre éditeur de code préféré (je préfère Visual Studio Code) ou suivre ces étapes dans votre terminal :
La première étape consiste à configurer le package.jsonfichier. Mais ne vous inquiétez pas de le faire manuellement. Vous pouvez gagner du temps en utilisant cette commande :
npm init --yes
Une fois cette étape réalisée, passons à l'étape suivante et récupérons toutes les choses nécessaires à notre projet.
Pour construire ce projet, nous aurons besoin de quelques packages. Exécutez simplement cette commande simple pour les obtenir tous :
npm i commander inquirer chalk ora mongoose nanoid dotenv
Avant de continuer, apportons une petite modification au package.jsonfichier. Supprimez cette ligne : "main": "index.js", et ajoutez ces deux lignes à la place :
"exports": "./index.js",
"type": "module",
Avec ces changements, nous convertissons notre projet de modules CommonJS en modules ES. Cela signifie que nous utiliserons importà la place de require()pour introduire des modules, et exportà la place de module.exportspour partager des éléments entre fichiers.
Maintenant, organisons notre projet en mettant en place une structure de dossiers intelligente. Cela signifie que nous créerons des dossiers pour contenir soigneusement nos fichiers JavaScript. Cette étape est vraiment importante. Cela rend les choses faciles à gérer et se développe en douceur.
Nous créons 3 dossiers et 2 fichiers dans le dossier principal :
Premier dossier : commands . Dans ce dossier, vous allez créer 4 fichiers. Les noms des fichiers et la description du code qu'ils contiendront sont mentionnés ci-dessous :
Deuxième dossier : db . Dans ce dossier, ajoutez un fichier nommé connectDB.js. Ce fichier contiendra le code pour se connecter à la base de données MongoDB et se déconnecter en cas de besoin.
Troisième dossier : schema . À l’intérieur, créez un fichier nommé TodoSchema.js. Ce fichier stocke le schéma et le modèle Mongoose. Fondamentalement, un plan pour nos tâches, voilà à quoi ressembleront nos tâches.
Premier fichier : .env . Créez ce fichier dans le répertoire racine/dossier principal du projet. C'est ici que vous placerez votre chaîne de connexion MongoDB.
Deuxième fichier : Créez le index.jsfichier dans le répertoire racine lui-même qui servira de point d'entrée à notre projet. C'est comme la façade du projet – là où tout commence.
Une fois que nous avons terminé, les dossiers de votre projet devraient ressembler à ceci :
Structure des dossiers du projet Comment se connecter à la base de données
Maintenant que vous avez mis en place le projet avec succès, il est temps de passer à la partie passionnante.
Pour garder une trace de toutes nos tâches, nous avons besoin d’un endroit pour les stocker. C'est là qu'intervient MongoDB Atlas. C'est comme un service spécial qui gère les bases de données pour nous. La meilleure partie? Vous pouvez commencer à l’utiliser gratuitement (aucune carte de crédit requise).
Pour vous y connecter, tout ce dont vous avez besoin est ce qu'on appelle une chaîne de connexion. Si MongoDB Atlas est nouveau pour vous, ne vous inquiétez pas. Consultez cet article facile à suivre : Tutoriel MongoDB Atlas - Comment démarrer . Il vous donne juste assez d'informations pour commencer à utiliser Atlas. Une fois que vous aurez terminé, vous saurez comment obtenir ce dont vous avez besoin, y compris la chaîne de connexion.
Une fois que vous avez cette chaîne de connexion, créez un nouvel élément appelé « variable d'environnement ». C'est comme un code secret utilisé par votre projet. Ouvrez le .envfichier et créez une ligne comme celle-ci : MONGO_URI=. Après le =, entrez votre chaîne de connexion.
N'oubliez pas : remplacez <password>par votre mot de passe réel et <username>par le nom d'utilisateur de votre administrateur de base de données dans la chaîne de connexion. Ajoutez également todosbetween /?dans la chaîne. Lorsque vous avez terminé, votre .envfichier devrait ressembler à ceci :
MONGO_URI=mongodb+srv://<username>:<password>@cluster0.k5tmsld.mongodb.net/todos?retryWrites=true&w=majority
Passons maintenant au code qui connecte notre outil à la base de données MongoDB. Ouvrez le ./db/connectDB.jsfichier et écrivons du code pour établir cette connexion.
Tout d’abord, nous devons importer le dotenvpackage que nous avons récupéré plus tôt lors de la configuration du projet et appeler la config()méthode sur dotenv. Cela nous aide à charger les variables d'environnement à partir du .envfichier. Voici comment procéder :
import dotenv from 'dotenv'
dotenv.config()
Ensuite, nous souhaitons importer quelques packages supplémentaires que nous utiliserons ici. Ce sont mongoose, oraetchalk :
import mongoose from 'mongoose'
import ora from 'ora'
import chalk from 'chalk'
Remarque : mongoose est une bibliothèque de modélisation de données objet (ODM) pour MongoDB. Il fournit une abstraction de niveau supérieur facilitant l'ajout, la lecture, la mise à jour et la suppression d'éléments de la base de données MongoDB.
Passons maintenant à l’action réelle. Nous définirons ici deux fonctions : connectDB()et disconnectDB().
La connectDB()fonction contiendra le code pour aider à connecter notre application NodeJS à la base de données M0ngoDB à l'aide de mongoose. C'est comme un appel téléphonique qui les connecte. Si nous n'établissons pas d'abord une connexion, notre application ne pourra pas interagir avec la base de données et effectuer les différentes opérations CRUD.
La disconnectDB()fonction fait le contraire. C'est comme raccrocher le téléphone une fois que notre application a fini de parler à la base de données. Si nous ne nous déconnectons pas, c'est comme si nous maintenions l'appel même après avoir terminé.
Ne pas nous déconnecter de la base de données une fois que nous avons fini d'interagir avec elle pourrait entraîner des fuites de ressources. Cela peut entraîner un ralentissement ou un blocage de votre application au fil du temps.
Laissez-moi vous montrer le code des deux fonctions :
export async function connectDB(){
try {
const spinner = ora('Connecting to the database...').start()
await mongoose.connect(process.env.MONGO_URI)
spinner.stop()
console.log(chalk.greenBright('Successfully connected to database!!!'))
} catch (error) {
console.log(chalk.redBright('Error: '), error);
process.exit(1)
}
}
export async function disconnectDB(){
try {
await mongoose.disconnect()
console.log(chalk.greenBright('Disconnected from the database.'))
} catch(err) {
console.log(chalk.redBright('Error: '), error);
process.exit(1)
}
}
Cela fait beaucoup de code à digérer en même temps, alors laissez-moi vous expliquer ceci :
Dans la connectDB()fonction, la ligne mongoose.connect(process.env.MONGO_URI)nous aide à nous connecter à la base de données à l'aide de la chaîne de connexion.
Vous vous souvenez du .envfichier ? Nous utilisons ses informations ici. Pour charger la MONGO_URIvariable, nous utilisons le dotenvpackage et appelons la config()fonction, puis nous pouvons y accéder en utilisant process.env.MONGO_URI.
Puisque mongoose.connect()renvoie une promesse, nous utilisons le awaitmot-clé qui le précède pour nous assurer de ne procéder que lorsque cette promesse renvoyée est résolue.
Il est possible de rencontrer des erreurs lors de l'exécution de ce code, nous avons donc enveloppé l'intégralité du code dans un try...catch()bloc pour nous assurer que toutes les erreurs qui apparaissent sont traitées correctement dans le catch()bloc.
Le orapackage nous aide à afficher un spinner pendant que nous nous connectons à la base de données. Une fois connecté avec succès, nous arrêtons le spinner et affichons un message de joie en vert en utilisant chalk.
Si vous remarquez, nous faisons la même chose dans la disconnectDB()fonction. Mais au lieu de nous connecter, nous nous déconnectons de la base de données en utilisant mongoose.disconnect(). Nous l'enveloppons dans un bloc try-catch similaire, et encore une fois nous affichons des messages colorés en utilisant chalk.
Nous utilisons exportavant ces fonctions pour permettre à d'autres parties du projet de les utiliser. N'oubliez pas d'ajouter ces deux lignes temporaires à la fin du fichier pour l'instant :
connectDB()
disconnectDB()
Maintenant, vous pouvez exécuter le connectDB.jsfichier à l'aide de la commande : node ./db/connectDB.jset attendez-vous à voir ceci dans la console :
Sortie vue sur le terminal lorsque connectDB.jsle fichier est exécuté. Il montre comment notre code se connecte avec succès à la base de données et s'en déconnecte, affichant les messages de console appropriés lorsque nous invoquons les méthodes connectDB()et .disconnectDB()
La connexion à la base de données est une grande étape, mais vous faites de grands progrès ! Avant de continuer, assurez-vous de supprimer les 2 lignes que vous avez ajoutées à la fin car elles ont été ajoutées uniquement pour vérifier si nos fonctions de connexion et de déconnexion fonctionnent comme prévu.
Comment créer un modèle de mangouste
Un modèle Mongoose est comme un outil qui nous aide à communiquer avec la base de données. Avec lui, nous pouvons facilement effectuer des choses comme ajouter, lire, mettre à jour et supprimer des tâches. C'est comme un assistant utile qui comprend comment communiquer avec la base de données.
Pour créer ce modèle, nous avons besoin de quelque chose appelé un schéma. Il définit essentiellement à quoi devrait ressembler chaque tâche. Considérez-le comme un plan ou un ensemble d'instructions qui guident la manière dont chaque tâche est créée, les informations qu'elle doit contenir et la manière dont ces informations sont organisées. C'est comme définir des règles sur la façon dont nos tâches sont stockées dans la base de données.
Nous allons construire ce schéma dans le ./schema/TodoSchema.jsfichier. Ouvrez-le et plongeons-y. Tout d’abord, nous avons besoin de deux outils spéciaux : mongooseet nanoid. Nous utiliserons nanoidpour créer des identifiants courts et uniques pour chaque tâche.
Tapez ces lignes pour importer les outils :
import mongoose from 'mongoose'
import {nanoid} from 'nanoid'
Maintenant, nous utilisons la mongoose.Schema()méthode pour créer notre schéma. Voici le code correspondant :
const TodoSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
detail: {
type: String,
required: true,
trim: true
},
status: {
type: String,
required: true,
enum: ['completed', 'pending'],
default: 'pending',
trim: true
},
code: {
type: String,
required: true,
default: 'code',
trim: true
}
}, {timestamps: true})
Toute tâche créée à l'aide de ce schéma aura les propriétés suivantes :
Nous avons réussi à définir notre schéma – mais vous vous demandez peut-être si la codepropriété était censée être unique pour chaque tâche. Actuellement, il stocke la même valeur, c'est-à-dire le « code », pour chaque tâche. Ne vous inquiétez pas, nous allons résoudre ce problème. Ajoutez ce code à la fin :
TodoSchema.pre('save', function(next){
this.code = nanoid(10)
next()
})
Ici, cela TodoSchema.pre('save', function(){....})nous aide à définir un crochet/une fonction de pré-enregistrement qui s'exécute à chaque fois avant qu'une tâche ne soit enregistrée dans la base de données.
À l'intérieur de la fonction, nous utilisons nanoid(10)pour créer un identifiant unique de 10 caractères pour la tâche et mettons cet identifiant généré dans le codechamp de la tâche (nous pouvons en fait accéder à n'importe quelle propriété/champ de la tâche en utilisant le thismot-clé).
La dernière ligne de code : next()indique essentiellement à l'ordinateur que nous avons terminé et qu'il peut enfin enregistrer le document maintenant. Avec cela, nous générons un identifiant unique pour chaque tâche créée à l'aide du nanoidpackage.
Enfin, nous allons créer un Todosmodèle en utilisant ce TodoSchemaplan et l'exporter. C'est ainsi:
const Todos = mongoose.model('Todos', TodoSchema)
export default Todos
Et voilà ! Nous avons construit notre schéma et notre modèle. Passons maintenant à la section suivante de ce didacticiel.
Comment travailler sur les opérations CRUD
Félicitations pour avoir suivi avec succès jusqu'ici. Jusqu'à présent, nous avons fait 3 choses :
Ensuite, nous travaillerons sur les différentes opérations CRUD telles que la création, la lecture, la mise à jour et la suppression des tâches de notre base de données.
Commençons maintenant par créer des tâches dans notre projet. Au début, j'avais prévu un processus simple dans lequel vous ajoutez une tâche à la base de données à la fois. Cela signifie que lorsque vous demandez à l'outil de créer une tâche, il vous demande une fois les détails de la tâche, comme le nom et la description, puis enregistre la tâche.
Mais ensuite j’ai réalisé : que se passe-t-il si quelqu’un souhaite ajouter rapidement de nombreuses tâches ? Le faire un par un n’est pas cool. Il y a deux problèmes :
Ces problèmes ne sont pas amusants du tout ! Pour résoudre ce problème, nous avons besoin d'un moyen d'ajouter plusieurs tâches en une seule fois. Voici comment nous allons procéder :
Après avoir saisi le nom et la description de la tâche, nous vous demanderons si vous souhaitez ajouter d'autres tâches. Si vous saisissez oui, nous poursuivons le processus depuis le début (en vous demandant de saisir à nouveau le nom et la description de la tâche suivante). Mais si vous entrez non, le processus de pose de questions s'arrêtera et toutes les tâches saisies seront enregistrées ensemble dans la base de données. De cette façon, vous pouvez créer de nombreuses tâches sans avoir à les exécuter une par une. Il s’agit avant tout de rendre les choses fluides pour vous.
Nous allons écrire du code dans le ./commands/addTask.jsfichier. C'est là que la magie opère. Décomposons-le étape par étape :
Tout d’abord, nous importons les packages et fonctions nécessaires que nous avons créés précédemment. Vous pouvez ajouter ces lignes de code pour ce faire :
import inquirer from "inquirer";
import { connectDB, disconnectDB } from '../db/connectDB.js'
import Todos from "../schema/TodoSchema.js";
import ora from "ora";
import chalk from "chalk";
Maintenant, nous créons une fonction asynchrone appelée input()pour recueillir le nom et les détails de la tâche auprès de l'utilisateur. Voici comment ça se passe :
async function input(){
const answers = await inquirer.prompt([
{ name: 'name', message: 'Enter name of the task:', type: 'input' },
{ name: 'detail', message: 'Enter the details of the task:', type: 'input' },
])
return answers
}
En termes simples, input()permet inquirerde demander à l'utilisateur le nom et les détails de la tâche. Les réponses sont ensuite renvoyées sous forme d'objet.
Mais attendez, vous vous demandez peut-être ce qui inquirer.prompt()se passe. C'est une méthode du inquirerpackage qui pose des questions et attend des réponses. Vous fournissez un tableau d'objets de question, chacun contenant des détails tels que le message à afficher à l'utilisateur et le type de question. La fonction renvoie une promesse, nous attendons donc awaitles réponses de l'utilisateur qui sont renvoyées sous forme d'objet.
Voici { name: 'name', message: 'Enter name of the task:', type: 'input' }la première question qui sera posée à l’utilisateur. La messagepropriété contient la question qui sera affichée à l'utilisateur. Dans notre cas, il s'agit de : Enter the name of the task. L'utilisateur sera invité à saisir du texte (une chaîne), puisque cette question est de type: 'input'. Cela name: 'name'signifie que la réponse de l'utilisateur à cette question sera attribuée à une propriété nommée – namedans l'objet de la réponse.
L'objet suivant est la deuxième question qui sera posée à l'utilisateur. Dans ce cas, un message s'affichera dans le terminal : Enter the details of the tasket la réponse de l'utilisateur sera affectée à une propriété appelée detaildans l'objet de la réponse.
Pour voir comment fonctionne le code ci-dessus, vous pouvez ajouter ces 2 lignes de code à la fin du fichier :
const output = await input()
console.log(output)
Maintenant, enregistrez le fichier et exécutez le code à l'aide de la commande : node ./commands/addTask.js. Voici ce que vous verrez lorsque vous exécuterez le code :
Sortie vue sur le terminal lorsque nous invoquons simplement la input()méthode et exécutons le code. Il montre comment inquirer.jsrenvoie les réponses de l'utilisateur après le processus de pose de questions.
Nous pouvons maintenant procéder au reste du code et vous pouvez supprimer les 2 dernières lignes que vous venez d'ajouter.
Créons maintenant une fonction nommée askQuestions()pour rassembler plusieurs tâches. Voici à quoi ça ressemble :
const askQuestions = async() => {
const todoArray = []
let loop = false
do{
const userRes = await input()
todoArray.push(userRes)
const confirmQ = await inquirer.prompt([{ name: 'confirm', message: 'Do you want to add more tasks?', type: 'confirm' }])
if(confirmQ.confirm){
loop = true
} else {
loop = false
}
} while(loop)
return todoArray
}
Dans askQuestions(), nous mettons en place une boucle qui continue de demander des tâches jusqu'à ce que l'utilisateur décide d'arrêter. Nous rassemblons chaque tâche de l'utilisateur en appelant la input()fonction, et la réponse de l'utilisateur renvoyée est transmise au fichier todoArray.
Ensuite, nous demandons si l'utilisateur souhaite ajouter d'autres tâches à l'aide d'une question de confirmation. S'ils disent oui, nous passons loopà trueet la boucle continue – sinon, loopcela devient falseet la boucle se termine. Enfin, nous renvoyons le tableau des tâches, c'est-à-dire todoArray.
Vous pouvez tester cela en ajoutant ces lignes de code à la fin du fichier :
const output = await askQuestions()
console.log(output)
Lorsque vous exécutez le fichier en utilisant node ./commands/addTask.js, vous verrez un résultat similaire à celui que vous voyez ici :
Sortie vue sur le terminal lorsque nous invoquons la askQuestions()méthode et exécutons le code. Il affiche le tableau de tâches renvoyées par la méthode lorsque l'utilisateur ne souhaite pas continuer à ajouter d'autres tâches.
Nous y sommes presque! Avant de continuer, n'oubliez pas de supprimer les 2 dernières lignes que vous venez d'ajouter. Après avoir fait cela, passons à autre chose.
Jusqu’à présent, nous avons réussi à collecter toutes les tâches que l’utilisateur souhaite créer.
Maintenant, définissons la dernière pièce du puzzle : la addTask()fonction. Cette fonction rassemble le tout et complète le processus de création de tâches. Voici le code complet :
export default async function addTask() {
try {
// calling askQuestions() to get array of todo's
const userResponse = await askQuestions()
// connecting to the database
await connectDB()
// Displaying a spinner with the following text message using ora
let spinner = ora('Creating the todos...').start()
// looping over every todo in the userResponse array
// and saving each todo in the database
for(let i=0; i<userResponse.length; i++){
const response = userResponse[i]
await Todos.create(response)
}
// Stopping the spinner and displaying the success message
spinner.stop()
console.log(
chalk.greenBright('Created the todos!')
)
// disconnecting the database
await disconnectDB()
} catch (error) {
// Error Handling
console.log('Something went wrong, Error: ', error)
process.exit(1)
}
}
La addTask()fonction commence par appeler la askQuestions()fonction pour rassembler le tableau de tâches et l'attribuer à la userResponsevariable. Ensuite, il se connecte à la base de données à l'aide de connectDB(), affiche une double flèche utilisant orapour montrer le processus de création de tâche, parcourt chaque tâche du tableau et l'enregistre dans la base de données à l'aide de Todos.create(response).
Une fois que toutes les tâches sont enregistrées, le spinner s'arrête, un message de réussite s'affiche, puis il se déconnecte de la base de données à l'aide de disconnectDB().
L'intégralité du code est enveloppée dans un try...catchbloc pour gérer correctement les erreurs potentielles.
Avec ce code, vous avez terminé le processus de création de tâches. Bon travail! Il s’agissait probablement du morceau de code le plus complexe de tout le projet. Les opérations futures telles que les tâches de lecture, de suppression et de mise à jour seront assez simples et faciles en comparaison. Cela dit, passons à l'exécution de l'opération de lecture.
Nous allons maintenant explorer comment lire les tâches de la base de données MongoDB. Le processus est simple et je vais vous guider à travers l'intégralité du code du ./commands/readTask.jsfichier :
Commençons par importer les packages et fonctions nécessaires au début du fichier :
// Importing packages and functions
import { connectDB, disconnectDB } from '../db/connectDB.js'
import Todos from '../schema/TodoSchema.js'
import chalk from 'chalk'
import ora from 'ora'
Maintenant, définissons une fonction asynchrone nommée readTask()qui encapsule la logique de lecture des tâches. La fonction entière est enveloppée dans un bloc try...catch pour gérer les erreurs potentielles :
export default async function readTask(){
try {
// connecting to the database
await connectDB()
// starting the spinner
const spinner = ora('Fetching all todos...').start()
// fetching all the todos from the database
const todos = await Todos.find({})
// stopping the spinner
spinner.stop()
// check if todos exist or not
if(todos.length === 0){
console.log(chalk.blueBright('You do not have any tasks yet!'))
} else {
todos.forEach(todo => {
console.log(
chalk.cyanBright('Todo Code: ') + todo.code + '\n' +
chalk.blueBright('Name: ') + todo.name + '\n' +
chalk.yellowBright('Description: ') + todo.detail + '\n'
)
})
}
// disconnect from the database
await disconnectDB()
} catch (error) {
// Error Handling
console.log('Something went wrong, Error: ', error)
process.exit(1)
}
}
readTask()
Maintenant, décomposons le code étape par étape :
Dans la dernière ligne de code, nous appelons la readTask()fonction. Ceci est uniquement à des fins de test et vous pouvez supprimer cette ligne comme indiqué.
Pour exécuter le code, utilisez la commande : node ./commands/readTask.js. Lorsque vous exécutez ceci, vous verrez quelque chose de similaire au résultat affiché ici :
Remarque : j'avais déjà créé des tâches aléatoires. Ainsi, lorsque j'exécute le readTask.jsfichier, je vois ceci dans mon terminal :
Sortie vue sur le terminal lorsque readTask.jsle fichier est exécuté. Il montre comment le code lit avec succès toutes les tâches de la base de données et les imprime dans le terminal.
Avant de continuer, n'oubliez pas de supprimer la dernière ligne de code du readTask.jsfichier car nous n'en aurons plus besoin à l'avenir.
Avec ce code, vous avez implémenté avec succès la fonctionnalité de lecture pour votre outil CLI de gestionnaire de tâches. Bon travail! Dans les sections à venir, nous explorerons comment supprimer et mettre à jour des tâches.
Cette section du didacticiel couvre le processus simple de suppression de tâches de la base de données. La logique est simple : les utilisateurs saisissent le code Todo de la tâche qu'ils souhaitent supprimer, et nous supprimons cette tâche de la base de données.
Examinons le code pour que cela se produise dans le ./commands/deleteTask.jsfichier.
La première étape consiste à importer les packages et fonctions nécessaires au début du fichier, notamment Inquirer, TodosModel, ConnectDB(), DisconnectDB(), Ora et Chalk.
// Importing packages and functions
import inquirer from "inquirer";
import Todos from '../schema/TodoSchema.js'
import {connectDB, disconnectDB} from '../db/connectDB.js'
import ora from "ora";
import chalk from "chalk";
Ensuite, nous définirons une fonction asynchrone appelée getTaskCode(). Le rôle de cette fonction est de demander à l'utilisateur de saisir le code de la tâche qu'il souhaite supprimer à l'aide de inquirer. La fonction coupe ensuite le code saisi par l'utilisateur à l'aide de la trim()méthode et renvoie le code coupé. Le processus de découpage est nécessaire pour supprimer les espaces de début ou de fin que le code pourrait contenir.
Voici le code de la getTaskCode()fonction :
export async function getTaskCode(){
try {
// Prompting the user to enter the todo code
const answers = await inquirer.prompt([
{name: 'code', 'message': 'Enter the code of the todo: ', type: 'input'},
])
// Trimming user's response so that the todo code does not contain any starting or trailing white spaces
answers.code = answers.code.trim()
return answers
} catch (error) {
console.log('Something went wrong...\n', error)
}
}
Nous allons maintenant définir la fonction principale nommée deleteTask(). Le code complet est ci-dessous :
export default async function deleteTask(){
try {
// Obtaining the todo code provided by user
const userCode = await getTaskCode()
// Connecting to the database
await connectDB()
// Starting the spinner
const spinner = ora('Finding and Deleting the todo...').start()
// Deleting the task
const response = await Todos.deleteOne({code: userCode.code})
// Stopping the spinner
spinner.stop()
// Checking the delete operation
if(response.deletedCount === 0){
console.log(chalk.redBright('Could not find any todo matching the provided name. Deletion failed.'))
} else {
console.log(chalk.greenBright('Deleted Task Successfully'))
}
// Disconnecting from the database
await disconnectDB()
} catch (error) {
// Error Handling
console.log('Something went wrong, Error: ', error)
process.exit(1)
}
}
Décomposons ce code étape par étape :
Si j'appelle la fonction : deleteTask()puis que j'exécute le code à l'aide node /commands/deleteTask.jsde la commande, je vois ceci dans ma console :
Sortie vue sur le terminal lorsque deleteTask.jsle fichier est exécuté. Il montre comment le code supprime avec succès une seule tâche de la base de données.
Comme vous pouvez le voir dans le GIF ci-dessus, le code vous demandera de saisir un code Todo pour la tâche que vous souhaitez supprimer. Lors de la suppression, vous recevrez un message de confirmation dans la console. Lorsque nous lisons toutes nos tâches après le processus de suppression, nous ne voyons pas la tâche supprimée. Cela implique que notre code réussit à faire ce qu’il est censé faire !
Dans cette section, nous examinerons le code pour mettre à jour une tâche spécifique. La mise à jour d'une tâche est un peu plus complexe que les opérations précédentes. Le processus se déroule comme suit :
Commençons à coder ! La première chose à faire est d’importer tous les packages et fonctions dont nous aurons besoin pour effectuer ce travail.
// Importing packages and functions
import {connectDB, disconnectDB} from '../db/connectDB.js'
import { getTaskCode } from './deleteTask.js'
import inquirer from 'inquirer'
import Todos from '../schema/TodoSchema.js'
import ora from 'ora'
import chalk from 'chalk'
Avant de commencer à travailler sur notre updateTask()fonction, nous allons créer une petite fonction dans le même fichier nommée askUpdateQ(). Le rôle de cette fonction est d'inviter l'utilisateur à saisir les valeurs mises à jour de la tâche, telles que le nom, la description et l'état de la tâche. À la fin, cette fonction renverra l'objet de réponse.
Voici le code correspondant :
async function askUpdateQ(todo){
try {
// Prompting the user to update the todo data
const update = await inquirer.prompt([
{name: 'name', message: 'Update the name?', type: 'input', default: todo.name},
{name: 'detail', message: 'Update the Description?', type: 'input', default: todo.detail},
{name: 'status', message: 'Update the status', type: 'list', choices: ['pending', 'completed'], default: todo.status}
])
return update
} catch (error) {
console.log('Something went wrong... \n', error)
}
}
Deux choses sont à noter ici :
Cela dit, regardons maintenant le code de la updateTask()fonction :
export default async function updateTask(){
try {
// Obtaining the task code entered by user by calling getTaskCode() method
const userCode = await getTaskCode()
// Connecting to the database
await connectDB()
// Starting the spinner
const spinner = ora('Finding the todo...').start()
// Finding the todo which the user wants to update
const todo = await Todos.findOne({code: userCode.code})
// Stopping the spinner
spinner.stop()
// Checking if the todo exists or not
if(!todo){
console.log(chalk.redBright('Could not find a Todo with the code you provided.'))
} else{
console.log(chalk.blueBright('Type the updated properties. Press Enter if you don\'t want to update the data.'))
// Get the user's response of the updated data by calling askUpdateQ() method
const update = await askUpdateQ(todo)
// If user marked status as completed, we delete the todo else we update the data
if(update.status === 'completed'){
// Changing spinner text and starting it again
spinner.text = 'Deleting the todo...'
spinner.start()
// Deleting the todo
await Todos.deleteOne({_id : todo._id})
// Stopping the spinner and display the success message
spinner.stop()
console.log(chalk.greenBright('Deleted the todo.'))
} else {
// Update the todo
spinner.text = 'Updating the todo'
spinner.start()
await Todos.updateOne({_id: todo._id}, update, {runValidators: true})
spinner.stop()
console.log(chalk.greenBright('Updated the todo.'))
}
}
// Disconnecting from the database
await disconnectDB()
} catch (error) {
// Error Handling
console.log('Something went wrong, Error: ', error)
process.exit(1)
}
}
Voici une ventilation du code ci-dessus :
Si j'appelle la updateTask()fonction et exécute le code à l'aide de la commande :node ./commands/updateTask.js , je vois quelque chose comme ceci dans ma console :
Sortie vue sur le terminal lorsque updateTask.jsle fichier est exécuté. Il montre comment le code récupère avec succès la tâche d'origine et la remplace avec succès par les valeurs mises à jour fournies par l'utilisateur.
Avec cela, vous avez implémenté avec succès toutes les opérations CRUD. Maintenant, utilisons la commanderbibliothèque pour tout rassembler et créer un outil CLI entièrement fonctionnel.
Comment écrire le point d'entrée CLI à l'aide de Commander
Dans les dernières étapes de notre projet, nous allons exploiter la puissance de la commanderbibliothèque pour créer une interface CLI conviviale. Avec commander, nous pouvons définir soigneusement différentes commandes – telles que lire, ajouter, mettre à jour et supprimer – de manière organisée et intuitive.
Notre code résidera dans le index.jsfichier, qui sert de point d'entrée à notre application. Ci-dessous le code complet :
#!/usr/bin/env node
// Importing the required functions for each command
import addTask from './commands/addTask.js'
import deleteTask from './commands/deleteTask.js'
import readTask from './commands/readTask.js'
import updateTask from './commands/updateTask.js'
// Importing the Command class from Commander.js library
import { Command } from 'commander'
// Creating an instance of the Command class
const program = new Command()
// Setting the name and description of the CLI tool
program
.name('todo')
.description('Your terminal task manager!')
.version('1.0.0')
// Defining a command called 'add'
program
.command('add')
.description('Create a new todo.')
.action(addTask)
// Defining a command called 'read'
program
.command('read')
.description('Reads all the todos.')
.action(readTask)
// Defining a command called 'update'
program
.command('update')
.description('Updates a todo.')
.action(updateTask)
// Defining a command called 'delete'
program
.command('delete')
.description('Deletes a todo.')
.action(deleteTask)
// Parsing the command-line arguments and executing the corresponding actions
program.parse()
Comment tester l'outil CLI
Nous sommes maintenant presque sur la ligne finale de la création de notre outil CLI Task Manager ! Avant de pouvoir installer et utiliser l'outil, il nous suffit d'apporter un petit ajustement au package.jsonfichier. Ajoutez simplement l'entrée suivante au fichier JSON :
"bin": {
"todo": "index.js"
}
Si vous avez déjà créé un outil CLI et souhaitez que les utilisateurs y accèdent à partir de la ligne de commande d'une manière similaire aux commandes telles que nodeou npm, alors la propriété "bin" entre en jeu.
La propriété "bin" dans le package.jsonfichier vous permet de spécifier des commandes qui deviennent globalement accessibles une fois votre package installé. En termes plus simples, il vous permet de créer des raccourcis pour exécuter des scripts ou des fonctions spécifiques à partir de la ligne de commande.
Le code fourni demande à Node.js d'exécuter le script défini dans index.jschaque fois que quelqu'un entre tododans le terminal. Essentiellement, cela transforme votre script en un outil de ligne de commande accessible mondialement.
La dernière étape avant de pouvoir commencer à utiliser l'outil est de l'installer globalement sur votre système ! Exécutez la commande suivante pour ce faire :
npm i -g .
Conclusion
Félicitations si vous avez suivi jusqu'ici ! Vous êtes maintenant entièrement équipé pour commencer à utiliser votre outil CLI Task Manager.
Voici les commandes que vous pouvez utiliser pour faire fonctionner l'outil :
Vous pouvez également utiliser ces 2 options à l'aide de l'outil :
Et cela conclut ce manuel. J'espère que vous l'avez trouvé agréable et instructif.
Voici le lien vers le référentiel : Task Manager CLI Tool Repo .
À la prochaine! 👋 ❤️ ✨
Source : https://www.freecodecamp.org
#node #nodejs #mongodb