Pourquoi Deployer Express sur Supabase ?
Le déploiement d'un application Express sur Supabase est une approche puissante pour les développeurs qui cherchent à créer des applications backend robustes et scalables. Supabase est une plateforme open-source de base de données et d'authentification, permettant aux développeurs de se concentrer davantage sur l'application métier plutôt que sur le backend traditionnel.
Un cas concret : Imaginez un petit projet de gestion de tâches. Vous avez besoin d'une API pour créer, lire, mettre à jour et supprimer des tâches. En utilisant Express pour le backend et Supabase comme base de données, vous pouvez rapidement développer une application fonctionnelle et scalable.
Prerequis
Connaissances nécessaires :
- JavaScript ES6+
- Node.js (v14 ou plus)
- npm (Node Package Manager)
- Bases de connaissances en Express.js
- Connaissance de SQL pour gérer la base de données de Supabase
Outils à installer :
Concepts fondamentaux
Concept 1 : Supabase et ses services
Supabase offre plusieurs services :
- Database : Pour stocker vos données
- Authentification : Pour gérer les utilisateurs
- Functions : Pour exécuter du code serveur
## Installation de la CLI de Supabase
npm install -g supabase-cli
Concept 2 : Lien entre Express et Supabase
Pour intégrer Express avec Supabase, nous utilisons les services Database et Auth.
// Import des modules nécessaires
const express = require('express');
const { createClient } = require('@supabase/supabase-js');
// Configuration de l'application Express
const app = express();
app.use(express.json());
// Création du client Supabase
const supabaseUrl = 'https://your-project-ref.supabase.co';
const supabaseAnonKey = 'your-anon-key';
const supabase = createClient(supabaseUrl, supabaseAnonKey);
Concept 3 : Utilisation des services Supabase
Authentification
// Route pour l'inscription d'un utilisateur
app.post('/register', async (req, res) => {
const { email, password } = req.body;
const { data, error } = await supabase.auth.signUp({
email,
password,
});
if (error) return res.status(400).json({ error: error.message });
res.json(data);
});
Base de données
// Route pour récupérer toutes les tâches
app.get('/tasks', async (req, res) => {
const { data, error } = await supabase.from('tasks').select('*');
if (error) return res.status(500).json({ error: error.message });
res.json(data);
});
// Route pour créer une nouvelle tâche
app.post('/tasks', async (req, res) => {
const { title } = req.body;
const { data, error } = await supabase.from('tasks').insert([{ title }]);
if (error) return res.status(400).json({ error: error.message });
res.json(data);
});
Mise en pratique : projet fil rouge
Mini-projet : Gestionnaire de tâches
Nous allons créer un simple gestionnaire de tâches avec les fonctionnalités suivantes :
- Inscription et connexion des utilisateurs
- Création, lecture, mise à jour et suppression de tâches
Étape 1 : Initialiser le projet
## Créer un nouveau dossier pour le projet
mkdir task-manager
cd task-manager
## Initialiser un nouveau projet Node.js
npm init -y
## Installer les dépendances nécessaires
npm install express @supabase/supabase-js bcryptjs jsonwebtoken dotenv
Étape 2 : Configurer le fichier .env
## Créer un fichier .env pour stocker les variables d'environnement
touch .env
Contenu du .env :
SUPABASE_URL=https://your-project-ref.supabase.co
SUPABASE_ANON_KEY=your-anon-key
SECRET_KEY=my-secret-key
Étape 3 : Créer l'application Express
Créer un fichier app.js avec le code suivant :
// Import des modules nécessaires
const express = require('express');
const { createClient } = require('@supabase/supabase-js');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
require('dotenv').config();
// Configuration de l'application Express
const app = express();
app.use(express.json());
// Création du client Supabase
const supabaseUrl = process.env.SUPABASE_URL;
const supabaseAnonKey = process.env.SUPABASE_ANON_KEY;
const supabase = createClient(supabaseUrl, supabaseAnonKey);
// Route pour l'inscription d'un utilisateur
app.post('/register', async (req, res) => {
const { email, password } = req.body;
// Hacher le mot de passe
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
const { data, error } = await supabase.auth.signUp({
email,
password: hashedPassword,
});
if (error) return res.status(400).json({ error: error.message });
res.json(data);
});
// Route pour l'authentification d'un utilisateur
app.post('/login', async (req, res) => {
const { email, password } = req.body;
const { data, error } = await supabase.auth.signIn({
email,
password,
});
if (error) return res.status(400).json({ error: error.message });
// Générer un token JWT
const token = jwt.sign({ id: data.user.id }, process.env.SECRET_KEY, { expiresIn: '1h' });
res.json({ token });
});
// Middleware pour vérifier le token JWT
const verifyToken = (req, res, next) => {
const token = req.headers['authorization'];
if (!token) return res.status(403).json({ message: 'Aucen token fourni' });
jwt.verify(token, process.env.SECRET_KEY, (err, decoded) => {
if (err) return res.status(401).json({ message: 'Token invalide' });
req.userId = decoded.id;
next();
});
};
// Route pour récupérer toutes les tâches
app.get('/tasks', verifyToken, async (req, res) => {
const { data, error } = await supabase.from('tasks').select('*');
if (error) return res.status(500).json({ error: error.message });
res.json(data);
});
// Route pour créer une nouvelle tâche
app.post('/tasks', verifyToken, async (req, res) => {
const { title } = req.body;
const { data, error } = await supabase.from('tasks').insert([{ title }]);
if (error) return res.status(400).json({ error: error.message });
res.json(data);
});
// Démarrer le serveur
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Serveur en cours sur le port ${PORT}`);
});
Étape 4 : Créer les tables de la base de données
Connectez-vous à Supabase et créez une nouvelle table tasks avec les colonnes suivantes :
- id (SERIAL PRIMARY KEY)
- title (VARCHAR NOT NULL)
- user_id (TEXT REFERENCES auth.users(id))
Étape 5 : Exécuter l'application
## Démarrer le serveur Express
node app.js
Erreurs fréquentes et debugging
Erreur 1 : supabase.auth.signUp retourne une erreur
Code incorrect :
const { data, error } = await supabase.auth.signUp({
email,
password: hashedPassword,
});
Code correct :
const { user, error } = await supabase.auth.signUp({
email,
password: hashedPassword,
});
Erreur 2 : jwt.verify retourne une erreur
Code incorrect :
jwt.verify(token, process.env.SECRET_KEY, (err, decoded) => {
if (err) return res.status(401).json({ message: 'Token invalide' });
req.userId = decoded.id;
next();
});
Code correct :
jwt.verify(token, process.env.SECRET_KEY, (err, decoded) => {
if (err) return res.status(401).json({ message: 'Token invalide' });
req.userId = decoded.sub; // Utiliser decoded.sub au lieu de decoded.id
next();
});
Erreur 3 : supabase.from('tasks').insert retourne une erreur
Code incorrect :
const { data, error } = await supabase.from('tasks').insert([{ title }]);
Code correct :
const { data, error } = await supabase.from('tasks').insert([{ title, user_id: req.userId }]);
Pour aller plus loin
Piste 1 : Ajouter des fonctionnalités d'authentification avancées
- Utiliser les hooks de Supabase pour gérer l'authentification côté client
- Implémenter la récupération de mot de passe et le changement de mot de passe
Piste 2 : Optimiser les performances
- Ajouter des index aux tables pour améliorer les performances des requêtes
- Utiliser des transactions pour assurer l'intégrité des données
Piste 3 : Créer une application web frontend avec React ou Vue.js
- Utiliser le token JWT pour authentifier les requêtes vers le backend Express
- Implémenter la création, lecture, mise à jour et suppression de tâches via un interface utilisateur
Défi pratique :
Créez une application web frontend utilisant React pour afficher la liste des tâches et permettre l'ajout, la modification et la suppression de tâches en utilisant les routes Express créées précédemment.