Built Portfolio Page - Index Page

Index

More...

Build a Finance SaaS Platform - Index Page

Index

More...

从头开始创建一个自动产生文档/类型安全的现代API(18) 添加数据更新功能

添加更新数据的Hooks

为了能够方便调用 Hooks 修改数据,我对接口做了改造,body 参数加上了id,这样我们就可以在页面初始化时,不用指定 id,等调用时再根据 body 的 id 调用后台。
添加 hooks/use-update-task.ts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import { InferRequestType,InferResponseType } from "hono";
import { useMutation, useQueryClient } from "@tanstack/react-query";

import { client } from "@/lib/hono"

type ResponseType = InferResponseType<typeof client.tasks[":id"]["$patch"]>;
type RequestType = InferRequestType<typeof client.tasks[":id"]["$patch"]>["json"];

interface UpdateTaskPayload {
id: number;
name?: string;
done?: boolean;
order?: number;
};

export const useUpdateTask = ( ) => {
const queryClient = useQueryClient();

const mutation = useMutation<
ResponseType,
Error,
RequestType
>({
mutationFn: async (json) => {
const response = await client.tasks[":id"]["$patch"]({
json,
param: { id: json.id },
});
return response.json();
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey:["tasks"]});
},
onError: () => {
console.log("task update failed");
},
});

return mutation;
}
More...

从头开始创建一个自动产生文档/类型安全的现代API(17) 添加数据读取功能

添加读取数据的Hooks

首先安装依赖:

1
bun add @tanstack/react-query

添加 hooks/use-get-tasks-list.ts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { useQuery } from "@tanstack/react-query";
import { client } from "@/lib/hono"

export const useGetTasksList = () => {
const query = useQuery({
queryKey: ["tasks" ],
queryFn: async () => {
const res = await client.tasks.$get();

if(!res.ok){
throw new Error("Failed to fetch tasks list");
}

const data = await res.json();
return data;
},
});

return query;
};

添加支持模块 lib/hono.ts:

1
2
3
4
import { hc } from "hono/client";
import { AppType } from "@/app/api/[[...route]]/route";

export const client = hc<AppType>('/api');

注意:‘/api’ 是对应于 API 所在路径的。

More...

从头开始创建一个自动产生文档/类型安全的现代API(16) 添加字段

我们发现“顺序”这个字段缺失了,我们添加一下,顺便看一下如何变更数据结构。

修改数据结构

修改 db/schema.ts:

重新生成数据库

1
2
bun drizzle-kit generate
bun drizzle-kit push

修改page.tsx

修改interface:

1
2
3
4
5
6
interface Task {
id: number
name: string
done: boolean
order: number
}

修改 add 逻辑,点击 order:

1
2
3
4
5
6
7
8
9
10
11
case "added": {
return [
...tasks,
{
id: Date.now(),
name: action.name,
done: false,
order: tasks.length,
},
]
}
More...

从头开始创建一个自动产生文档/类型安全的现代API(15) 创建前端页面

现在我们开始创建前端页面。

利用 v0 快速输出前端页面

打开 v0 输入以下提示词:

帮忙编写一个网页,风格为现代偏科技,支持显示task list,task有name 和 done 两个属性,用户可以添加/修改/删除 task。
未完成的任务 最好显示为方框,完成后显示为打勾。
任务清单支持拖曳 调整 顺序。

通过几轮调整,页面基本符合要求。

More...

从头开始创建一个自动产生文档/类型安全的现代API(13) 设置测试环境

下面我们设置一下单元测试的环境,避免测试影响正常环境的数据。

添加测试环境配置文件

添加文件 .env.test:

1
2
3
4
NODE_ENV=development
PORT=3001
LOG_LEVEL=silent
DATABASE_URL=file:./test.db

修改环境变量读取程序

修改文件 utility/env.ts:

1
2
3
4
5
6
7
8
9
10
...
import path from "node:path";

expand(config({
path: path.resolve(
process.cwd(),
process.env.NODE_ENV === "test" ? ".env.test" : ".env",
),
}));
...
More...

从头开始创建一个自动产生文档/类型安全的现代API(11) 按id删除任务

下面我们给 API 添加按id删除任务。

添加根据 ID 修改任务

添加路径

添加路径,修改app/api/[[...route]]/routes/tasks/tasks.routes.ts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
export const deleteById = createRoute({
tags: ["Tasks"],
path: "/tasks/{id}",
method: "delete",
request: {
params: IdParamsSchema,
},
responses: {
[HttpStatusCodes.NO_CONTENT]: {
description: "Task deleted",
},
[HttpStatusCodes.NOT_FOUND]: jsonContent(
notFoundSchema,
"The task was not found",
),
[HttpStatusCodes.UNPROCESSABLE_ENTITY]: jsonContent(
createErrorSchema(IdParamsSchema),
"Invalid id error",
),
},
});

...
export type DeleteByIdRoute = typeof deleteById;

添加实现

添加实现,修改 app/api/[[...route]]/routes/tasks/tasks.handlers.ts :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
export const deleteById: AppRouteHandler<DeleteByIdRoute> = async (c) => {
const { id } = c.req.valid("param");

const result = await db
.delete(tasks)
.where(eq(tasks.id, id));

if ( result.rowsAffected === 0 ) {
return c.json({ message: HttpstatusPhase.NOT_FOUND }, HttpStatusCodes.NOT_FOUND);
};

return c.body(null, HttpStatusCodes.NO_CONTENT );
};

...

添加引用

添加引用,修改 `` :

1
2
3
...
.openapi(routes.deleteById, handlers.deleteById);
...
More...

请我喝杯咖啡吧~

支付宝
微信