Skip to content

chore: lint against runtime imports of devDependencies#852

Merged
TwitchBronBron merged 1 commit into
masterfrom
lint-extraneous-dependencies
Jul 7, 2026
Merged

chore: lint against runtime imports of devDependencies#852
TwitchBronBron merged 1 commit into
masterfrom
lint-extraneous-dependencies

Conversation

@TwitchBronBron

Copy link
Copy Markdown
Member

Why

The 2.67.1 extension crashed on activation with Cannot find module 'dayjs/plugin/relativeTime'. Root cause: dayjs was imported at runtime but listed only in devDependencies, which get stripped when the extension is packaged into a .vsix. That was fixed in #850 — this PR adds tooling so the whole class of bug fails CI instead of shipping to users.

What

Adds the import/no-extraneous-dependencies rule (via eslint-plugin-import). It fails npm run lint when a runtime source file imports a package not listed in dependencies. This runs inside the existing lint step, which is already part of CI (build.yml) and the preversion gate — no new CI surface.

Config choices:

  • devDependencies allowed only in scripts/**, benchmarks/**, and config files
  • *.spec.ts files exempt entirely (they only run when devDependencies are installed)
  • optionalDependencies: false, peerDependencies: true

Issues the new rule surfaced (also fixed here)

  • lodash — imported at runtime in DeviceManager.ts and LocalPackageManager.ts but only a devDependency → moved to dependencies. (Same latent crash as dayjs.)
  • @parcel/watcher — an intentional dev-only optional require() wrapped in try/catch → added a scoped eslint-disable rather than promoting it to a prod dep.

Limitations

This is a source-level heuristic: it catches static import/require of undeclared packages (the common case), but won't catch dynamic require(variable) paths. It's the cheapest, earliest catch; a packaged-artifact smoke test would be a stronger (heavier) complement if we want one later.

🤖 Generated with Claude Code

Adds the `import/no-extraneous-dependencies` eslint rule (via
eslint-plugin-import) so `npm run lint` fails when a runtime source
file imports a package that is only listed in devDependencies. Those
get stripped when the extension is packaged into a .vsix, which caused
the 2.67.1 activation crash ("Cannot find module 'dayjs/...'").

The rule runs inside the existing lint step, which is already part of
CI (build.yml) and the `preversion` gate.

Also fixes the issues the new rule surfaced:
- move `lodash` from devDependencies to dependencies (imported at
  runtime in DeviceManager.ts and LocalPackageManager.ts)
- scope-disable the rule for the intentional optional `@parcel/watcher`
  require (dev-only, wrapped in try/catch)
- disable the rule for *.spec.ts files, which only run with
  devDependencies installed

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@TwitchBronBron
TwitchBronBron merged commit 886af51 into master Jul 7, 2026
8 checks passed
@TwitchBronBron
TwitchBronBron deleted the lint-extraneous-dependencies branch July 7, 2026 19:49
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.

1 participant