fix: 质量修复 — ESLint 规则 TS6 兼容 + catch 注解 + 空函数体注释化 + 后端架构对齐 + 前端红线修复

- enforce-catch-type: 增加 TSUnknownKeyword 判断,消除28个 TS6 假阳性
- no-empty-function: 统一为注释方案,移除测试/生产分支和 eslint-disable 引导
- logger.ts: 空函数体改为注释说明,删除无用 eslint-disable 指令
- 补充15处 catch 子句 : unknown 类型注解
- 清理7个测试文件失效 eslint-disable 指令
- chat/send.ts: 提取 getModelWithProvider DAO,消除直接 Drizzle 操作
- projects/update.ts: 修复死代码+条件逻辑 bug
- providers/update.ts: 补充至少一个字段校验
- 前端: inline style → CSS className, ProviderFormModal whitespace 校验
- 开发文档: 更新 Zod 使用说明(AI SDK 框架级约束)
This commit is contained in:
2026-06-01 23:11:42 +08:00
parent 0d60120219
commit ab7b7fb189
28 changed files with 124 additions and 83 deletions

View File

@@ -25,6 +25,9 @@ export const enforceCatchType = {
if (type?.type === "TSTypeReference") {
return type.typeName?.name === "unknown";
}
if (type?.type === "TSUnknownKeyword") {
return true;
}
return false;
}
@@ -45,12 +48,7 @@ export const enforceCatchType = {
}
}
if (
body &&
body.type === "BlockStatement" &&
body.body.length === 0 &&
!hasCommentsInBody(body)
) {
if (body && body.type === "BlockStatement" && body.body.length === 0 && !hasCommentsInBody(body)) {
context.report({ node: body, messageId: "emptyCatchNoComment" });
}
}
@@ -59,4 +57,4 @@ export const enforceCatchType = {
CatchClause: check,
};
},
};
};

View File

@@ -2,14 +2,10 @@ export const noEmptyFunction = {
meta: {
type: "problem",
docs: {
description:
"禁止空函数体,并提供项目约定的修复指引:生产代码使用 () => undefined测试代码使用 () => {} + eslint-disable",
description: "禁止空函数体。修复方式在函数体内添加注释说明为何为空实现如接口契约、测试桩、noop。",
},
messages: {
unexpectedProduction:
"生产代码中空函数应使用 () => undefined 明确表意(如 noop/voidLog。如果确需空实现且为接口契约请添加注释说明原因。",
unexpectedTest:
"测试代码中空函数使用 () => {} 并在文件顶部添加 /* eslint-disable @typescript-eslint/no-empty-function */。",
unexpected: "空函数体禁止使用。请在 {} 内添加注释说明原因,例如:/* 实现 Logger 接口契约,有意静默丢弃 */。",
},
schema: [],
},
@@ -17,17 +13,11 @@ export const noEmptyFunction = {
create(context) {
const sourceCode = context.sourceCode ?? context.getSourceCode();
const allowedFunctionTypes = new Set([
"ArrowFunctionExpression",
"FunctionDeclaration",
"FunctionExpression",
]);
const allowedFunctionTypes = new Set(["ArrowFunctionExpression", "FunctionDeclaration", "FunctionExpression"]);
function isEmptyBody(body) {
return (
body.type === "BlockStatement" &&
body.body.length === 0 &&
sourceCode.getCommentsInside(body).length === 0
body.type === "BlockStatement" && body.body.length === 0 && sourceCode.getCommentsInside(body).length === 0
);
}
@@ -54,12 +44,9 @@ export const noEmptyFunction = {
if (isPrivateOrProtectedConstructor(node)) return;
if (isOverrideMethod(node)) return;
const isTest = /[\\/]tests?[\\/]/.test(context.filename ?? "") || context.filename?.includes("test");
context.report({
node,
messageId: isTest ? "unexpectedTest" : "unexpectedProduction",
data: { name: node.id?.name ?? node.key?.name ?? "function" },
messageId: "unexpected",
});
}