987a576423
Closes #2800 This PR makes it so that `check-scripts` will error out if you forget to add a "references" entry to a tsconfig file when adding an internal dependency in our monorepo. If these project references are missed it can prevent TS from building/rebuilding things when they need to be built/rebuilt. ### Change Type - [x] `internal` — Any other changes that don't affect the published package[^2]
100 lines
2.9 KiB
TypeScript
100 lines
2.9 KiB
TypeScript
import kleur from 'kleur'
|
|
import { join, relative } from 'path'
|
|
import { readJsonIfExists, writeJsonFile } from './lib/file'
|
|
import { nicelog } from './lib/nicelog'
|
|
import { Package, getAllWorkspacePackages } from './lib/workspace'
|
|
|
|
const packagesWithoutTSConfigs: ReadonlySet<string> = new Set(['config'])
|
|
|
|
async function checkTsConfigs({ packages, fix }: { fix?: boolean; packages: Package[] }) {
|
|
let numErrors = 0
|
|
|
|
for (const workspace of packages) {
|
|
const tsconfigPath = join(workspace.path, 'tsconfig.json')
|
|
if (packagesWithoutTSConfigs.has(workspace.name)) {
|
|
continue
|
|
}
|
|
|
|
const tsconfig = (await readJsonIfExists(tsconfigPath)) as {
|
|
references?: { path: string }[]
|
|
}
|
|
if (!tsconfig) {
|
|
throw new Error('No tsconfig.json found at ' + tsconfigPath)
|
|
}
|
|
|
|
const tldrawDeps = Object.keys({
|
|
...workspace.packageJson.dependencies,
|
|
...workspace.packageJson.devDependencies,
|
|
}).filter((dep) => dep.startsWith('@tldraw/'))
|
|
|
|
const fixedDeps = []
|
|
const missingRefs = []
|
|
const currentRefs = new Set<string>([...(tsconfig.references?.map((ref) => ref.path) ?? [])])
|
|
for (const dep of tldrawDeps) {
|
|
// construct the expected path to the dependency's tsconfig
|
|
const matchingWorkspace = packages.find((p) => p.name === dep)
|
|
if (!matchingWorkspace) {
|
|
throw new Error(`No workspace found for ${dep}`)
|
|
}
|
|
const tsconfigReferencePath = relative(workspace.path, matchingWorkspace.path)
|
|
fixedDeps.push({ path: tsconfigReferencePath })
|
|
if (currentRefs.has(tsconfigReferencePath)) {
|
|
currentRefs.delete(tsconfigReferencePath)
|
|
} else {
|
|
missingRefs.push(dep)
|
|
}
|
|
}
|
|
|
|
fixedDeps.sort((a, b) => a.path.localeCompare(b.path))
|
|
if (currentRefs.size > 0) {
|
|
if (fix) {
|
|
tsconfig.references = fixedDeps
|
|
writeJsonFile(tsconfigPath, tsconfig)
|
|
} else {
|
|
numErrors++
|
|
nicelog(
|
|
[
|
|
'❌ ',
|
|
kleur.red(`${workspace.name}: `),
|
|
kleur.blue(relative(process.cwd(), tsconfigPath)),
|
|
kleur.grey(' has unnecessary reference(s) to '),
|
|
kleur.red([...currentRefs].join(', ')),
|
|
].join('')
|
|
)
|
|
}
|
|
}
|
|
if (missingRefs.length) {
|
|
if (fix) {
|
|
tsconfig.references = fixedDeps
|
|
writeJsonFile(tsconfigPath, tsconfig)
|
|
} else {
|
|
numErrors++
|
|
nicelog(
|
|
[
|
|
'❌ ',
|
|
kleur.red(`${workspace.name}: `),
|
|
kleur.blue(relative(process.cwd(), tsconfigPath)),
|
|
kleur.grey(' is missing reference(s) to '),
|
|
kleur.red(missingRefs.join(', ')),
|
|
].join('')
|
|
)
|
|
nicelog('The references entry should look like this:')
|
|
nicelog('"references": ' + JSON.stringify(fixedDeps, null, 2))
|
|
}
|
|
}
|
|
}
|
|
if (numErrors > 0) {
|
|
nicelog('Run `yarn check-tsconfigs --fix` to fix these problems')
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
async function main({ fix }: { fix?: boolean }) {
|
|
const packages = await getAllWorkspacePackages()
|
|
|
|
await checkTsConfigs({ packages, fix })
|
|
}
|
|
|
|
main({
|
|
fix: process.argv.includes('--fix'),
|
|
})
|