Skip to content

Instantly share code, notes, and snippets.

@donmccurdy
Last active March 15, 2024 18:49
Show Gist options
  • Save donmccurdy/4f1c25d522745531ad9bebdc347e6664 to your computer and use it in GitHub Desktop.
Save donmccurdy/4f1c25d522745531ad9bebdc347e6664 to your computer and use it in GitHub Desktop.
Scan a monorepo for missing or transitive dependencies in subpackages.
import {readFile} from 'node:fs/promises';
import {join} from 'node:path';
import glob from 'glob';
import builtinModules from 'builtin-modules';
const IMPORT_IDENTIFIER_REGEX = /(?:\A|\r|\n|\r\n)import[^'"]*['"]([\@\.\/\w_-]+)['"]/g;
const BUILTIN_MODULES = new Set<string>(builtinModules);
const pkgPaths = glob.sync(join('modules', '*', 'package.json'));
console.log(
`
| status | pkg | missing dependencies |
|--------|-----|----------------------|
`.trim()
);
for (const pkgPath of pkgPaths.sort()) {
const pkg = JSON.parse(await readFile(pkgPath, 'utf8'));
const module = pkg.name.split('/').pop();
const allDependencies = new Set<string>([
...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.devDependencies || {}),
...Object.keys(pkg.peerDependencies || {}),
...Object.keys(pkg.optionalDependencies || {})
]);
const missingDependencies = new Set<string>();
const sourceImports = new Set<string>();
for (const sourcePath of glob.sync(join('modules', module, 'src', '**', '*.ts'))) {
const source = await readFile(sourcePath, 'utf8');
for (const match of source.matchAll(IMPORT_IDENTIFIER_REGEX)) {
const identifier = match[1];
if (identifier.startsWith('.')) continue;
const baseIdentifier = identifier.startsWith('@')
? identifier.split('/').slice(0, 2).join('/')
: identifier.split('/')[0];
sourceImports.add(baseIdentifier);
if (
!allDependencies.has(baseIdentifier) &&
!BUILTIN_MODULES.has(baseIdentifier) &&
baseIdentifier !== pkg.name
) {
missingDependencies.add(baseIdentifier);
}
}
}
if (missingDependencies.size) {
console.log(`| ❌ | ${pkg.name} | ${Array.from(missingDependencies).join(', ')} |`);
} else {
console.log(`| ✅ | ${pkg.name} | |`);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment