scripts/fixTsReferences.mjs (112 lines of code) (raw):
/**
* 原则上,package depends 中的本地 package 和 tsconfig 中的 references 应该是一一对应的。
* 如果两者不同,则应该检查并修复
*/
/*eslint-env node*/
import { argv } from 'process'
import { constants, fstat } from 'fs'
import { readFile, writeFile, copyFile, access } from 'fs/promises'
import path from 'path'
import jsonc from 'jsonc-parser'
import { execSync } from 'child_process'
import colors from 'colors/safe.js'
// console.log(argv)
// console.log(process.env.PWD)
// 不处理的package
import packageBlacklist from './ignore.mjs'
const packagesJSON = execSync('npx lerna ls --json --all').toString()
const packageALL = JSON.parse(packagesJSON)
// 黑名单过滤掉
const packages = packageALL.filter((pac) => {
let inBL = false
packageBlacklist.forEach((rule) => {
inBL = inBL || pac.location.includes(rule)
})
return !inBL
})
// console.log(packages)
// 所有可link的本地 pkg
const localPkgNames = packages.map((p) => p.name)
const pkgDict = {}
packages.forEach((p) => {
pkgDict[p.name] = p
})
for (const pkg of packages) {
const pjsonPath = path.resolve(pkg.location, 'package.json')
const tsconfigPath = path.resolve(pkg.location, 'tsconfig.json')
const pjson = await readFile(pjsonPath)
const dependents = JSON.parse(pjson).dependencies || {}
// 注意 tsconfig 不一定存在
try {
await access(tsconfigPath, constants.F_OK)
} catch (error) {
console.warn(`${pkg.name} do not have a tsconfig.json, skip.`)
continue
}
try {
const tsconfigJson = (await readFile(tsconfigPath)).toString()
// const errors = []
// const tsconfig = jsonc.parse(tsconfigJson, errors, {
// disallowComments: false,
// allowEmptyContent: true,
// allowTrailingComma: true,
// })
// const references = tsconfig.references || []
// 过滤 dependents 中的本地包
const localDepPkgs = Object.keys(dependents)
.filter((pkgName) => {
return localPkgNames.includes(pkgName)
})
.sort()
// 生成相对路径
const pathsShouldBe = []
localDepPkgs.map((pkgName) => {
// 被依赖的包
const depPkg = pkgDict[pkgName]
// 相对路径
const depReference = path.relative(pkg.location, depPkg.location)
pathsShouldBe.push(depReference)
// tsconfig中是否存在这个reference
// if (references.map((i) => i.path).includes(depReference)) {
// } else {
// console.warn('漏掉的 reference ', depReference)
// }
})
const referencesShouldBe = pathsShouldBe.map((ref) => {
return {
path: ref,
}
})
// 修改 jsonc
const editList = jsonc.modify(
tsconfigJson,
// NOTE 并不是标准的 json path
['references'],
referencesShouldBe,
{
formattingOptions: {
tabSize: 4,
insertSpaces: false,
},
isArrayInsertion: true,
}
)
// console.log(editList)
const newJson = jsonc.applyEdits(tsconfigJson, editList)
// console.log(newJson)
let refText = localDepPkgs.join(', ')
if (refText.length > 60) {
refText = refText.slice(0, 60) + '...'
}
console.log(
colors.rainbow('auto_ts_reference'),
colors.green(pkg.name),
'->',
colors.blue(refText)
)
await writeFile(tsconfigPath, newJson)
} catch (error) {
console.log(error)
console.log(pkg.name, tsconfigPath)
}
}