Skip to content

chore: add ESLint guard against direct third-party imports bypassing bundle#1189

Merged
OrKoN merged 4 commits intoChromeDevTools:mainfrom
mvanhorn:osc/1123-bundle-import-test-guard
Apr 1, 2026
Merged

chore: add ESLint guard against direct third-party imports bypassing bundle#1189
OrKoN merged 4 commits intoChromeDevTools:mainfrom
mvanhorn:osc/1123-bundle-import-test-guard

Conversation

@mvanhorn
Copy link
Copy Markdown
Contributor

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

  • Verified npx eslint --no-cache src/ passes with no violations on the current codebase
  • Verified the rule correctly catches a test file with import {Client} from '@modelcontextprotocol/sdk/client/index.js'
  • Verified the rule allows import type {Flags} from 'lighthouse' (type-only import)
  • Verified the rule does not fire inside src/third_party/index.ts (the barrel itself)
  • Verified scripts/ and tests/ are unaffected (rule scoped to src/**/*.ts)

@zyzyzyryxy
Copy link
Copy Markdown
Contributor

Thank you for your contribution!

I see you hardcoded the list of bundled packages, I am thinking if we could get that list dynamically.

We generate build/src/third_party/bundled-packages.json during bundling, but that we cannot rely on in eslint. We could maybe have a test to check if they are in sync instead.

Could eslint parse src/third_party/*.ts for imports there to populate that list? Not sure if that could work.

In both cases, we would need some special case handling around puppeteer anyways.

If either of those is impractical, certainly having hardcoded list is still better than nothing.

@mvanhorn
Copy link
Copy Markdown
Contributor Author

Replaced hardcoded list with discoverBundledPackages() that reads src/third_party/*.ts at ESLint load time and extracts package names from import statements. Correctly discovers all 8 packages including scoped packages and side-effect imports.

mvanhorn added 2 commits April 1, 2026 09:03
…ndle

Adds a custom ESLint rule `@local/no-direct-third-party-imports` that
prevents value imports of bundled third-party packages from files in
`src/` unless they go through the `src/third_party/index.ts` barrel.

Type-only imports are allowed since they are erased at compile time.
The rule is scoped to `src/**/*.ts` so scripts and tests are unaffected.

This prevents the class of bugs described in ChromeDevTools#1123 where direct imports
work in development (devDependencies present) but fail in the published
npm package (only bundled code available).

Closes ChromeDevTools#1123
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.
@OrKoN OrKoN force-pushed the osc/1123-bundle-import-test-guard branch from a9238e5 to f9e15d3 Compare April 1, 2026 07:03
Copy link
Copy Markdown
Collaborator

@OrKoN OrKoN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thanks!

@OrKoN OrKoN enabled auto-merge April 1, 2026 07:07
@OrKoN OrKoN added this pull request to the merge queue Apr 1, 2026
@OrKoN OrKoN removed this pull request from the merge queue due to a manual request Apr 1, 2026
@OrKoN OrKoN changed the title fix: add ESLint guard against direct third-party imports bypassing bundle chore: add ESLint guard against direct third-party imports bypassing bundle Apr 1, 2026
@OrKoN OrKoN enabled auto-merge April 1, 2026 07:41
@OrKoN OrKoN added this pull request to the merge queue Apr 1, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to a conflict with the base branch Apr 1, 2026
@OrKoN OrKoN enabled auto-merge April 1, 2026 07:52
@OrKoN OrKoN added this pull request to the merge queue Apr 1, 2026
Merged via the queue into ChromeDevTools:main with commit cdbc66f Apr 1, 2026
17 checks passed
@mvanhorn
Copy link
Copy Markdown
Contributor Author

mvanhorn commented Apr 6, 2026

Thanks for the merge!

@mvanhorn
Copy link
Copy Markdown
Contributor Author

mvanhorn commented Apr 7, 2026

Thanks for the quick review and merge!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Testing blind spot around bundling

4 participants