Skip to content

Commit 9e729e0

Browse files
authored
Merge pull request #494 from DEEIX-AI/update
refactor: upgrade to TypeScript 7 and update ESLint configuration
2 parents be5a41b + 3cb99c0 commit 9e729e0

115 files changed

Lines changed: 766 additions & 2710 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/pull_request_template.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
## Verification
3030

31-
<!-- List the commands or checks you ran. For example: cd backend && go test ./..., cd frontend && pnpm lint, cd frontend && pnpm build. -->
31+
<!-- List the commands or checks you ran. For example: cd backend && go test ./..., cd frontend && pnpm check, cd frontend && pnpm build. -->
3232

3333
- [ ] Not run; reason:
3434

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Frontend Quality
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- dev
8+
paths:
9+
- "frontend/**"
10+
- "scripts/sync-version.mjs"
11+
- "VERSION"
12+
- ".github/workflows/frontend-quality.yml"
13+
pull_request:
14+
branches:
15+
- main
16+
- dev
17+
paths:
18+
- "frontend/**"
19+
- "scripts/sync-version.mjs"
20+
- "VERSION"
21+
- ".github/workflows/frontend-quality.yml"
22+
workflow_dispatch:
23+
24+
permissions:
25+
contents: read
26+
27+
jobs:
28+
quality:
29+
name: Biome and TypeScript
30+
runs-on: ubuntu-24.04
31+
defaults:
32+
run:
33+
working-directory: frontend
34+
35+
steps:
36+
- name: Checkout
37+
uses: actions/checkout@v4
38+
39+
- name: Set up pnpm
40+
uses: pnpm/action-setup@v4
41+
with:
42+
version: 10.17.0
43+
run_install: false
44+
45+
- name: Set up Node.js
46+
uses: actions/setup-node@v4
47+
with:
48+
node-version: 24
49+
cache: pnpm
50+
cache-dependency-path: frontend/pnpm-lock.yaml
51+
52+
- name: Install dependencies
53+
run: pnpm install --frozen-lockfile
54+
55+
- name: Run frontend checks
56+
run: pnpm check

.gitignore

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ web_modules/
5151
# Optional npm cache directory
5252
.npm
5353

54-
# Optional eslint cache
55-
.eslintcache
56-
5754
# Optional stylelint cache
5855
.stylelintcache
5956

@@ -165,4 +162,4 @@ frontend/public/pwa/generated/
165162
docker-compose.local.yml
166163

167164
.DS_Store
168-
.idea
165+
.idea

frontend/BIOME.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Frontend Biome policy
2+
3+
DEEIX Chat uses Biome as the frontend linter. TypeScript 7 remains responsible for type checking; ESLint, `typescript-eslint`, and `eslint-config-next` are not part of the frontend toolchain.
4+
5+
## Commands
6+
7+
```bash
8+
pnpm check
9+
pnpm typecheck
10+
pnpm lint
11+
pnpm lint:fix
12+
```
13+
14+
`pnpm check` is the required non-mutating local and CI gate. It runs `pnpm lint` followed by `pnpm typecheck`. `lint:fix` applies safe Biome lint fixes only.
15+
16+
Formatting is intentionally outside this migration. Enabling a repository-wide formatter requires a separate mechanical baseline so lint-tooling changes remain reviewable and do not rewrite unrelated application files.
17+
18+
## Rule policy
19+
20+
Biome's recommended preset and the recommended React and Next.js domains are enabled in `biome.jsonc`. Project-specific deviations are listed explicitly so an upgrade cannot silently change the pull request gate.
21+
22+
- `error`: correctness, React hook ordering, duplicate JSX props, invalid React attributes, unsafe script usage, and concrete security defects. Errors fail `pnpm lint`.
23+
- `warn`: accessibility guidance, exhaustive hook dependencies, framework performance guidance, and Next.js conventions that can require project-specific exceptions. Warnings stay visible without blocking an otherwise valid build.
24+
- `off`: only for rules that are not reliable with the project's component abstractions. `useAriaPropsSupportedByRole` is disabled because Radix and polymorphic controls expose roles and ARIA attributes through runtime composition that Biome cannot resolve statically. `performance/noImgElement` is disabled because the application deliberately renders administrator-configured provider icons, arbitrary Markdown/tool images, and local previews whose URLs cannot be declared in a fixed Next image domain list.
25+
26+
Rule exceptions use file-scoped Biome overrides only for stable framework/library contracts. Inline suppressions are reserved for a single unavoidable statement and must include a reason. File-wide blanket disables and category-wide exceptions are not accepted.
27+
28+
The Animate UI registry owns `components/animate-ui/icons/icon.tsx` and exports its hook-backed helper as `getVariants`. That upstream API name is preserved so newly downloaded or overwritten registry components remain compatible; the Hook naming rule is disabled only for that exact registry-owned file.
29+
30+
## Migration coverage
31+
32+
Biome covers the correctness, hooks, accessibility, security, and performance rules that can be mapped from the former Next.js ESLint configuration. Biome 2.5 does not yet implement every React Compiler rule or every Next.js-specific rule. TypeScript and Next.js builds remain required checks, and unsupported rules should be reconsidered when Biome adds native equivalents.
33+
34+
Notable unsupported groups include React Compiler diagnostics such as immutability, refs, purity, set-state-in-render, and static component analysis, plus Next.js rules for page-specific HTML, Head, Script, and relative `location` assignments. These gaps are documented rather than hidden behind a second TypeScript runtime.

