Skip to content

feat(eslint-rules): add base-hook-no-forbidden-runtime rule#36253

Open
Hotell wants to merge 2 commits into
microsoft:masterfrom
Hotell:tools/ws-lint/rule-base-hook-no-forbidden-runtime
Open

feat(eslint-rules): add base-hook-no-forbidden-runtime rule#36253
Hotell wants to merge 2 commits into
microsoft:masterfrom
Hotell:tools/ws-lint/rule-base-hook-no-forbidden-runtime

Conversation

@Hotell
Copy link
Copy Markdown
Contributor

@Hotell Hotell commented May 26, 2026

Summary

Introduces a new workspace ESLint rule @nx/workspace-base-hook-no-forbidden-runtime that prevents useFooBase / useFooBase_unstable hooks from pulling in heavy runtime dependencies. It walks the imports of the base-hook module and flags transitive dependencies on packages outside an allowlist.

The rule is fully inert in this PR — it is registered with @nx/workspace but not enabled in any project config. Wiring happens in a follow-up PR.

Plan reference

Part of the split of #36251 — see prd/eslint-rules-base-hook-pr-split.spec.md (PR2).

Fixtures

Self-contained fixture workspace under tools/eslint-rules/rules/__fixtures__/base-hook-no-forbidden-runtime/ includes a local tsconfig.json plus stub packages: light-helper, heavy-runtime, watched-pkg (with light.ts / heavy.ts paths), and cyclic-pkg (a → b → index → a cycle) to verify cycle handling.

Verification

nx run eslint-rules:test --skip-nx-cache

→ 4 suites / 56 tests pass.

ESLint CLI perf (TIMING=200)

Measured on a combined branch (PR1 + PR2 + PR3 wiring) so the rule actually runs.

Project @nx/workspace-base-hook-no-forbidden-runtime % of total
react-button (no *Base hook) 0.56 ms 0.0%
react-combobox (1 *Base hook) 0.90 ms 0.0%
react-tags (1 *Base hook) 0.83 ms 0.0%

Negligible — the rule short-circuits on non-base-hook files and the import graph walk is bounded + cycle-safe.

Out of scope

  • Wiring into @fluentui/eslint-plugin (separate PR).
  • Beachball change file (declined — tooling-only change).

Registers @nx/workspace-base-hook-no-forbidden-runtime. Rule is not yet enabled in any project config and is fully inert until wired up in a follow-up PR.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 26, 2026

📊 Bundle size report

✅ No changes found

@github-actions
Copy link
Copy Markdown

Pull request demo site: URL

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new workspace ESLint rule (@nx/workspace-base-hook-no-forbidden-runtime) intended to prevent v9 use*Base_unstable hooks from (directly or transitively) depending on forbidden runtime packages, with a dedicated typed + untyped test/fixture setup.

Changes:

  • Introduces the base-hook-no-forbidden-runtime rule with transitive import-graph reach analysis (value vs type reach) and a one-shot warning when type info is missing.
  • Adds RuleTester coverage plus a self-contained fixture workspace (stub packages + tsconfig) to validate transitive reach and cycle handling.
  • Updates eslint-rules workspace config to exclude fixture files from lint compilation, and registers the rule in the workspace rules index.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tools/eslint-rules/tsconfig.lint.json Excludes __fixtures__ from lint tsconfig to avoid fixture compilation/lint noise.
tools/eslint-rules/rules/base-hook-no-forbidden-runtime.ts Implements the new rule, including import tracking, scope analysis, and transitive reach computation.
tools/eslint-rules/rules/base-hook-no-forbidden-runtime.spec.ts Adds untyped + typed RuleTester suites covering direct forbidden imports, transitive reach, and cycles.
tools/eslint-rules/rules/fixtures/base-hook-no-forbidden-runtime/tsconfig.json Fixture TS project config with path mappings to stub packages for typed tests.
tools/eslint-rules/rules/fixtures/base-hook-no-forbidden-runtime/stubs/watched-pkg/light.ts Stub “light” module that should not reach the forbidden runtime.
tools/eslint-rules/rules/fixtures/base-hook-no-forbidden-runtime/stubs/watched-pkg/index.ts Stub package entrypoint with mixed value/type re-exports to exercise reach semantics.
tools/eslint-rules/rules/fixtures/base-hook-no-forbidden-runtime/stubs/watched-pkg/heavy.ts Stub “heavy” module that imports the forbidden runtime.
tools/eslint-rules/rules/fixtures/base-hook-no-forbidden-runtime/stubs/light-helper/index.ts Stub helper package used by the “light” module.
tools/eslint-rules/rules/fixtures/base-hook-no-forbidden-runtime/stubs/heavy-runtime/index.ts Stub forbidden runtime package used to validate direct + transitive blocking.
tools/eslint-rules/rules/fixtures/base-hook-no-forbidden-runtime/stubs/cyclic-pkg/index.ts Stub cyclic package entrypoint to exercise cycle safety.
tools/eslint-rules/rules/fixtures/base-hook-no-forbidden-runtime/stubs/cyclic-pkg/b.ts Part of a cyclic import graph in the fixture.
tools/eslint-rules/rules/fixtures/base-hook-no-forbidden-runtime/stubs/cyclic-pkg/a.ts Part of a cyclic import graph in the fixture.
tools/eslint-rules/rules/fixtures/base-hook-no-forbidden-runtime/src/test.ts Placeholder file so the typed Program contains the filename used in RuleTester cases.
tools/eslint-rules/rules/fixtures/base-hook-no-forbidden-runtime/src/dummy.ts Additional placeholder/anchor file in the fixture project.
tools/eslint-rules/index.ts Registers the new rule in the exported workspace rules map.

Comment thread tools/eslint-rules/rules/base-hook-no-forbidden-runtime.ts Outdated
Comment thread tools/eslint-rules/rules/base-hook-no-forbidden-runtime.ts Outdated
Cache in-progress reach results to preserve transitive closure across import cycles, normalize diagnostic paths cross-platform, and add cyclic regression fixtures/tests.
@Hotell Hotell marked this pull request as ready for review May 26, 2026 17:44
@Hotell Hotell requested a review from a team as a code owner May 26, 2026 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants