chromedevtools--chrome-devtools-mcp
cdbc66f160
## Summary - Adds a custom ESLint rule `@local/no-direct-third-party-imports` that flags value imports of bundled third-party packages (`@modelcontextprotocol/sdk`, `puppeteer-core`, `@puppeteer/browsers`, `yargs`, `debug`, `zod`, `core-js`) when used outside of `src/third_party/` - Type-only imports (`import type`) are allowed since they are erased at compile time and don't affect the bundle - The rule is scoped to `src/**/*.ts` so development scripts and tests are unaffected This prevents the class of bugs where a direct npm import works during development (devDependencies installed) but breaks in the published package (only bundled code ships). PR #1111 was an example of this exact issue caught through manual `npm pack` testing. Closes #1123 ## Test plan - [x] Verified `npx eslint --no-cache src/` passes with no violations on the current codebase - [x] Verified the rule correctly catches a test file with `import {Client} from '@modelcontextprotocol/sdk/client/index.js'` - [x] Verified the rule allows `import type {Flags} from 'lighthouse'` (type-only import) - [x] Verified the rule does not fire inside `src/third_party/index.ts` (the barrel itself) - [x] Verified scripts/ and tests/ are unaffected (rule scoped to `src/**/*.ts`) --------- Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: Alex Rudenko <alexrudenko@chromium.org>
162 行
3.8 KiB
JavaScript
162 行
3.8 KiB
JavaScript
/**
|
|
* @license
|
|
* Copyright 2025 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import js from '@eslint/js';
|
|
import stylisticPlugin from '@stylistic/eslint-plugin';
|
|
import {defineConfig, globalIgnores} from 'eslint/config';
|
|
import importPlugin from 'eslint-plugin-import';
|
|
import globals from 'globals';
|
|
import tseslint from 'typescript-eslint';
|
|
|
|
import localPlugin from './scripts/eslint_rules/local-plugin.js';
|
|
|
|
export default defineConfig([
|
|
globalIgnores([
|
|
'**/node_modules',
|
|
'**/build/',
|
|
'tests/tools/fixtures/',
|
|
'src/third_party/lighthouse-devtools-mcp-bundle.js',
|
|
]),
|
|
importPlugin.flatConfigs.typescript,
|
|
{
|
|
languageOptions: {
|
|
ecmaVersion: 'latest',
|
|
sourceType: 'module',
|
|
|
|
globals: {
|
|
...globals.node,
|
|
},
|
|
|
|
parserOptions: {
|
|
projectService: {
|
|
allowDefaultProject: [
|
|
'.prettierrc.cjs',
|
|
'puppeteer.config.cjs',
|
|
'eslint.config.mjs',
|
|
'rollup.config.mjs',
|
|
'skills/memory-leak-debugging/references/compare_snapshots.js',
|
|
],
|
|
},
|
|
},
|
|
|
|
parser: tseslint.parser,
|
|
},
|
|
|
|
plugins: {
|
|
js,
|
|
'@local': localPlugin,
|
|
'@typescript-eslint': tseslint.plugin,
|
|
'@stylistic': stylisticPlugin,
|
|
},
|
|
|
|
settings: {
|
|
'import/resolver': {
|
|
typescript: true,
|
|
},
|
|
},
|
|
|
|
extends: ['js/recommended'],
|
|
},
|
|
tseslint.configs.recommended,
|
|
tseslint.configs.stylistic,
|
|
{
|
|
name: 'TypeScript rules',
|
|
rules: {
|
|
'@local/check-license': 'error',
|
|
curly: ['error', 'all'],
|
|
|
|
'no-undef': 'off',
|
|
'no-unused-vars': 'off',
|
|
'@typescript-eslint/no-unused-vars': [
|
|
'error',
|
|
{
|
|
argsIgnorePattern: '^_',
|
|
varsIgnorePattern: '^_',
|
|
},
|
|
],
|
|
'@typescript-eslint/no-explicit-any': [
|
|
'error',
|
|
{
|
|
ignoreRestArgs: true,
|
|
},
|
|
],
|
|
// This optimizes the dependency tracking for type-only files.
|
|
'@typescript-eslint/consistent-type-imports': 'error',
|
|
// So type-only exports get elided.
|
|
'@typescript-eslint/consistent-type-exports': 'error',
|
|
// Prefer interfaces over types for shape like.
|
|
'@typescript-eslint/consistent-type-definitions': ['error', 'interface'],
|
|
'@typescript-eslint/array-type': [
|
|
'error',
|
|
{
|
|
default: 'array-simple',
|
|
},
|
|
],
|
|
'@typescript-eslint/no-floating-promises': 'error',
|
|
|
|
'import/order': [
|
|
'error',
|
|
{
|
|
'newlines-between': 'always',
|
|
|
|
alphabetize: {
|
|
order: 'asc',
|
|
caseInsensitive: true,
|
|
},
|
|
},
|
|
],
|
|
|
|
'import/no-cycle': [
|
|
'error',
|
|
{
|
|
maxDepth: Infinity,
|
|
},
|
|
],
|
|
|
|
'import/enforce-node-protocol-usage': ['error', 'always'],
|
|
|
|
'@stylistic/function-call-spacing': 'error',
|
|
'@stylistic/semi': 'error',
|
|
|
|
'no-restricted-imports': [
|
|
'error',
|
|
{
|
|
patterns: [
|
|
{
|
|
regex: '.*chrome-devtools-frontend/(?!mcp/mcp.js$).*',
|
|
message:
|
|
'Import only the devtools-frontend code exported via node_modules/chrome-devtools-frontend/mcp/mcp.js',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
name: 'Source files',
|
|
files: ['src/**/*.ts'],
|
|
rules: {
|
|
'@local/no-direct-third-party-imports': 'error',
|
|
},
|
|
},
|
|
{
|
|
name: 'Tools definitions',
|
|
files: ['src/tools/**/*.ts'],
|
|
rules: {
|
|
'@local/enforce-zod-schema': 'error',
|
|
},
|
|
},
|
|
{
|
|
name: 'Tests',
|
|
files: ['**/*.test.ts'],
|
|
rules: {
|
|
// With the Node.js test runner, `describe` and `it` are technically
|
|
// promises, but we don't need to await them.
|
|
'@typescript-eslint/no-floating-promises': 'off',
|
|
},
|
|
},
|
|
]);
|