Skip to content

fix: replace package.json JSON-parser check with native rule to avoid config merge issues - #145

Open
saberzero1 wants to merge 3 commits into
obsidianmd:masterfrom
saberzero1:package-json-checks-refactor
Open

fix: replace package.json JSON-parser check with native rule to avoid config merge issues#145
saberzero1 wants to merge 3 commits into
obsidianmd:masterfrom
saberzero1:package-json-checks-refactor

Conversation

@saberzero1

@saberzero1 saberzero1 commented May 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

Replaces the { files: ['package.json'], language: 'json/json' } config block with a native obsidianmd/no-banned-dependencies rule that reads package.json from disk. This eliminates the class of config-merge issues where consumers' global typed-linting configs leak onto package.json and crash typescript-eslint rules.

Problem

The recommended config included a config block targeting package.json via @eslint/json and eslint-plugin-depend. ESLint's flat config merging is by design — config objects without files are "universal" and apply to every matched file (eslint/eslint#20352, eslint/eslint#20354). When consumers write:

export default defineConfig([
  ...obsidianmd.configs.recommended,
  {
    // No `files` — applies globally, including to package.json
    languageOptions: {
      parser: tsparser,
      parserOptions: { project: "./tsconfig.json" },
    },
  },
]);

ESLint merges the typed-linting setup onto package.json, and typescript-eslint rules crash because the JSON language processor doesn't provide TypeScript services. The disableTypeChecked guard only disables the plugin's own type-aware rules — it cannot prevent the consumer's config from leaking.

ESLint has explicitly rejected fixing this upstream (both issues closed as "works as intended").

Approach

The new obsidianmd/no-banned-dependencies rule:

  • Runs on regular JS/TS source files (part of the normal lint pass)
  • Reads package.json from disk via fs.readFileSync once per ESLint run (cached by resolved path)
  • Checks dependencies, devDependencies, peerDependencies, and optionalDependencies against the module-replacements banned lists (the same data source eslint-plugin-depend uses)
  • Supports the same presets (native, microutilities, preferred) and adds an allowed option for whitelisting

This pattern is established in the ecosystem — eslint-plugin-import/no-extraneous-dependencies does exactly this.

What changes for consumers

Nothing. ...obsidianmd.configs.recommended continues to work as a one-liner. The banned-dependency check is now part of recommendedPluginRulesConfig and fires automatically. No config migration needed.

Trade-off

Errors now report on the source file being linted rather than on the package.json line itself. The message includes the dependency name and section (e.g., "is-number" in dependencies should not be used. Use X instead.), so it's clear what to fix.

Changes

  • New rule obsidianmd/no-banned-dependencies (lib/rules/noBannedDependencies.ts)
  • Removed the files: ['package.json'] config block from flatRecommendedConfig
  • Removed @eslint/json and eslint-plugin-depend as dependencies/peerDependencies
  • Added module-replacements as a direct dependency
  • New tests with fixture-based package.json files (6 cases)
  • Removed tests/dependRules.test.ts (replaced by the new test file)

@saberzero1 saberzero1 changed the title fix: perform package.json banned dependencies checks with json parser fix: replace package.json JSON-parser check with native rule to avoid config merge issues May 7, 2026
@saberzero1
saberzero1 marked this pull request as ready for review May 8, 2026 06:44
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