豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit a9238e5

Browse files
committed
Dynamically populate bundled packages from src/third_party imports
Replace the hardcoded THIRD_PARTY_PACKAGES list with dynamic parsing of src/third_party/*.ts files at ESLint load time. This extracts bare package names from import/export statements and side-effect imports, so the list stays in sync automatically as new packages are added. A sync test against build/src/third_party/bundled-packages.json can be added once that file is generated during the build step.
1 parent 4dacf02 commit a9238e5

File tree

1 file changed

+52
-9
lines changed

1 file changed

+52
-9
lines changed

scripts/eslint_rules/no-direct-third-party-imports-rule.js

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,61 @@
1515
* (because devDependencies are installed) but fails once the package is
1616
* bundled and published via `npm pack`.
1717
*
18+
* The list of bundled packages is derived dynamically by scanning
19+
* `src/third_party/*.ts` for import/export statements at ESLint load time.
20+
*
1821
* See https://github.com/ChromeDevTools/chrome-devtools-mcp/issues/1123
1922
*/
2023

21-
const THIRD_PARTY_PACKAGES = [
22-
'@modelcontextprotocol/sdk',
23-
'puppeteer-core',
24-
'@puppeteer/browsers',
25-
'yargs',
26-
'debug',
27-
'zod',
28-
'core-js',
29-
];
24+
import {readdirSync, readFileSync} from 'node:fs';
25+
import {join, dirname} from 'node:path';
26+
import {fileURLToPath} from 'node:url';
27+
28+
const __dirname = dirname(fileURLToPath(import.meta.url));
29+
const THIRD_PARTY_DIR = join(__dirname, '..', '..', 'src', 'third_party');
30+
31+
/**
32+
* Parse all .ts files in src/third_party/ and extract the bare package names
33+
* from import/export statements. Relative imports and node_modules paths
34+
* (used for chrome-devtools-frontend) are skipped.
35+
*/
36+
function discoverBundledPackages() {
37+
const packages = new Set();
38+
// Match `from 'pkg'` (may appear on a different line than `import`)
39+
// and side-effect imports like `import 'pkg'`.
40+
const fromRe = /from\s+['"]([^'"]+)['"]/g;
41+
const sideEffectRe = /^import\s+['"]([^'"]+)['"]/gm;
42+
43+
let files;
44+
try {
45+
files = readdirSync(THIRD_PARTY_DIR).filter(f => f.endsWith('.ts'));
46+
} catch {
47+
return [];
48+
}
49+
50+
for (const file of files) {
51+
const content = readFileSync(join(THIRD_PARTY_DIR, file), 'utf8');
52+
for (const re of [fromRe, sideEffectRe]) {
53+
re.lastIndex = 0;
54+
let match;
55+
while ((match = re.exec(content)) !== null) {
56+
const source = match[1];
57+
// Skip relative imports and node_modules paths.
58+
if (source.startsWith('.') || source.startsWith('/')) {
59+
continue;
60+
}
61+
// Extract the bare package name (handle scoped packages like @foo/bar).
62+
const parts = source.split('/');
63+
const pkg = source.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0];
64+
packages.add(pkg);
65+
}
66+
}
67+
}
68+
69+
return [...packages];
70+
}
71+
72+
const THIRD_PARTY_PACKAGES = discoverBundledPackages();
3073

3174
/** Matches any import source that starts with one of the restricted packages. */
3275
function isRestrictedSource(source) {

0 commit comments

Comments
 (0)