Topic 008: Complex features in Node.js
First, install the necessary packages:
npm install express socket.io mongoose passport passport-local bcryptjs jsonwebtoken
// server.js
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const mongoose = require('mongoose');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const User = require('./models/User');
const Message = require('./models/Message');
// Initialize app and server
const app = express();
const server = http.createServer(app);
const io = socketIo(server);
// Connect to MongoDB
mongoose.connect('mongodb://localhost:27017/chatapp', { useNewUrlParser: true, useUnifiedTopology: true });
// Middleware
app.use(express.json());
app.use(passport.initialize());
// Passport configuration
passport.use(new LocalStrategy(async (username, password, done) => {
try {
const user = await User.findOne({ username });
if (!user) return done(null, false, { message: 'Incorrect username.' });
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) return done(null, false, { message: 'Incorrect password.' });
return done(null, user);
} catch (error) {
return done(error);
}
}));
// Serialize user into the session
passport.serializeUser((user, done) => {
done(null, user.id);
});
// Deserialize user out of the session
passport.deserializeUser(async (id, done) => {
try {
const user = await User.findById(id);
done(null, user);
} catch (error) {
done(error);
}
});
// Routes
app.post('/login', (req, res, next) => {
passport.authenticate('local', { session: false }, (err, user, info) => {
if (err || !user) {
return res.status(400).json({ message: 'Something went wrong', user: user });
}
const token = jwt.sign({ id: user.id }, 'your_jwt_secret', { expiresIn: '1h' });
return res.json({ user, token });
})(req, res, next);
});
app.post('/register', async (req, res) => {
const { username, password } = req.body;
const hashedPassword = await bcrypt.hash(password, 10);
const newUser = new User({ username, password: hashedPassword });
await newUser.save();
res.json(newUser);
});
// Middleware to verify JWT
const verifyJWT = (req, res, next) => {
const token = req.headers['x-access-token'];
if (!token) return res.status(403).send('Token is required');
jwt.verify(token, 'your_jwt_secret', (err, decoded) => {
if (err) return res.status(500).send('Failed to authenticate token.');
req.userId = decoded.id;
next();
});
};
// Real-time chat implementation with Socket.io
io.on('connection', (socket) => {
console.log('New client connected');
socket.on('joinRoom', ({ username, room }) => {
Of course! Here are six additional complex features you might encounter in a Node.js project:
Multer is a middleware for handling multipart/form-data, primarily used for file uploads. It is commonly integrated into Node.js applications to enable users to upload images, documents, or any other file types.
const express = require("express");
const multer = require("multer");
const app = express();
const upload = multer({ dest: "uploads/" });
app.post("/upload", upload.single("file"), (req, res) => {
// Handle file upload logic
res.send("File uploaded successfully");
});
app.listen(3000, () => {
console.log("Server is running on port 3000");
});
WebSocket is a communication protocol that enables bidirectional communication between a client and a server. It’s commonly used in collaborative applications like real-time editors or multiplayer games.
const WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 8080 });
wss.on("connection", (ws) => {
ws.on("message", (message) => {
// Broadcast message to all clients
wss.clients.forEach((client) => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
});
Using GeoJSON data and MongoDB’s geospatial queries, you can implement location-based services like finding nearby places, tracking devices, or displaying maps in your Node.js application.
const mongoose = require("mongoose");
const placeSchema = new mongoose.Schema({
name: String,
location: {
type: { type: String, enum: ["Point"], required: true },
coordinates: { type: [Number], required: true },
},
});
placeSchema.index({ location: "2dsphere" });
const Place = mongoose.model("Place", placeSchema);
Cheerio and Puppeteer are popular libraries for web scraping in Node.js. You can use them to extract data from web pages, automate form submissions, or perform various tasks involving web content extraction.
const axios = require("axios");
const cheerio = require("cheerio");
axios
.get("https://example.com")
.then((response) => {
const $ = cheerio.load(response.data);
const title = $("title").text();
console.log("Title:", title);
})
.catch((error) => {
console.error("Error fetching page:", error);
});
GraphQL is a query language for APIs that enables clients to request only the data they need. You can build a GraphQL API using Apollo Server, which simplifies data fetching and management in Node.js applications.
const { ApolloServer, gql } = require("apollo-server");
const { buildFederatedSchema } = require("@apollo/federation");
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => "Hello, world!",
},
};
const server = new ApolloServer({
schema: buildFederatedSchema([{ typeDefs, resolvers }]),
});
server.listen().then(({ url }) => {
console.log(`Server ready at ${url}`);
});
Agenda and Node Schedule are libraries for scheduling jobs or tasks in Node.js applications. You can use them to automate repetitive tasks, send scheduled emails, or perform periodic data updates.
const Agenda = require("agenda");
const { MongoClient } = require("mongodb");
const mongoConnectionString = "mongodb://127.0.0.1/agenda";
const agenda = new Agenda({ db: { address: mongoConnectionString } });
agenda.define("sendEmail", async (job) => {
const { to, subject, body } = job.attrs.data;
// Logic to send email
});
(async () => {
await agenda.start();
await agenda.schedule("in 2 minutes", "sendEmail", {
to: "example@example.com",
subject: "Test",
body: "Hello!",
});
})();
These examples showcase various advanced functionalities that you might encounter and implement in a Node.js project, ranging from file uploads and real-time collaboration to geolocation services and job scheduling.