使用 TypeScript 构建 API 服务器
视频描述 跳转到标题
使用轻量级 Hono 框架(Express 的精神继承者)来构建一个支持数据库 CRUD 操作的 RESTful API 服务器。
文本和代码 跳转到标题
如果你过去从事过 Node 项目,你可能使用过 Express 来设置 Web 服务器或托管 API。让我们看看如何使用 Hono 来做类似的事情。Hono 是一个小型简单的框架,我们可以与任何运行时一起使用,但我们将与 Deno 一起使用它。Hono 基本设置
我们将使用 JSR 将 Hono 添加到我们的项目中
deno add jsr:@hono/hono
然后它将被添加到 deno.json 文件中。
然后,在我们的主文件中,我们将创建基本的 Hono 设置。
import { Hono } from "@hono/hono";
const app = new Hono();
app.get("/", (c) => {
return c.text("Hello from the Trees!");
});
Deno.serve(app.fetch);
让我们运行 `deno run --allow-net main.ts`,然后在浏览器中访问 `localhost:8000` 即可看到效果。
CRUD 操作 跳转到标题
既然我们已经使用 Hono 设置了简单的服务器,我们就可以开始构建我们的数据库了。
为此,我们将使用 localStorage,但请记住,您可以与 Deno 一起使用任何持久化数据存储——PostgreSQL、SQL——任何您喜欢存储数据的地方。
让我们首先为一些数据创建一个容器。我们将从一个描述树类型的接口开始。
interface Tree {
id: string;
species: string;
age: number;
location: string;
}
然后我们将创建一些数据
const oak: Tree = {
id: "3",
species: "oak",
age: 3,
location: "Jim's Park",
};
然后我们将创建一些辅助函数,它们将帮助我们与 localStorage 进行交互
const setItem = (key: string, value: Tree) => {
localStorage.setItem(key, JSON.stringify(value));
};
const getItem = (key: string): Tree | null => {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : null;
};
现在让我们使用它们
setItem(`trees_${oak.id}`, oak);
const newTree = getItem(`trees_${oak.id}`);
console.log(newTree);
deno --allow-net main.ts
setItem
正在添加这棵树- 您也可以使用
setItem
来更新记录——如果键已经存在,值将被更新
const oak: Tree = {
id: "3",
species: "oak",
age: 4,
location: "Jim's Park",
};
localStorage.setItem(`trees_${oak.id}`, JSON.stringify(oak));
好的,既然我们已经了解了如何使用这些数据库方法,现在让我们使用 Hono 的路由来创建一些 REST API 路由。
app.post("/trees", async (c) => {
const { id, species, age, location } = await c.req.json();
const tree: Tree = { id, species, age, location };
setItem(`trees_${id}`, tree);
return c.json({
message: `We just added a ${species} tree!`,
});
});
为了测试这一点,我们将发送一个 curl 请求
curl -X POST https://:8000/trees \
-H "Content-Type: application/json" \
-d '{"id": "2", "species": "Willow", "age": 100, "location": "Juniper Park"}'
为了证明我们创建了那棵树,让我们通过其 ID 获取数据
app.get("/trees/:id", async (c) => {
const id = c.req.param("id");
const tree = await kv.get(["trees", id]);
if (!tree.value) {
return c.json({ message: "Tree not found" }, 404);
}
return c.json(tree.value);
});
为了测试,让我们运行一个获取数据的 curl 请求
curl https://:8000/trees/1
或者您可以在浏览器中访问:https://:8000/trees/1
当然,我们可以更新一棵树。这有点像之前,但我们将为此创建一个路由
app.put("/trees/:id", (c) => {
const id = c.req.param("id");
const { species, age, location } = c.req.json();
const updatedTree: Tree = { id, species, age, location };
setItem(`trees_${id}`, updatedTree);
return c.json({
message: `Tree has relocated to ${location}!`,
});
});
我们将更改位置,因为我们将把这棵树 PUT 到其他地方
curl -X PUT https://:8000/trees/1 \
-H "Content-Type: application/json" \
-d '{"species": "Oak", "age": 8, "location": "Theft Park"}'
最后,如果我们要删除一棵树,我们可以使用 Hono 的 delete 函数。
const deleteItem = (key: string) => {
localStorage.removeItem(key);
};
app.delete("/trees/:id", (c) => {
const id = c.req.param("id");
deleteItem(`trees_${id}`);
return c.json({
message: `Tree ${id} has been cut down!`,
});
});
我们结合 Deno 和 Hono 为我们的树数据构建了一个小型的 REST API。如果我们想部署它,我们可以做到,并且可以零配置部署到 Deno Deploy。
您可以使用 官方 Docker 镜像 将其部署到任何云 VPS,如 AWS、GCP、Digital Ocean。
完整的代码示例 跳转到标题
import { Hono } from "@hono/hono";
const app = new Hono();
interface Tree {
id: string;
species: string;
age: number;
location: string;
}
const setItem = (key: string, value: Tree) => {
localStorage.setItem(key, JSON.stringify(value));
};
const getItem = (key: string): Tree | null => {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : null;
};
const deleteItem = (key: string) => {
localStorage.removeItem(key);
};
const oak: Tree = {
id: "3",
species: "oak",
age: 3,
location: "Jim's Park",
};
setItem(`trees_${oak.id}`, oak);
const newTree = getItem(`trees_${oak.id}`);
console.log(newTree);
app.get("/", (c) => {
return c.text("Hello from the Trees!");
});
app.post("/trees", async (c) => {
const { id, species, age, location } = await c.req.json();
const tree: Tree = { id, species, age, location };
setItem(`trees_${id}`, tree);
return c.json({
message: `We just added a ${species} tree!`,
});
});
app.get("/trees/:id", async (c) => {
const id = await c.req.param("id");
const tree = getItem(`trees_${id}`);
if (!tree) {
return c.json({ message: "Tree not found" }, 404);
}
return c.json(tree);
});
app.put("/trees/:id", async (c) => {
const id = c.req.param("id");
const { species, age, location } = await c.req.json();
const updatedTree: Tree = { id, species, age, location };
setItem(`trees_${id}`, updatedTree);
return c.json({
message: `Tree has relocated to ${location}!`,
});
});
app.delete("/trees/:id", (c) => {
const id = c.req.param("id");
deleteItem(`trees_${id}`);
return c.json({
message: `Tree ${id} has been cut down!`,
});
});
Deno.serve(app.fetch);