Files
node-fastify/server.js
2025-09-20 23:02:18 +08:00

131 lines
3.7 KiB
JavaScript

// 1. 导入依赖
require('dotenv').config(); // 尽早加载环境变量
const fastify = require('fastify')({ logger: true }); // 开启日志,方便调试
const { ObjectId } = require('mongodb'); // 导入 ObjectId 用于ID操作
// 2. 注册 MongoDB 插件
// Fastify 的插件系统能确保在路由处理前,数据库连接已经准备就绪
fastify.register(require('./db-connector'));
// ------------------- API 路由定义 -------------------
/**
* @api {post} /todos 创建一个新的 Todo
*/
fastify.post('/todos', async (request, reply) => {
// fastify.mongo.db 是由我们的插件注入的
const todosCollection = fastify.mongo.db.collection('todos');
// 从请求体中获取数据
const { text, completed = false } = request.body;
if (!text) {
return reply.code(400).send({ message: '`text` 字段是必需的。' });
}
const newTodo = {
text,
completed,
createdAt: new Date(),
};
const result = await todosCollection.insertOne(newTodo);
reply.code(201).send(result); // 201 Created
});
/**
* @api {get} /todos 获取所有 Todos
*/
fastify.get('/todos', async (request, reply) => {
const todosCollection = fastify.mongo.db.collection('todos');
const todos = await todosCollection.find({}).toArray();
reply.send(todos);
});
/**
* @api {get} /todos/:id 获取单个 Todo
*/
fastify.get('/todos/:id', async (request, reply) => {
const { id } = request.params;
// 校验 ID 格式是否正确
if (!ObjectId.isValid(id)) {
return reply.code(400).send({ message: '无效的ID格式。' });
}
const objectId = new ObjectId(id);
const todosCollection = fastify.mongo.db.collection('todos');
const todo = await todosCollection.findOne({ _id: objectId });
if (!todo) {
return reply.code(404).send({ message: '未找到指定的 Todo。' });
}
reply.send(todo);
});
/**
* @api {put} /todos/:id 更新一个 Todo
*/
fastify.put('/todos/:id', async (request, reply) => {
const { id } = request.params;
const { text, completed } = request.body;
if (!ObjectId.isValid(id)) {
return reply.code(400).send({ message: '无效的ID格式。' });
}
const objectId = new ObjectId(id);
const todosCollection = fastify.mongo.db.collection('todos');
const updateDoc = { $set: {} };
if (text !== undefined) updateDoc.$set.text = text;
if (completed !== undefined) updateDoc.$set.completed = completed;
// 如果没有提供任何更新字段,则返回错误
if (Object.keys(updateDoc.$set).length === 0) {
return reply.code(400).send({ message: '请提供需要更新的字段 (text 或 completed)。' })
}
const result = await todosCollection.updateOne({ _id: objectId }, updateDoc);
if (result.matchedCount === 0) {
return reply.code(404).send({ message: '未找到指定的 Todo 进行更新。' });
}
reply.send({ message: 'Todo 更新成功。' });
});
/**
* @api {delete} /todos/:id 删除一个 Todo
*/
fastify.delete('/todos/:id', async (request, reply) => {
const { id } = request.params;
if (!ObjectId.isValid(id)) {
return reply.code(400).send({ message: '无效的ID格式。' });
}
const objectId = new ObjectId(id);
const todosCollection = fastify.mongo.db.collection('todos');
const result = await todosCollection.deleteOne({ _id: objectId });
if (result.deletedCount === 0) {
return reply.code(404).send({ message: '未找到指定的 Todo 进行删除。' });
}
reply.code(200).send({ message: 'Todo 删除成功。' });
});
// 3. 启动服务器
const start = async () => {
try {
await fastify.listen({ port: 3000 });
fastify.log.info(`服务器运行在 ${fastify.server.address().port}`);
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();