En aquest tema, aprendrem a construir una API de comerç electrònic utilitzant Node.js i Express. Aquesta API permetrà gestionar productes, usuaris, comandes i autenticació. A més, implementarem operacions CRUD (Crear, Llegir, Actualitzar, Eliminar) per a cada recurs.
Objectius del Tema
- Configurar un projecte Node.js amb Express.
- Crear models de dades per a productes, usuaris i comandes.
- Implementar operacions CRUD per a cada recurs.
- Gestionar l'autenticació i l'autorització d'usuaris.
- Provar l'API utilitzant Postman.
- Configuració del Projecte
1.1. Inicialitzar el Projecte
Primer, crearem una nova carpeta per al projecte i inicialitzarem un projecte Node.js.
1.2. Instal·lar les Dependències Necessàries
Instal·larem Express, Mongoose (per a MongoDB), bcrypt (per a l'encriptació de contrasenyes) i jsonwebtoken (per a l'autenticació).
1.3. Configurar l'Aplicació Express
Crearem un fitxer app.js per configurar l'aplicació Express.
// app.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const app = express();
const port = process.env.PORT || 3000;
// Middleware
app.use(bodyParser.json());
// Connexió a MongoDB
mongoose.connect('mongodb://localhost/ecommerce', { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('Could not connect to MongoDB', err));
// Rutes
app.get('/', (req, res) => {
res.send('Welcome to the E-commerce API');
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
- Models de Dades
2.1. Model de Producte
Crearem un model per als productes.
// models/Product.js
const mongoose = require('mongoose');
const productSchema = new mongoose.Schema({
name: { type: String, required: true },
description: String,
price: { type: Number, required: true },
category: String,
stock: { type: Number, default: 0 }
});
const Product = mongoose.model('Product', productSchema);
module.exports = Product;2.2. Model d'Usuari
Crearem un model per als usuaris.
// models/User.js
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const userSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true }
});
// Encriptar la contrasenya abans de guardar l'usuari
userSchema.pre('save', async function(next) {
if (!this.isModified('password')) return next();
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
});
const User = mongoose.model('User', userSchema);
module.exports = User;2.3. Model de Comanda
Crearem un model per a les comandes.
// models/Order.js
const mongoose = require('mongoose');
const orderSchema = new mongoose.Schema({
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
products: [
{
product: { type: mongoose.Schema.Types.ObjectId, ref: 'Product', required: true },
quantity: { type: Number, required: true }
}
],
total: { type: Number, required: true },
status: { type: String, default: 'Pending' }
});
const Order = mongoose.model('Order', orderSchema);
module.exports = Order;
- Rutes i Controladors
3.1. Rutes de Productes
Crearem rutes per gestionar els productes.
// routes/products.js
const express = require('express');
const router = express.Router();
const Product = require('../models/Product');
// Crear un nou producte
router.post('/', async (req, res) => {
const product = new Product(req.body);
try {
await product.save();
res.status(201).send(product);
} catch (error) {
res.status(400).send(error);
}
});
// Obtenir tots els productes
router.get('/', async (req, res) => {
try {
const products = await Product.find();
res.send(products);
} catch (error) {
res.status(500).send(error);
}
});
// Obtenir un producte per ID
router.get('/:id', async (req, res) => {
try {
const product = await Product.findById(req.params.id);
if (!product) return res.status(404).send();
res.send(product);
} catch (error) {
res.status(500).send(error);
}
});
// Actualitzar un producte per ID
router.put('/:id', async (req, res) => {
try {
const product = await Product.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true });
if (!product) return res.status(404).send();
res.send(product);
} catch (error) {
res.status(400).send(error);
}
});
// Eliminar un producte per ID
router.delete('/:id', async (req, res) => {
try {
const product = await Product.findByIdAndDelete(req.params.id);
if (!product) return res.status(404).send();
res.send(product);
} catch (error) {
res.status(500).send(error);
}
});
module.exports = router;3.2. Rutes d'Usuaris
Crearem rutes per gestionar els usuaris.
// routes/users.js
const express = require('express');
const router = express.Router();
const User = require('../models/User');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
// Registrar un nou usuari
router.post('/register', async (req, res) => {
const user = new User(req.body);
try {
await user.save();
res.status(201).send(user);
} catch (error) {
res.status(400).send(error);
}
});
// Iniciar sessió
router.post('/login', async (req, res) => {
try {
const user = await User.findOne({ email: req.body.email });
if (!user) return res.status(400).send('Invalid email or password');
const isMatch = await bcrypt.compare(req.body.password, user.password);
if (!isMatch) return res.status(400).send('Invalid email or password');
const token = jwt.sign({ _id: user._id }, 'secretkey');
res.send({ user, token });
} catch (error) {
res.status(500).send(error);
}
});
module.exports = router;3.3. Rutes de Comandes
Crearem rutes per gestionar les comandes.
// routes/orders.js
const express = require('express');
const router = express.Router();
const Order = require('../models/Order');
// Crear una nova comanda
router.post('/', async (req, res) => {
const order = new Order(req.body);
try {
await order.save();
res.status(201).send(order);
} catch (error) {
res.status(400).send(error);
}
});
// Obtenir totes les comandes
router.get('/', async (req, res) => {
try {
const orders = await Order.find().populate('user').populate('products.product');
res.send(orders);
} catch (error) {
res.status(500).send(error);
}
});
// Obtenir una comanda per ID
router.get('/:id', async (req, res) => {
try {
const order = await Order.findById(req.params.id).populate('user').populate('products.product');
if (!order) return res.status(404).send();
res.send(order);
} catch (error) {
res.status(500).send(error);
}
});
// Actualitzar una comanda per ID
router.put('/:id', async (req, res) => {
try {
const order = await Order.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true });
if (!order) return res.status(404).send();
res.send(order);
} catch (error) {
res.status(400).send(error);
}
});
// Eliminar una comanda per ID
router.delete('/:id', async (req, res) => {
try {
const order = await Order.findByIdAndDelete(req.params.id);
if (!order) return res.status(404).send();
res.send(order);
} catch (error) {
res.status(500).send(error);
}
});
module.exports = router;3.4. Integrar les Rutes a l'Aplicació
Finalment, integrarem les rutes a l'aplicació principal.
// app.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const app = express();
const port = process.env.PORT || 3000;
// Middleware
app.use(bodyParser.json());
// Connexió a MongoDB
mongoose.connect('mongodb://localhost/ecommerce', { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('Could not connect to MongoDB', err));
// Rutes
const productRoutes = require('./routes/products');
const userRoutes = require('./routes/users');
const orderRoutes = require('./routes/orders');
app.use('/api/products', productRoutes);
app.use('/api/users', userRoutes);
app.use('/api/orders', orderRoutes);
app.get('/', (req, res) => {
res.send('Welcome to the E-commerce API');
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
- Provar l'API
4.1. Utilitzar Postman
Utilitzarem Postman per provar les diferents rutes de l'API. Aquí teniu alguns exemples de peticions:
-
Crear un producte:
- Mètode: POST
- URL:
http://localhost:3000/api/products - Cos:
{ "name": "Product 1", "description": "Description of Product 1", "price": 100, "category": "Category 1", "stock": 10 }
-
Obtenir tots els productes:
- Mètode: GET
- URL:
http://localhost:3000/api/products
-
Registrar un usuari:
- Mètode: POST
- URL:
http://localhost:3000/api/users/register - Cos:
{ "username": "user1", "email": "user1@example.com", "password": "password123" }
-
Iniciar sessió:
- Mètode: POST
- URL:
http://localhost:3000/api/users/login - Cos:
{ "email": "user1@example.com", "password": "password123" }
-
Crear una comanda:
- Mètode: POST
- URL:
http://localhost:3000/api/orders - Cos:
{ "user": "user_id", "products": [ { "product": "product_id", "quantity": 2 } ], "total": 200 }
Conclusió
En aquest tema, hem après a crear una API de comerç electrònic utilitzant Node.js i Express. Hem configurat el projecte, creat models de dades, implementat operacions CRUD i gestionat l'autenticació d'usuaris. També hem provat l'API utilitzant Postman. Aquest és un bon punt de partida per desenvolupar aplicacions de comerç electrònic més complexes i robustes.
Curs de Node.js
Mòdul 1: Introducció a Node.js
Mòdul 2: Conceptes Bàsics
Mòdul 3: Sistema de Fitxers i I/O
Mòdul 4: HTTP i Servidors Web
Mòdul 5: NPM i Gestió de Paquets
Mòdul 6: Framework Express.js
- Introducció a Express.js
- Configuració d'una Aplicació Express
- Middleware
- Routing en Express
- Gestió d'Errors
Mòdul 7: Bases de Dades i ORMs
- Introducció a les Bases de Dades
- Utilitzar MongoDB amb Mongoose
- Utilitzar Bases de Dades SQL amb Sequelize
- Operacions CRUD
Mòdul 8: Autenticació i Autorització
Mòdul 9: Proves i Depuració
- Introducció a les Proves
- Proves Unitàries amb Mocha i Chai
- Proves d'Integració
- Depuració d'Aplicacions Node.js
Mòdul 10: Temes Avançats
Mòdul 11: Desplegament i DevOps
- Variables d'Entorn
- Utilitzar PM2 per a la Gestió de Processos
- Desplegar a Heroku
- Integració i Desplegament Continu
