style: 完成所有文件的lint

This commit is contained in:
claude-code-best
2026-05-01 21:39:30 +08:00
parent d136872cc9
commit 6182015005
1333 changed files with 68255 additions and 77882 deletions

View File

@@ -12,69 +12,76 @@
* bun scripts/check-bundle-integrity.ts ./dist # 指定目录
*/
import { readdir, readFile } from "fs/promises"
import { join, resolve, dirname } from "path"
import { fileURLToPath } from "url"
import { readdir, readFile } from 'fs/promises'
import { join, resolve, dirname } from 'path'
import { fileURLToPath } from 'url'
// ─── 从 package.json 读取 dependencies 作为白名单 ────────────────
const __dirname = dirname(fileURLToPath(import.meta.url))
const pkg = JSON.parse(await readFile(join(__dirname, '..', 'package.json'), 'utf-8'))
const pkg = JSON.parse(
await readFile(join(__dirname, '..', 'package.json'), 'utf-8'),
)
const PKG_DEPS = new Set(Object.keys(pkg.dependencies ?? {}))
// ─── Node.js 内置模块白名单 ────────────────────────────────────────
const NODE_BUILTINS = new Set([
"assert",
"async_hooks",
"buffer",
"child_process",
"cluster",
"console",
"constants",
"crypto",
"dgram",
"diagnostics_channel",
"dns",
"domain",
"events",
"fs",
"fs/promises",
"http",
"http2",
"https",
"inspector",
"module",
"net",
"os",
"path",
"perf_hooks",
"process",
"punycode",
"querystring",
"readline",
"repl",
"stream",
"string_decoder",
"sys",
"timers",
"tls",
"tty",
"url",
"util",
"v8",
"vm",
"worker_threads",
"zlib",
"node:test",
'assert',
'async_hooks',
'buffer',
'child_process',
'cluster',
'console',
'constants',
'crypto',
'dgram',
'diagnostics_channel',
'dns',
'domain',
'events',
'fs',
'fs/promises',
'http',
'http2',
'https',
'inspector',
'module',
'net',
'os',
'path',
'perf_hooks',
'process',
'punycode',
'querystring',
'readline',
'repl',
'stream',
'string_decoder',
'sys',
'timers',
'tls',
'tty',
'url',
'util',
'v8',
'vm',
'worker_threads',
'zlib',
'node:test',
])
// Node 18+ 内置但不在传统列表中的模块
const NODE_18_PLUS_BUILTINS = new Set(["undici"])
const NODE_18_PLUS_BUILTINS = new Set(['undici'])
// Bun 专用模块(仅在 Bun 运行时可用Node.js 环境会失败)
const BUN_MODULES = new Set(["bun", "bun:ffi", "bun:test", "bun:sqlite"])
const BUN_MODULES = new Set(['bun', 'bun:ffi', 'bun:test', 'bun:sqlite'])
// macOS JXA / native 框架(通过 ObjC.import非真正的 require
const NATIVE_FRAMEWORKS = new Set(["AppKit", "CoreGraphics", "Foundation", "UIKit"])
const NATIVE_FRAMEWORKS = new Set([
'AppKit',
'CoreGraphics',
'Foundation',
'UIKit',
])
// ─── 模式 ──────────────────────────────────────────────────────────
// 匹配 import { ... } from "./chunk-xxxxx.js" 或 import"./chunk-xxxxx.js"
@@ -87,8 +94,13 @@ const DYNAMIC_IMPORT_RE = /import\("([^"]+)"\)/g
const NODE_REQUIRE_RE = /nodeRequire\("([^"]+)"\)/g
interface Finding {
type: "broken-chunk-ref" | "third-party-require" | "third-party-import" | "third-party-node-require" | "bun-runtime-only"
severity: "error" | "warning"
type:
| 'broken-chunk-ref'
| 'third-party-require'
| 'third-party-import'
| 'third-party-node-require'
| 'bun-runtime-only'
severity: 'error' | 'warning'
file: string
line: number
module: string
@@ -96,17 +108,17 @@ interface Finding {
}
async function main() {
const distDir = resolve(process.argv[2] || "./dist")
const distDir = resolve(process.argv[2] || './dist')
console.log(`\n🔍 检查构建产物完整性: ${distDir}\n`)
// 1. 列出所有 chunk 文件
let files: string[]
try {
files = (await readdir(distDir)).filter((f) => f.endsWith(".js"))
files = (await readdir(distDir)).filter(f => f.endsWith('.js'))
} catch {
console.error(`❌ 无法读取目录: ${distDir}`)
console.error(" 请先运行 bun run build")
console.error(' 请先运行 bun run build')
process.exit(1)
}
@@ -118,8 +130,8 @@ async function main() {
// 2. 逐文件扫描
for (const file of files) {
const filePath = join(distDir, file)
const content = await readFile(filePath, "utf-8")
const lines = content.split("\n")
const content = await readFile(filePath, 'utf-8')
const lines = content.split('\n')
for (let i = 0; i < lines.length; i++) {
const line = lines[i]
@@ -130,11 +142,11 @@ async function main() {
for (const m of staticImportMatches) {
const ref = m[1]
// 提取文件名部分(去掉 ./
const refFile = ref.replace(/^\.\//, "")
const refFile = ref.replace(/^\.\//, '')
if (!fileSet.has(refFile)) {
findings.push({
type: "broken-chunk-ref",
severity: "error",
type: 'broken-chunk-ref',
severity: 'error',
file,
line: lineNum,
module: ref,
@@ -149,11 +161,17 @@ async function main() {
const mod = m[1]
// 跳过 ObjC.importJXA 语法,不是真正的 require
if (NATIVE_FRAMEWORKS.has(mod)) continue
if (NODE_BUILTINS.has(mod) || NODE_18_PLUS_BUILTINS.has(mod) || PKG_DEPS.has(mod) || mod.startsWith("node:")) continue
if (
NODE_BUILTINS.has(mod) ||
NODE_18_PLUS_BUILTINS.has(mod) ||
PKG_DEPS.has(mod) ||
mod.startsWith('node:')
)
continue
if (BUN_MODULES.has(mod)) {
findings.push({
type: "bun-runtime-only",
severity: "warning",
type: 'bun-runtime-only',
severity: 'warning',
file,
line: lineNum,
module: mod,
@@ -163,8 +181,8 @@ async function main() {
}
// 第三方模块 — 在生产环境(全局 npm install中找不到
findings.push({
type: "third-party-require",
severity: "error",
type: 'third-party-require',
severity: 'error',
file,
line: lineNum,
module: mod,
@@ -177,15 +195,21 @@ async function main() {
for (const m of dynImportMatches) {
const mod = m[1]
// 跳过内部 chunk 引用和相对路径
if (mod.startsWith("./") || mod.startsWith("../")) continue
if (mod.startsWith('./') || mod.startsWith('../')) continue
// 跳过 ObjC.import
if (NATIVE_FRAMEWORKS.has(mod)) continue
if (NODE_BUILTINS.has(mod) || NODE_18_PLUS_BUILTINS.has(mod) || PKG_DEPS.has(mod) || mod.startsWith("node:")) continue
if (
NODE_BUILTINS.has(mod) ||
NODE_18_PLUS_BUILTINS.has(mod) ||
PKG_DEPS.has(mod) ||
mod.startsWith('node:')
)
continue
if (BUN_MODULES.has(mod)) {
// bun:test 等只在 Bun 运行时可用Node.js 运行时会失败
findings.push({
type: "bun-runtime-only",
severity: "warning",
type: 'bun-runtime-only',
severity: 'warning',
file,
line: lineNum,
module: mod,
@@ -195,8 +219,8 @@ async function main() {
}
// 第三方动态 import
findings.push({
type: "third-party-import",
severity: "error",
type: 'third-party-import',
severity: 'error',
file,
line: lineNum,
module: mod,
@@ -209,11 +233,17 @@ async function main() {
for (const m of nodeRequireMatches) {
const mod = m[1]
if (NATIVE_FRAMEWORKS.has(mod)) continue
if (NODE_BUILTINS.has(mod) || NODE_18_PLUS_BUILTINS.has(mod) || PKG_DEPS.has(mod) || mod.startsWith("node:")) continue
if (
NODE_BUILTINS.has(mod) ||
NODE_18_PLUS_BUILTINS.has(mod) ||
PKG_DEPS.has(mod) ||
mod.startsWith('node:')
)
continue
if (BUN_MODULES.has(mod)) {
findings.push({
type: "bun-runtime-only",
severity: "warning",
type: 'bun-runtime-only',
severity: 'warning',
file,
line: lineNum,
module: mod,
@@ -222,8 +252,8 @@ async function main() {
continue
}
findings.push({
type: "third-party-node-require",
severity: "error",
type: 'third-party-node-require',
severity: 'error',
file,
line: lineNum,
module: mod,
@@ -234,18 +264,22 @@ async function main() {
}
// 3. 汇总报告
const errors = findings.filter((f) => f.severity === "error")
const warnings = findings.filter((f) => f.severity === "warning")
const errors = findings.filter(f => f.severity === 'error')
const warnings = findings.filter(f => f.severity === 'warning')
// 按 type 分组
const brokenRefs = errors.filter((f) => f.type === "broken-chunk-ref")
const thirdPartyRequires = errors.filter((f) => f.type === "third-party-require")
const thirdPartyImports = errors.filter((f) => f.type === "third-party-import")
const thirdPartyNodeRequires = errors.filter((f) => f.type === "third-party-node-require")
const bunRuntimeOnly = warnings.filter((f) => f.type === "bun-runtime-only")
const brokenRefs = errors.filter(f => f.type === 'broken-chunk-ref')
const thirdPartyRequires = errors.filter(
f => f.type === 'third-party-require',
)
const thirdPartyImports = errors.filter(f => f.type === 'third-party-import')
const thirdPartyNodeRequires = errors.filter(
f => f.type === 'third-party-node-require',
)
const bunRuntimeOnly = warnings.filter(f => f.type === 'bun-runtime-only')
if (brokenRefs.length > 0) {
console.log("❌ 断裂的 chunk 引用(引用了不存在的文件):")
console.log('❌ 断裂的 chunk 引用(引用了不存在的文件):')
for (const f of brokenRefs) {
console.log(` ${f.file}:${f.line}${f.module}`)
}
@@ -253,7 +287,7 @@ async function main() {
}
if (thirdPartyRequires.length > 0) {
console.log("❌ 通过 __require() 引用的第三方模块(生产环境会找不到):")
console.log('❌ 通过 __require() 引用的第三方模块(生产环境会找不到):')
const grouped = groupByModule(thirdPartyRequires)
for (const [mod, items] of grouped) {
console.log(` "${mod}" — 出现 ${items.length} 次:`)
@@ -266,7 +300,7 @@ async function main() {
}
if (thirdPartyImports.length > 0) {
console.log("❌ 通过 import() 动态引用的第三方模块(生产环境会找不到):")
console.log('❌ 通过 import() 动态引用的第三方模块(生产环境会找不到):')
const grouped = groupByModule(thirdPartyImports)
for (const [mod, items] of grouped) {
console.log(` "${mod}" — 出现 ${items.length} 次:`)
@@ -279,7 +313,9 @@ async function main() {
}
if (thirdPartyNodeRequires.length > 0) {
console.log("❌ 通过 nodeRequire() 引用的第三方模块(绕过打包,生产环境会找不到):")
console.log(
'❌ 通过 nodeRequire() 引用的第三方模块(绕过打包,生产环境会找不到):',
)
const grouped = groupByModule(thirdPartyNodeRequires)
for (const [mod, items] of grouped) {
console.log(` "${mod}" — 出现 ${items.length} 次:`)
@@ -292,7 +328,7 @@ async function main() {
}
if (bunRuntimeOnly.length > 0) {
console.log("⚠️ Bun 运行时专用模块Node.js 环境会失败):")
console.log('⚠️ Bun 运行时专用模块Node.js 环境会失败):')
const grouped = groupByModule(bunRuntimeOnly)
for (const [mod, items] of grouped) {
console.log(` "${mod}" — 出现 ${items.length}`)
@@ -301,9 +337,9 @@ async function main() {
}
// 4. 总结
console.log("─".repeat(50))
console.log('─'.repeat(50))
if (errors.length === 0 && warnings.length === 0) {
console.log("✅ 构建产物完整性检查通过,未发现问题。")
console.log('✅ 构建产物完整性检查通过,未发现问题。')
} else {
console.log(`📊 总计: ${errors.length} 个错误, ${warnings.length} 个警告`)
if (errors.length > 0) {
@@ -330,7 +366,7 @@ function groupByModule(items: Finding[]): Map<string, Finding[]> {
return new Map([...map.entries()].sort((a, b) => b[1].length - a[1].length))
}
main().catch((err) => {
console.error("Fatal error:", err)
main().catch(err => {
console.error('Fatal error:', err)
process.exit(2)
})