Skip to content

fix(deps): replace @package-json/types with an inline minimal type#476

Open
nbouvrette wants to merge 10 commits intoun-ts:masterfrom
nbouvrette:fix/inline-package-json-type
Open

fix(deps): replace @package-json/types with an inline minimal type#476
nbouvrette wants to merge 10 commits intoun-ts:masterfrom
nbouvrette:fix/inline-package-json-type

Conversation

@nbouvrette
Copy link
Copy Markdown

@nbouvrette nbouvrette commented Mar 15, 2026

Problem

@package-json/types was added in #434 to replace type-fest after it leaked into published .d.ts files (from being in devDependencies). While that fixed the immediate issue, it introduced a new transitive dependency with low maintenance activity — all for type annotations covering a handful of package.json fields.

Additionally, @package-json/types itself has a bug under strict TypeScript (strict: true) that affects consumers:

error TS2411: Property 'node' of type 'string | undefined' is not assignable to 'string' index type 'string'.
error TS2411: Property 'extends' of type 'string | undefined' is not assignable to 'string' index type 'string'.

(A fix has been submitted upstream: importantimport/package-json#1, but it depends on that maintainer acting.)

Solution

Remove @package-json/types from dependencies entirely and replace it with a small inline PackageJson interface added to src/types.ts, covering exactly the fields this plugin uses:

  • name, version — used in read-pkg-up.ts and no-duplicates.ts
  • private, main, bin, browser — used in no-unused-modules.ts
  • dependencies, devDependencies, optionalDependencies, peerDependencies, bundleDependencies, bundledDependencies — used in no-extraneous-dependencies.ts

PackageJson lives in src/types.ts (not a new utility file) because utils/read-pkg-up.js is part of the public API (exported via the ./utils package export) and references PackageJson in its return type — making it effectively public. This is also why @package-json/types had to be in dependencies rather than devDependencies in the first place.

Field types are aligned with authoritative sources (type-fest, pkg-types, npm spec):

  • browser uses Record<string, string | false>false is a real pattern for excluding modules in browser bundles (e.g. "fs": false)
  • bundleDependencies/bundledDependencies use string[] | Record<string, string> — array per npm spec; object form is non-standard but intentionally supported by this rule (tested since the original eslint-plugin-import in 2019)

Benefits

  • Zero new dependencies for consumers — no transitive type packages in published .d.ts files
  • No exposure to upstream breakage — the TS2411 strict mode issue in @package-json/types no longer affects consumers of this plugin
  • Easy to maintain — fields are stable and well-known; the interface only changes if the plugin starts using new package.json fields

Changes

  • src/types.ts — new PackageJson interface added to the existing public types file
  • src/utils/read-pkg-up.ts, src/rules/no-duplicates.ts, src/rules/no-extraneous-dependencies.ts, src/rules/no-unused-modules.ts — update imports to use local type
  • src/rules/no-extraneous-dependencies.ts — fix comment: object form of bundleDependencies is supported by this rule, not by npm
  • package.json — remove @package-json/types from dependencies
  • yarn.lock — updated after dependency removal

@package-json/types was added in un-ts#434 as a replacement for type-fest,
after type-fest leaked into published .d.ts files from devDependencies.
However the swap introduced a new transitive dependency (~148k weekly
downloads, low activity) for what is effectively three type annotations
touching only 8 package.json fields.

This commit removes the dependency entirely and replaces it with a small
inline PackageJson interface in src/utils/package-json.ts that covers
exactly the fields this plugin accesses:
- name, version (read-pkg-up, no-duplicates)
- dependencies, devDependencies, optionalDependencies, peerDependencies,
  bundleDependencies, bundledDependencies (no-extraneous-dependencies)

Benefits:
- Zero runtime/type dependencies added to consumers
- No more exposure to upstream type breakages (e.g. TS2411 strict errors
  in @package-json/types that affect consumers with strict: true)
- The interface is trivial to maintain; package.json dep fields are stable

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 15, 2026

⚠️ No Changeset found

Latest commit: 35e351b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 15, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Removed the external @package-json/types dependency, added a local PackageJson interface at src/utils/package-json.ts, and updated imports in three files to use the local type; minor comment and type adjustments related to bundleDependencies/bundledDependencies were made in the no-extraneous-dependencies rule.

Changes

Cohort / File(s) Summary
Dependency removal
package.json
Deleted the @package-json/types entry from dependencies.
New local type
src/utils/package-json.ts
Added exported PackageJson interface (optional fields used by the project). bundleDependencies / bundledDependencies defined as `string[]
Type import updates
src/rules/no-duplicates.ts, src/rules/no-extraneous-dependencies.ts, src/utils/read-pkg-up.ts
Replaced type-only imports from @package-json/types with local imports from ../utils/package-json.js or ./package-json.js.
Rule comment / minor logic note
src/rules/no-extraneous-dependencies.ts
Updated inline comment clarifying that npm spec uses an array for bundleDependencies while object form is also supported non-standardly; actual extraction logic unchanged (uses arrayOrKeys on bundle fields).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

dependencies

Suggested reviewers

  • JounQin

Poem

🐰 I nibbled a dep and stitched a type,
Brought package shapes back into sight,
Swapped imports, kept the rules in line,
A tidy hop — everything's fine! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically describes the main change: removing the @package-json/types dependency and replacing it with an inline minimal PackageJson type.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can generate a title for your PR based on the changes.

Add @coderabbitai placeholder anywhere in the title of your PR and CodeRabbit will replace it with a title based on the changes in the PR. You can change the placeholder by changing the reviews.auto_title_placeholder setting.

@nbouvrette
Copy link
Copy Markdown
Author

FYI @mshima (re: #434 (comment))

Copy link
Copy Markdown
Collaborator

@SukkaW SukkaW left a comment

Choose a reason for hiding this comment

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

CI is failing.

Add `private`, `main`, `bin`, and `browser` fields to the inline
PackageJson interface, which are accessed in `no-unused-modules.ts`
but were omitted from the initial audit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@nbouvrette
Copy link
Copy Markdown
Author

Good catch @SukkaW! The initial audit only covered files explicitly mentioned in the PR description (read-pkg-up.ts, no-duplicates.ts, no-extraneous-dependencies.ts) and missed that no-unused-modules.ts also accesses PackageJson fields via readPkgUp — specifically private, bin, browser, and main.

Fixed in the latest commit by adding those four missing fields to the inline interface. I've verified all pkg. field accesses across the entire src/ directory — the interface now covers everything the plugin uses.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codesandbox-ci
Copy link
Copy Markdown

codesandbox-ci bot commented Mar 17, 2026

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

@nbouvrette nbouvrette requested a review from SukkaW March 17, 2026 00:46
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/utils/package-json.ts`:
- Around line 16-18: Change the types for bundleDependencies and
bundledDependencies from "string[] | Record<string,string>" to the correct
npm-supported "string[] | boolean", and update the preceding comment to state
they support either an array of package names or a boolean (remove the incorrect
"object form (supported by npm)" phrasing); if your code still intentionally
accepts non-standard object forms via arrayOrKeys(), add a separate inline note
next to arrayOrKeys() (or near these fields) clarifying that object-form support
is an internal/lenient parse behavior and not part of the npm spec.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b4d7234e-06f8-4130-b1c0-35d35c78cc1d

📥 Commits

Reviewing files that changed from the base of the PR and between 6f1ee84 and 439c730.

📒 Files selected for processing (1)
  • src/utils/package-json.ts

nbouvrette and others added 2 commits March 16, 2026 22:18
The comment implied npm supports an object form for bundleDependencies,
which is inaccurate. Only string[] is in the npm spec. The Record<string,string>
type is kept because arrayOrKeys() in no-extraneous-dependencies.ts handles
object form leniently, but boolean would break that call site.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- bundleDependencies/bundledDependencies: string[] | boolean (per npm spec
  and original @package-json/types), not Record<string,string>. Update
  no-extraneous-dependencies.ts call site to guard against boolean values.
- browser: add | false to record values (Record<string, string | false>)
  to support the common pattern of excluding modules (e.g. "fs": false).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/rules/no-extraneous-dependencies.ts`:
- Around line 44-52: The code uses `const bundle = pkg.bundleDependencies ||
pkg.bundledDependencies` which treats an explicit falsey value (e.g., false) as
missing; update this to use the nullish coalescing operator so explicit booleans
are preserved: replace the `||` with `??` when assigning `bundle` in the
`no-extraneous-dependencies.ts` code that computes `bundle` and then later uses
`arrayOrKeys(bundle)` for `bundledDependencies`, ensuring the boolean `false` is
not overwritten by the fallback.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 078841c2-c04d-4a4b-8622-3b70cd76fa69

📥 Commits

Reviewing files that changed from the base of the PR and between 0ca7b62 and aa2e5f6.

📒 Files selected for processing (2)
  • src/rules/no-extraneous-dependencies.ts
  • src/utils/package-json.ts

The object form of bundleDependencies (Record<string, string>) is
non-standard but intentionally supported by no-extraneous-dependencies
and has been tested since the original eslint-plugin-import (2019).
Revert the type back to string[] | Record<string, string> and restore
the original call site.

Also fix the comment in no-extraneous-dependencies.ts: object form is
non-standard, not "supported by npm" as the old comment claimed.

The browser fix (Record<string, string | false>) is kept — false values
are a real pattern for excluding modules in browser bundles.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 17, 2026

Open in StackBlitz

npm i https://pkg.pr.new/eslint-plugin-import-x@476

commit: 35e351b

nbouvrette and others added 2 commits March 17, 2026 17:24
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Since utils/read-pkg-up.js is part of the public API (exported via
the ./utils package export), PackageJson appears in its return type
and is effectively public. Moving it to src/types.ts makes this
explicit and consistent with the rest of the public type surface.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@JounQin JounQin requested review from Copilot and removed request for SukkaW March 19, 2026 02:38
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

Removes the @package-json/types dependency and replaces it with an internal minimal PackageJson interface so published .d.ts files no longer rely on a low-maintenance transitive type package and strict TS consumers avoid upstream type issues.

Changes:

  • Drop @package-json/types from dependencies (and lockfile).
  • Add an internal minimal PackageJson interface and switch type imports to use it.
  • Update documentation comment around bundleDependencies/bundledDependencies handling.

Reviewed changes

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

Show a summary per file
File Description
yarn.lock Removes the resolved @package-json/types entry after dependency removal.
package.json Removes @package-json/types from dependencies.
src/types.ts Adds internal PackageJson interface for the subset of package.json fields used.
src/utils/read-pkg-up.ts Switches PackageJson type import to the internal type.
src/rules/no-duplicates.ts Switches PackageJson type import to the internal type.
src/rules/no-extraneous-dependencies.ts Switches PackageJson type import and adjusts the bundled deps comment.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Nicolas Bouvrette <bouvrette.nicolas@gmail.com>
@nbouvrette nbouvrette requested a review from SukkaW March 21, 2026 01:01
@nbouvrette
Copy link
Copy Markdown
Author

@SukkaW @JounQin can we re-run CI? was there anything missing on my end to merge this PR?

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.

4 participants