// 扫描源码 src 下所有 .vue/.js 的三方 import,列出目标工程 package.json 里没有的包。
|
// 一次性用途:避免在阶段3逐模块移植时反复被“依赖没装”打断构建。
|
import { readdirSync, readFileSync, statSync } from 'node:fs'
|
import path from 'node:path'
|
|
const SRC = 'D:/beforeProject/lims/lims-ruoyi-before/src'
|
const TARGET_PKG = 'D:/beforeProject/lims/lims-vue3/package.json'
|
const SRC_PKG = 'D:/beforeProject/lims/lims-ruoyi-before/package.json'
|
|
const tgt = JSON.parse(readFileSync(TARGET_PKG, 'utf8'))
|
const src = JSON.parse(readFileSync(SRC_PKG, 'utf8'))
|
const tgtDeps = { ...tgt.dependencies, ...tgt.devDependencies }
|
const srcDeps = { ...src.dependencies, ...src.devDependencies }
|
|
function* walk(dir) {
|
for (const name of readdirSync(dir)) {
|
const p = path.join(dir, name)
|
if (statSync(p).isDirectory()) yield* walk(p)
|
else if (/\.(vue|js|mjs)$/.test(name)) yield p
|
}
|
}
|
|
function pkgOf(spec) {
|
if (!spec) return null
|
if (spec.startsWith('.') || spec.startsWith('/') || spec.startsWith('@/') || spec.startsWith('~')) return null
|
if (!/^[@a-zA-Z]/.test(spec)) return null
|
const parts = spec.split('/')
|
return spec.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0]
|
}
|
|
const RE = /(?:^|[^\w.])(?:import\s+(?:[\s\S]*?\sfrom\s+)?|export\s+[\s\S]*?\sfrom\s+|require\()\s*['"]([^'"]+)['"]/g
|
const use = new Map() // pkg -> Set(files)
|
|
for (const file of walk(SRC)) {
|
const text = readFileSync(file, 'utf8')
|
let m
|
RE.lastIndex = 0
|
while ((m = RE.exec(text))) {
|
const pkg = pkgOf(m[1])
|
if (!pkg) continue
|
if (pkg === 'vue' || pkg === 'vue-router' || pkg === 'vuex' || pkg === 'pinia') continue
|
if (!use.has(pkg)) use.set(pkg, new Set())
|
use.get(pkg).add(path.relative(SRC, file).replace(/\\/g, '/'))
|
}
|
}
|
|
const missing = []
|
const present = []
|
for (const [pkg, files] of [...use].sort()) {
|
if (tgtDeps[pkg]) present.push([pkg, tgtDeps[pkg], srcDeps[pkg] || '-', files.size])
|
else missing.push([pkg, srcDeps[pkg] || '未在源码 package.json 声明', files.size, [...files].slice(0, 3)])
|
}
|
|
console.log('=== 目标工程缺失的包(' + missing.length + ')===')
|
for (const [pkg, sv, n, sample] of missing) {
|
console.log(` ${pkg.padEnd(30)} src=${String(sv).padEnd(10)} 引用文件数=${n} 例:${sample.join(', ')}`)
|
}
|
console.log('\n=== 已有(' + present.length + ')===')
|
for (const [pkg, tv, sv, n] of present) {
|
const flag = sv !== '-' && sv.replace(/[\^~]/g, '') !== String(tv).replace(/[\^~]/g, '') ? ' ← 版本不同' : ''
|
console.log(` ${pkg.padEnd(30)} tgt=${String(tv).padEnd(12)} src=${String(sv).padEnd(12)} 文件数=${n}${flag}`)
|
}
|