repo-tools/type-deps: support nested declaration files
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -2,4 +2,4 @@
|
||||
'@backstage/repo-tools': patch
|
||||
---
|
||||
|
||||
The `type-deps` command now detects ambient global types from the `jest` namespace in declaration files, rather than only looking for explicit imports and reference directives.
|
||||
The `type-deps` command now follows relative imports and re-exports into declaration chunk files, and detects ambient global types such as the `jest` namespace.
|
||||
|
||||
@@ -78,6 +78,50 @@ function shouldCheckTypes(pkg: Package & PackageJsonWithTypes) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a declaration file and recursively follow all relative imports and
|
||||
* re-exports, collecting the source content of each file encountered.
|
||||
*/
|
||||
function collectDeclSources(entryPath: string): string[] {
|
||||
const visited = new Set<string>();
|
||||
const sources: string[] = [];
|
||||
|
||||
function visit(filePath: string) {
|
||||
const resolved = resolvePath(filePath);
|
||||
if (visited.has(resolved)) {
|
||||
return;
|
||||
}
|
||||
visited.add(resolved);
|
||||
|
||||
// Handle .js -> .d.ts extension mapping used by declaration chunk files
|
||||
let actualPath = resolved;
|
||||
if (!fs.existsSync(actualPath)) {
|
||||
actualPath = resolved.replace(/\.js$/, '.d.ts');
|
||||
}
|
||||
if (!fs.existsSync(actualPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const src = fs.readFileSync(actualPath, 'utf8');
|
||||
sources.push(src);
|
||||
|
||||
// Follow relative imports and re-exports into chunk files
|
||||
const relativeRefs = (
|
||||
src.match(/^(?:import|export) .* from '\..*';$/gm) || []
|
||||
)
|
||||
.map(match => match.match(/from '(.*)'/)?.[1] ?? '')
|
||||
.filter(n => n.startsWith('.'));
|
||||
|
||||
const dir = resolvePath(actualPath, '..');
|
||||
for (const ref of relativeRefs) {
|
||||
visit(resolvePath(dir, ref));
|
||||
}
|
||||
}
|
||||
|
||||
visit(entryPath);
|
||||
return sources;
|
||||
}
|
||||
|
||||
function findAllDeps(declSrc: string) {
|
||||
const importedDeps = (declSrc.match(/^import .* from '.*';$/gm) || [])
|
||||
.map(match => match.match(/from '(.*)'/)?.[1] ?? '')
|
||||
@@ -112,11 +156,8 @@ function findAllDeps(declSrc: string) {
|
||||
*/
|
||||
function checkTypes(pkg: Package) {
|
||||
const allDeps = getPackageExportDetails(pkg.packageJson).flatMap(exp => {
|
||||
const typeDecl = fs.readFileSync(
|
||||
resolvePath(pkg.dir, 'dist', exp.distPath),
|
||||
'utf8',
|
||||
);
|
||||
return findAllDeps(typeDecl);
|
||||
const entryPath = resolvePath(pkg.dir, 'dist', exp.distPath);
|
||||
return collectDeclSources(entryPath).flatMap(src => findAllDeps(src));
|
||||
});
|
||||
const deps = Array.from(new Set(allDeps));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user