Skip to Content
Packages@workspace/database

@workspace/database

Le package @workspace/database fournit un client MongoDB (version 6.12.0) et des modèles pour gérer les données de l’application.

Présentation

Ce package est le cœur de la persistance des données du projet. Il utilise le driver MongoDB officiel avec :

  • Pattern Singleton : une seule connexion rĂ©utilisĂ©e dans toute l’application
  • Connection pooling : gestion optimisĂ©e des connexions (2-10 connexions)
  • Types TypeScript : support complet avec gĂ©nĂ©riques pour les collections
  • Index optimisĂ©s : index unique sur l’email, index de recherche sur le nom
  • Gestion automatique : horodatage et normalisation des donnĂ©es

Installation

Ce package fait partie du monorepo et est automatiquement disponible via l’alias @workspace/database.

Configuration

Variables d’environnement

Créez un fichier .env.local à la racine de l’application web (apps/web/.env.local) :

# Configuration MongoDB MONGODB_URI=mongodb://localhost:27017 MONGODB_DB_NAME=tp-nextjs
VariableDescriptionDéfautRequis
MONGODB_URIURL de connexion MongoDBmongodb://localhost:27017Non
MONGODB_DB_NAMENom de la base de donnéestp-nextjsNon

Docker

Le projet utilise Docker Compose pour gérer MongoDB. La configuration lance automatiquement MongoDB 7 dans un container.

Utilisez Docker Compose pour démarrer MongoDB :

# Démarrer MongoDB en arrière-plan docker-compose up -d # Vérifier que MongoDB est démarré docker-compose ps # Voir les logs docker-compose logs -f mongodb # Accéder au shell MongoDB docker exec -it tp-nextjs-mongodb mongosh # Arrêter MongoDB docker-compose down

Caractéristiques techniques

  • Driver MongoDB : version 6.12.0
  • Connection pooling :
    • Pool minimum : 2 connexions
    • Pool maximum : 10 connexions
  • Timeouts :
    • Server selection : 5000ms
    • Connection : 10000ms
  • Pattern Singleton : Ă©vite les connexions multiples en dĂ©veloppement

Client MongoDB

Connexion

import { getMongoClient, getDatabase, getCollection } from "@workspace/database"; // Récupérer le client MongoDB const client = await getMongoClient(); // Récupérer la base de données const db = await getDatabase(); // Récupérer une collection typée const users = await getCollection<User>("users");

Fonctions disponibles

FonctionDescription
getMongoClient()Récupère le client MongoDB (singleton)
getDatabase()Récupère la base de données principale
getCollection<T>(name)Récupère une collection typée
closeConnection()Ferme la connexion
checkConnection()Vérifie la connexion

Modèle User

Interface

interface User { _id?: ObjectId; email: string; name: string; password?: string; createdAt: Date; updatedAt: Date; }

Types utilitaires

// Pour la création type CreateUserInput = Omit<User, '_id' | 'createdAt' | 'updatedAt'>; // Pour la mise à jour type UpdateUserInput = Partial<Omit<User, '_id' | 'createdAt' | 'updatedAt'>>;

Opérations CRUD

Créer un utilisateur

