// 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();