跳到内容
Sutando
Esc
↑↓导航↵打开⌘J预览

用 Sutando 和 Express 构建 REST API

用 Sutando 构建 REST API 非常简单。本教程将构建一个完整的博客 API,包含验证和错误处理。


用 Sutando 构建 REST API 非常简单。本教程将构建一个完整的博客 API,包含验证和错误处理。

项目搭建

mkdir blog-api && cd blog-api
npm init -y
npm install sutando mysql2 express zod

数据库和模型

import { sutando, Model } from 'sutando';

sutando.addConnection({
  client: 'mysql2',
  connection: { host: '127.0.0.1', user: 'root', password: '', database: 'blog' }
});

class User extends Model {
  table = 'users';
  hidden = ['password'];
  relationPosts() { return this.hasMany(Post, 'user_id'); }
}

class Post extends Model {
  table = 'posts';
  casts = { published: 'boolean' };
  relationUser() { return this.belongsTo(User, 'user_id'); }
  relationComments() { return this.hasMany(Comment, 'post_id'); }
  scopePublished(query) { return query.where('published', true); }
}

class Comment extends Model {
  table = 'comments';
  relationUser() { return this.belongsTo(User, 'user_id'); }
}

API 路由

// 文章列表(分页 + 预加载)
app.get('/posts', async (req, res) => {
  const page = Number(req.query.page) || 1;
  const limit = Number(req.query.limit) || 20;
  const posts = await Post.query()
    .with('user', 'comments.user')
    .published()
    .orderBy('created_at', 'desc')
    .paginate(page, limit);
  res.json(posts);
});

// 创建文章(带验证)
app.post('/posts', async (req, res) => {
  const data = createPostSchema.parse(req.body);
  const post = await Post.query().create(data);
  res.status(201).json(post);
});

// 更新文章
app.put('/posts/:id', async (req, res) => {
  const post = await Post.query().find(req.params.id);
  if (!post) return res.status(404).json({ error: '文章不存在' });
  post.fill(updatePostSchema.parse(req.body));
  await post.save();
  res.json(post);
});

// 删除文章
app.delete('/posts/:id', async (req, res) => {
  const post = await Post.query().find(req.params.id);
  if (!post) return res.status(404).json({ error: '文章不存在' });
  await post.delete();
  res.json({ success: true });
});

// 添加评论
app.post('/posts/:id/comments', async (req, res) => {
  const post = await Post.query().find(req.params.id);
  if (!post) return res.status(404).json({ error: '文章不存在' });
  const comment = await Comment.query().create({ ...req.body, post_id: post.id });
  res.status(201).json(comment);
});

展示的关键功能

  • 分页:.paginate(page, limit)
  • 预加载:.with('user', 'comments.user')
  • 查询作用域:.published()
  • 验证:用 Zod schema
  • 错误处理:async 包装器 + 错误中间件
  • 隐藏字段:模型上的 hidden 数组隐藏密码

完整文档请访问 sutando.org。

这个页面有帮助吗?