feat: 全栈 Logger 依赖注入 — DB/Route/AI 层传参 + 前端 Logger + 测试更新 + 归档 add-frontend-logger

This commit is contained in:
2026-06-01 20:32:19 +08:00
parent 4c72754739
commit 844562303c
60 changed files with 1648 additions and 778 deletions

View File

@@ -11,6 +11,7 @@ import {
restoreProject,
updateProject,
} from "../../../src/server/db/projects";
import { createNoopLogger } from "../../../src/server/logger";
import { createMigratedTestDatabase } from "../../helpers";
function withProjectsDb(callback: (db: Database) => void): void {
@@ -26,7 +27,7 @@ function withProjectsDb(callback: (db: Database) => void): void {
describe("项目数据访问层", () => {
test("创建项目", () => {
withProjectsDb((db) => {
const result = createProject(db, { description: "测试描述", name: "测试项目" });
const result = createProject(db, { description: "测试描述", name: "测试项目" }, createNoopLogger());
expect("error" in result).toBe(false);
expect((result as { project: unknown }).project).toBeDefined();
@@ -43,8 +44,8 @@ describe("项目数据访问层", () => {
test("项目名称全局唯一(含归档项目)", () => {
withProjectsDb((db) => {
createProject(db, { name: "唯一名称" });
const result2 = createProject(db, { name: "唯一名称" });
createProject(db, { name: "唯一名称" }, createNoopLogger());
const result2 = createProject(db, { name: "唯一名称" }, createNoopLogger());
expect("error" in result2).toBe(true);
expect((result2 as unknown as { error: string }).error).toContain("已存在");
});
@@ -52,7 +53,7 @@ describe("项目数据访问层", () => {
test("trim 后名称为空时创建失败", () => {
withProjectsDb((db) => {
const result = createProject(db, { name: " " });
const result = createProject(db, { name: " " }, createNoopLogger());
expect("error" in result).toBe(true);
expect((result as unknown as { error: string }).error).toContain("不能为空");
});
@@ -60,9 +61,9 @@ describe("项目数据访问层", () => {
test("列表查询(分页和关键字)", () => {
withProjectsDb((db) => {
createProject(db, { description: "descA", name: "项目A" });
createProject(db, { description: "descB", name: "项目B" });
createProject(db, { name: "其他" });
createProject(db, { description: "descA", name: "项目A" }, createNoopLogger());
createProject(db, { description: "descB", name: "项目B" }, createNoopLogger());
createProject(db, { name: "其他" }, createNoopLogger());
const result1 = listProjects(db, { page: 1, pageSize: 20 });
expect(result1.total).toBe(3);
@@ -79,7 +80,7 @@ describe("项目数据访问层", () => {
test("获取项目详情", () => {
withProjectsDb((db) => {
const created = createProject(db, { description: "详情", name: "详情项目" });
const created = createProject(db, { description: "详情", name: "详情项目" }, createNoopLogger());
const id = (created as { project: { id: string } }).project.id;
const result = getProject(db, id);
@@ -99,10 +100,10 @@ describe("项目数据访问层", () => {
test("更新项目名称和描述", () => {
withProjectsDb((db) => {
const created = createProject(db, { name: "原名" });
const created = createProject(db, { name: "原名" }, createNoopLogger());
const id = (created as { project: { id: string } }).project.id;
const result = updateProject(db, id, { description: "新描述", name: "新名" });
const result = updateProject(db, id, { description: "新描述", name: "新名" }, createNoopLogger());
expect("error" in result).toBe(false);
const updated = result as { project: { description: string; name: string } };
@@ -113,11 +114,11 @@ describe("项目数据访问层", () => {
test("更新已归档项目失败", () => {
withProjectsDb((db) => {
const created = createProject(db, { name: "待归档" });
const created = createProject(db, { name: "待归档" }, createNoopLogger());
const id = (created as { project: { id: string } }).project.id;
archiveProject(db, id);
archiveProject(db, id, createNoopLogger());
const result = updateProject(db, id, { name: "新名称" });
const result = updateProject(db, id, { name: "新名称" }, createNoopLogger());
expect("error" in result).toBe(true);
expect((result as unknown as { status: number }).status).toBe(409);
});
@@ -125,10 +126,10 @@ describe("项目数据访问层", () => {
test("归档项目", () => {
withProjectsDb((db) => {
const created = createProject(db, { name: "待归档" });
const created = createProject(db, { name: "待归档" }, createNoopLogger());
const id = (created as { project: { id: string } }).project.id;
const result = archiveProject(db, id);
const result = archiveProject(db, id, createNoopLogger());
expect("error" in result).toBe(false);
const archived = (result as { project: { archivedAt: null | string; status: string } }).project;
@@ -146,10 +147,10 @@ describe("项目数据访问层", () => {
test("对已归档项目重复归档失败", () => {
withProjectsDb((db) => {
const created = createProject(db, { name: "测试" });
const created = createProject(db, { name: "测试" }, createNoopLogger());
const id = (created as { project: { id: string } }).project.id;
archiveProject(db, id);
const result = archiveProject(db, id);
archiveProject(db, id, createNoopLogger());
const result = archiveProject(db, id, createNoopLogger());
expect("error" in result).toBe(true);
expect((result as unknown as { status: number }).status).toBe(409);
});
@@ -157,11 +158,11 @@ describe("项目数据访问层", () => {
test("恢复已归档项目", () => {
withProjectsDb((db) => {
const created = createProject(db, { name: "恢复测试" });
const created = createProject(db, { name: "恢复测试" }, createNoopLogger());
const id = (created as { project: { id: string } }).project.id;
archiveProject(db, id);
archiveProject(db, id, createNoopLogger());
const result = restoreProject(db, id);
const result = restoreProject(db, id, createNoopLogger());
expect("error" in result).toBe(false);
const restored = (result as { project: { archivedAt: null | string; status: string } }).project;
@@ -172,9 +173,9 @@ describe("项目数据访问层", () => {
test("恢复 active 项目失败", () => {
withProjectsDb((db) => {
const created = createProject(db, { name: "活跃项目" });
const created = createProject(db, { name: "活跃项目" }, createNoopLogger());
const id = (created as { project: { id: string } }).project.id;
const result = restoreProject(db, id);
const result = restoreProject(db, id, createNoopLogger());
expect("error" in result).toBe(true);
expect((result as unknown as { status: number }).status).toBe(409);
});
@@ -182,11 +183,11 @@ describe("项目数据访问层", () => {
test("永久删除已归档项目", () => {
withProjectsDb((db) => {
const created = createProject(db, { name: "删除测试" });
const created = createProject(db, { name: "删除测试" }, createNoopLogger());
const id = (created as { project: { id: string } }).project.id;
archiveProject(db, id);
archiveProject(db, id, createNoopLogger());
const result = deleteProject(db, id);
const result = deleteProject(db, id, createNoopLogger());
expect("error" in result).toBe(false);
const after = getProject(db, id);
@@ -196,10 +197,10 @@ describe("项目数据访问层", () => {
test("删除 active 项目失败", () => {
withProjectsDb((db) => {
const created = createProject(db, { name: "活跃项目" });
const created = createProject(db, { name: "活跃项目" }, createNoopLogger());
const id = (created as { project: { id: string } }).project.id;
const result = deleteProject(db, id);
const result = deleteProject(db, id, createNoopLogger());
expect("error" in result).toBe(true);
expect((result as unknown as { status: number }).status).toBe(409);
});
@@ -207,7 +208,7 @@ describe("项目数据访问层", () => {
test("创建项目名称超过 10 个字符失败", () => {
withProjectsDb((db) => {
const result = createProject(db, { name: "这是一个非常非常长的名字" });
const result = createProject(db, { name: "这是一个非常非常长的名字" }, createNoopLogger());
expect("error" in result).toBe(true);
expect((result as unknown as { error: string }).error).toContain("不能超过 10 个字符");
});
@@ -215,7 +216,7 @@ describe("项目数据访问层", () => {
test("创建项目名称刚好 10 个字符成功", () => {
withProjectsDb((db) => {
const result = createProject(db, { name: "一二三四五六七八九十" });
const result = createProject(db, { name: "一二三四五六七八九十" }, createNoopLogger());
expect("error" in result).toBe(false);
const project = (result as { project: { name: string } }).project;
expect(project.name).toBe("一二三四五六七八九十");
@@ -224,10 +225,10 @@ describe("项目数据访问层", () => {
test("更新项目名称超过 10 个字符失败", () => {
withProjectsDb((db) => {
const created = createProject(db, { name: "短名" });
const created = createProject(db, { name: "短名" }, createNoopLogger());
const id = (created as { project: { id: string } }).project.id;
const result = updateProject(db, id, { name: "这是一个非常非常长的名字" });
const result = updateProject(db, id, { name: "这是一个非常非常长的名字" }, createNoopLogger());
expect("error" in result).toBe(true);
expect((result as unknown as { error: string }).error).toContain("不能超过 10 个字符");
});
@@ -235,10 +236,10 @@ describe("项目数据访问层", () => {
test("更新项目名称 trim 后为空失败", () => {
withProjectsDb((db) => {
const created = createProject(db, { name: "原名" });
const created = createProject(db, { name: "原名" }, createNoopLogger());
const id = (created as { project: { id: string } }).project.id;
const result = updateProject(db, id, { name: " " });
const result = updateProject(db, id, { name: " " }, createNoopLogger());
expect("error" in result).toBe(true);
expect((result as unknown as { error: string }).error).toContain("不能为空");
});