全局启用 no-console: error 规则,强制服务端 .ts 文件使用 createModuleLogger。豁免场景: scripts/(脚本)、tests/(测试)、src/**/*.tsx(客户端组件,留待 Task 12-14 处理)、src/**/hooks/**/*.ts(客户端 hooks)、src/**/components/**/*.ts(客户端 utils)、src/shared/lib/query-client.ts(被客户端导入)。将 deletes/ 归档目录加入 globalIgnores。
152 lines
4.6 KiB
JavaScript
152 lines
4.6 KiB
JavaScript
import { defineConfig, globalIgnores } from "eslint/config";
|
|
import nextVitals from "eslint-config-next/core-web-vitals";
|
|
import nextTs from "eslint-config-next/typescript";
|
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
import { dirname, join } from "node:path";
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
|
const eslintConfig = defineConfig([
|
|
...nextVitals,
|
|
...nextTs,
|
|
{
|
|
rules: {
|
|
"react-hooks/incompatible-library": "off",
|
|
"@typescript-eslint/no-unused-vars": [
|
|
"warn",
|
|
{
|
|
argsIgnorePattern: "^_",
|
|
varsIgnorePattern: "^_",
|
|
caughtErrorsIgnorePattern: "^_",
|
|
},
|
|
],
|
|
// 禁止硬编码 hex 颜色字面量(白名单:tokens 定义文件、邮件、manifest)
|
|
// 白名单文件内的 #hex 需在所在行上方加 // eslint-disable-next-line no-restricted-syntax 注释豁免
|
|
"no-restricted-syntax": [
|
|
"error",
|
|
{
|
|
selector: "Literal[value=/#[0-9a-fA-F]{3,8}/]",
|
|
message:
|
|
"禁止硬编码 hex 颜色,使用设计令牌 hsl(var(--*)) 或 Tailwind 类 bg-*",
|
|
},
|
|
],
|
|
// 禁止 console.* 调用,统一使用 createModuleLogger("module-name")
|
|
// 豁免场景:scripts/、tests/、客户端 .tsx(留待客户端错误上报机制处理)、被客户端导入的 .ts
|
|
"no-console": "error",
|
|
},
|
|
},
|
|
{
|
|
files: ["tests/**/*.ts"],
|
|
languageOptions: {
|
|
globals: {
|
|
describe: "readonly",
|
|
it: "readonly",
|
|
test: "readonly",
|
|
expect: "readonly",
|
|
beforeAll: "readonly",
|
|
afterAll: "readonly",
|
|
beforeEach: "readonly",
|
|
afterEach: "readonly",
|
|
vi: "readonly",
|
|
},
|
|
},
|
|
},
|
|
// 自定义规则:检测硬编码字体家族字面量
|
|
{
|
|
plugins: {
|
|
"design-tokens": {
|
|
rules: {
|
|
"no-hardcoded-fonts": await import(
|
|
pathToFileURL(join(__dirname, "eslint-rules/no-hardcoded-design-tokens.js")).href
|
|
).then((m) => m.default ?? m),
|
|
},
|
|
},
|
|
},
|
|
rules: {
|
|
"design-tokens/no-hardcoded-fonts": "error",
|
|
},
|
|
},
|
|
// 缓存策略规则:禁止在 actions / route.ts 中直接调用 revalidatePath/revalidateTag
|
|
{
|
|
files: ["src/modules/**/actions*.ts", "src/app/api/**/route.ts", "src/i18n/actions*.ts"],
|
|
rules: {
|
|
"no-restricted-syntax": [
|
|
"error",
|
|
{
|
|
selector: "CallExpression[callee.name='revalidatePath']",
|
|
message:
|
|
"使用 invalidateFor() 替代直接 revalidatePath(),参见 docs/architecture/004 缓存章节",
|
|
},
|
|
{
|
|
selector: "CallExpression[callee.name='revalidateTag']",
|
|
message:
|
|
"使用 invalidateFor() 替代直接 revalidateTag(),参见 docs/architecture/004 缓存章节",
|
|
},
|
|
],
|
|
},
|
|
},
|
|
// 豁免:shared/lib/cache/ 内部允许调用 revalidatePath/revalidateTag(invalidate.ts 内部实现)
|
|
{
|
|
files: ["src/shared/lib/cache/**/*.ts"],
|
|
rules: {
|
|
"no-restricted-syntax": "off",
|
|
},
|
|
},
|
|
// 豁免:scripts/ 和 tests/ 允许 console(脚本/测试场景不接入 logger)
|
|
{
|
|
files: ["scripts/**/*.{js,mjs,ts}", "tests/**/*.{ts,tsx,js}"],
|
|
rules: {
|
|
"no-console": "off",
|
|
},
|
|
},
|
|
// 暂时豁免:客户端 .tsx 文件中的 console 调用,留待客户端错误上报机制(Task 12-14)处理
|
|
// 客户端组件不能导入服务端 pino logger,需通过 useErrorReport Hook 上报
|
|
{
|
|
files: ["src/**/*.tsx"],
|
|
rules: {
|
|
"no-console": "off",
|
|
},
|
|
},
|
|
// 豁免:客户端 hooks(.ts)被客户端组件导入,不能使用服务端 logger
|
|
// 留待 Task 12-14 客户端错误上报机制处理
|
|
{
|
|
files: ["src/**/hooks/**/*.ts"],
|
|
rules: {
|
|
"no-console": "off",
|
|
},
|
|
},
|
|
// 豁免:components 目录中的 .ts utils(如 exam-preview-utils.ts)被客户端 hooks 导入
|
|
{
|
|
files: ["src/**/components/**/*.ts"],
|
|
rules: {
|
|
"no-console": "off",
|
|
},
|
|
},
|
|
// 豁免:被客户端组件导入的 .ts 文件不能使用服务端 logger(如 query-client.ts 被 providers.tsx 导入)
|
|
{
|
|
files: ["src/shared/lib/query-client.ts"],
|
|
rules: {
|
|
"no-console": "off",
|
|
},
|
|
},
|
|
// Override default ignores of eslint-config-next.
|
|
globalIgnores([
|
|
// Default ignores of eslint-config-next:
|
|
".next/**",
|
|
"out/**",
|
|
"build/**",
|
|
"next-env.d.ts",
|
|
"docs/scripts/**",
|
|
"playwright-report/**",
|
|
"test-results/**",
|
|
// Debug scripts using CommonJS
|
|
"tests/webapp/debug_drizzle.js",
|
|
// Migration/maintenance scripts using CommonJS require()
|
|
"scripts/**/*.js",
|
|
// 已删除文件的归档目录,不参与 lint
|
|
"deletes/**",
|
|
]),
|
|
]);
|
|
|
|
export default eslintConfig;
|