import { createUser } from "@workspace/database"; const newUser = await createUser({ email: "test@example.com", name: "Test User", password: "hashedPassword", // Toujours hasher avant ! });

Trouver un utilisateur

import { findUserById, findUserByEmail } from "@workspace/database"; // Par ID const user = await findUserById("67abc123..."); // Par email (utile pour l'authentification) const user = await findUserByEmail("test@example.com");

Lister les utilisateurs

import { listUsers, countUsers } from "@workspace/database"; // Liste paginée (20 résultats par défaut) const users = await listUsers(20, 0); // Nombre total const total = await countUsers();

Mettre Ă  jour un utilisateur

import { updateUser } from "@workspace/database"; const updated = await updateUser("67abc123...", { name: "Nouveau nom", });

Supprimer un utilisateur

import { deleteUser } from "@workspace/database"; const success = await deleteUser("67abc123...");

Initialisation

Au démarrage de l’application, initialisez les index :

import { initializeUsersCollection } from "@workspace/database"; // Crée les index nécessaires (email unique, etc.) await initializeUsersCollection();

Bonnes pratiques

1. Hashage des mots de passe

Toujours hasher les mots de passe avant de les stocker :

import { hashPassword } from "@/lib/auth"; import { createUser } from "@workspace/database"; // ❌ JAMAIS faire ça await createUser({ email, name, password: "plaintext" }); // ✅ Toujours hasher avant const hashedPassword = await hashPassword(password); await createUser({ email, name, password: hashedPassword });

2. Normalisation des emails

Les emails sont automatiquement normalisés (minuscules + trim) par le package :

// Ces deux appels trouvent le mĂŞme utilisateur await findUserByEmail("USER@EXAMPLE.COM"); await findUserByEmail(" user@example.com ");

3. Gestion des erreurs

Gérez les erreurs de connexion et les contraintes d’unicité :

try { await createUser({ email, name, password }); } catch (error) { // Erreur d'email dupliqué (code 11000) if (error.code === 11000) { console.error("Cet email existe déjà"); } }

4. Fermeture propre

Appelez closeConnection() à l’arrêt de l’application pour libérer les ressources :

import { closeConnection } from "@workspace/database"; // À l'arrêt de l'application process.on("SIGTERM", async () => { await closeConnection(); process.exit(0); });

Sécurité

Protection du mot de passe

  • findUserById() et listUsers() excluent automatiquement le mot de passe
  • findUserByEmail() inclut le mot de passe pour l’authentification
  • Utilisez projection: { password: 0 } pour exclure manuellement

Index unique sur l’email

Un index unique empêche les doublons d’email :

// Créé automatiquement par initializeUsersCollection() await collection.createIndex({ email: 1 }, { unique: true });

Structure du package

packages/database/ ├── src/ │ ├── index.ts # Exports principaux │ ├── mongodb-client.ts # Client MongoDB singleton │ └── user.ts # Modèle User et CRUD ├── package.json # Dépendances (mongodb@6.12.0) ├── tsconfig.json # Configuration TypeScript ├── eslint.config.js # Configuration ESLint └── README.md # Documentation

Dépendances

Le package utilise les dépendances suivantes :

  • mongodb (^6.12.0) : Driver MongoDB officiel
  • @types/node : Types TypeScript pour Node.js
  • typescript : Compilateur TypeScript

Intégration avec l’authentification

Ce package est conçu pour fonctionner avec le système d’authentification du projet. Voir le guide d’authentification pour plus de détails.

Workflow complet

import { createUser, findUserByEmail } from "@workspace/database"; import { hashPassword, verifyPassword, createSession } from "@/lib/auth"; // 1. Inscription async function signup(email: string, name: string, password: string) { // Vérifier si l'email existe const existing = await findUserByEmail(email); if (existing) throw new Error("Email déjà utilisé"); // Hasher le mot de passe const hashedPassword = await hashPassword(password); // Créer l'utilisateur const user = await createUser({ email, name, password: hashedPassword }); // Créer la session await createSession(user._id.toString(), user.email, user.name); } // 2. Connexion async function login(email: string, password: string) { // Trouver l'utilisateur const user = await findUserByEmail(email); if (!user || !user.password) throw new Error("Identifiants invalides"); // Vérifier le mot de passe const isValid = await verifyPassword(password, user.password); if (!isValid) throw new Error("Identifiants invalides"); // Créer la session await createSession(user._id.toString(), user.email, user.name); }

Exemple complet

import { createUser, findUserByEmail, listUsers, checkConnection, } from "@workspace/database"; // Vérifier la connexion const isConnected = await checkConnection(); if (!isConnected) { console.error("MongoDB non disponible"); return; } // Créer un utilisateur const user = await createUser({ email: "nouveau@example.com", name: "Nouveau User", }); // Récupérer tous les utilisateurs const allUsers = await listUsers(); console.log(`${allUsers.length} utilisateurs trouvés`);
Last updated on