frontend/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,14 @@ NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8080
147147

148148
```bash
149149
pnpm dev
150+
pnpm check
150151
pnpm lint
152+
pnpm lint:fix
151153
pnpm build
152154
pnpm start
153155
```
154156

155-
当前 `package.json` 未配置单独的 `typecheck` 脚本,需要类型检查时使用框架构建或临时执行 TypeScript 检查命令
157+
`check` 依次运行 Biome 静态检查和 TypeScript 7 类型检查。规则范围、严重级别和框架例外见 [BIOME.md](./BIOME.md)
156158

157159
## 开发约束
158160

@@ -170,7 +172,7 @@ pnpm start
170172
## 提交前验证
171173

172174
```bash
173-
pnpm lint
175+
pnpm check
174176
```
175177

176178
涉及构建、路由、依赖或 Next.js 配置变更时再执行:

frontend/biome.jsonc

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
{
2+
"$schema": "https://biomejs.dev/schemas/2.5.4/schema.json",
3+
"vcs": {
4+
"enabled": true,
5+
"clientKind": "git",
6+
"useIgnoreFile": false
7+
},
8+
"files": {
9+
"ignoreUnknown": true,
10+
"includes": [
11+
"**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}",
12+
"!node_modules",
13+
"!.next",
14+
"!out",
15+
"!build",
16+
"!next-env.d.ts",
17+
"!public/sw.js",
18+
"!public/vendor",
19+
"!shared/generated"
20+
]
21+
},
22+
"formatter": {
23+
"enabled": false
24+
},
25+
"linter": {
26+
"enabled": true,
27+
"domains": {
28+
"next": "recommended",
29+
"react": "recommended"
30+
},
31+
"rules": {
32+
"preset": "recommended",
33+
"a11y": {
34+
"noLabelWithoutControl": "off",
35+
"noStaticElementInteractions": "off",
36+
"noSvgWithoutTitle": "off",
37+
"useAriaPropsSupportedByRole": "off",
38+
"useSemanticElements": "off"
39+
},
40+
"correctness": {
41+
"noUnusedFunctionParameters": "off",
42+
"useExhaustiveDependencies": {
43+
"level": "warn",
44+
"options": {
45+
"reportUnnecessaryDependencies": false
46+
}
47+
},
48+
"useImageSize": "off"
49+
},
50+
"nursery": {
51+
"noComponentHookFactories": "error",
52+
"noReactStringRefs": "error"
53+
},
54+
"performance": {
55+
"noBarrelFile": "off",
56+
"noImgElement": "off",
57+
"noNamespaceImport": "off",
58+
"useTopLevelRegex": "off"
59+
},
60+
"suspicious": {
61+
"noAlert": "off",
62+
"noArrayIndexKey": "off",
63+
"noDocumentCookie": "off",
64+
"noEmptyBlockStatements": "off",
65+
"noShadowRestrictedNames": "off",
66+
"useAwait": "off"
67+
},
68+
"complexity": {
69+
"noExcessiveCognitiveComplexity": "off",
70+
"noUselessFragments": "off",
71+
"noUselessSwitchCase": "off",
72+
"useOptionalChain": "off"
73+
},
74+
"style": {
75+
"noNestedTernary": "off",
76+
"noNonNullAssertion": "off",
77+
"useBlockStatements": "off",
78+
"useConsistentTypeDefinitions": "off",
79+
"useConst": "off",
80+
"useImportType": "off"
81+
}
82+
}
83+
},
84+
"overrides": [
85+
{
86+
"includes": ["components/animate-ui/icons/icon.tsx"],
87+
"linter": {
88+
"rules": {
89+
"correctness": {
90+
"useExhaustiveDependencies": "off",
91+
"useHookAtTopLevel": "off"
92+
}
93+
}
94+
}
95+
},
96+
{
97+
"includes": ["components/animate-ui/utils/get-strict-context.tsx"],
98+
"linter": {
99+
"rules": {
100+
"nursery": {
101+
"noComponentHookFactories": "off"
102+
}
103+
}
104+
}
105+
},
106+
{
107+
"includes": ["shared/components/file-preview/preview-docx.tsx"],
108+
"linter": {
109+
"rules": {
110+
"suspicious": {
111+
"noUnknownAttribute": "off"
112+
}
113+
}
114+
}
115+
},
116+
{
117+
"includes": [
118+
"components/ui/live-waveform.tsx",
119+
"components/ui/virtual-table.tsx",
120+
"shared/components/file-preview/preview-document.tsx"
121+
],
122+
"linter": {
123+
"rules": {
124+
"a11y": {
125+
"noAriaHiddenOnFocusable": "off"
126+
}
127+
}
128+
}
129+
},
130+
{
131+
"includes": [
132+
"features/admin/components/sections/billing/billing-redemption.tsx",
133+
"features/chat/components/message/message-meta.tsx"
134+
],
135+
"linter": {
136+
"rules": {
137+
"a11y": {
138+
"noNoninteractiveTabindex": "off"
139+
}
140+
}
141+
}
142+
},
143+
{
144+
"includes": [
145+
"features/chat/components/sections/chat-input.tsx",
146+
"features/layouts/components/navigation/sidebar-conversation-item.tsx",
147+
"features/settings/components/sections/chat/settings-chat.tsx"
148+
],
149+
"linter": {
150+
"rules": {
151+
"a11y": {
152+
"noAutofocus": "off"
153+
}
154+
}
155+
}
156+
},
157+
{
158+
"includes": ["shared/components/file-preview/preview-media.tsx"],
159+
"linter": {
160+
"rules": {
161+
"a11y": {
162+
"useMediaCaption": "off"
163+
}
164+
}
165+
}
166+
},
167+
{
168+
"includes": ["components/ui/input-group.tsx"],
169+
"linter": {
170+
"rules": {
171+
"a11y": {
172+
"useKeyWithClickEvents": "off"
173+
}
174+
}
175+
}
176+
}
177+
]
178+
}

frontend/components/animate-ui/icons/arrow-right.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use client';
22

3-
import * as React from 'react';
43
import { motion, type Variants } from 'motion/react';
54

65
import {

frontend/components/animate-ui/icons/audio-lines.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use client';
22

3-
import * as React from 'react';
43
import { motion, type Variants } from 'motion/react';
54

65
import {

frontend/components/animate-ui/icons/binary.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use client';
22

3-
import * as React from 'react';
43
import { motion, type Variants } from 'motion/react';
54

65
import {

frontend/components/animate-ui/icons/blend.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use client';
22

3-
import * as React from 'react';
43
import { motion, type Variants } from 'motion/react';
54

65
import {

0 commit comments

Comments
 (0)