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": "[email protected]", "password": "password123" }
-
Iniciar sessió:
- Mètode: POST
- URL:
http://localhost:3000/api/users/login
- Cos:
{ "email": "[email protected]", "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