From d7a65d8bffa383ad27f0e3a8673d953297cdfe73 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sat, 28 Feb 2026 22:31:42 +0800 Subject: [PATCH 1/6] feat: add `ignore.vulnerability` --- README.md | 1 + package.json | 8 ++++++++ src/providers/diagnostics/rules/vulnerability.ts | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/README.md b/README.md index 9ad71d3..7f7f9c6 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ | `npmx.diagnostics.vulnerability` | Show warnings for packages with known vulnerabilities | `boolean` | `true` | | `npmx.diagnostics.distTag` | Show warnings when a dependency uses a dist tag | `boolean` | `true` | | `npmx.diagnostics.engineMismatch` | Show warnings when dependency engines mismatch with the current package | `boolean` | `true` | +| `npmx.ignore.vulnerability` | List of package names to ignore vulnerability warnings for (e.g. ["nuxt", "lodash"]) | `array` | `[]` | diff --git a/package.json b/package.json index c3e86fa..a610c91 100644 --- a/package.json +++ b/package.json @@ -98,6 +98,14 @@ "type": "boolean", "default": true, "description": "Show warnings when dependency engines mismatch with the current package" + }, + "npmx.ignore.vulnerability": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "List of package names to ignore vulnerability warnings for (e.g. [\"nuxt\", \"lodash\"])" } } }, diff --git a/src/providers/diagnostics/rules/vulnerability.ts b/src/providers/diagnostics/rules/vulnerability.ts index 63ca465..d652af0 100644 --- a/src/providers/diagnostics/rules/vulnerability.ts +++ b/src/providers/diagnostics/rules/vulnerability.ts @@ -1,5 +1,6 @@ import type { OsvSeverityLevel, PackageVulnerabilityInfo } from '#utils/api/vulnerability' import type { DiagnosticRule } from '..' +import { config } from '#state' import { getVulnerability, SEVERITY_LEVELS } from '#utils/api/vulnerability' import { npmxPackageUrl } from '#utils/links' import { formatUpgradeVersion } from '#utils/version' @@ -30,6 +31,9 @@ export const checkVulnerability: DiagnosticRule = async ({ dep, parsed, exactVer if (!parsed || !exactVersion) return + if (config.ignore.vulnerability.includes(dep.name)) + return + const result = await getVulnerability({ name: dep.name, version: exactVersion }) if (!result) return From e0de95c09d4ef9ea82ae71b43b0922b9e76684cc Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sun, 1 Mar 2026 15:41:53 +0800 Subject: [PATCH 2/6] feat: allow ignoring vulnerabilities for specific package versions --- src/providers/code-actions/index.ts | 15 ++++- src/providers/code-actions/quick-fix.ts | 56 ++++++++++++++----- .../diagnostics/rules/vulnerability.ts | 3 +- tests/__mocks__/vscode.ts | 1 + tests/__setup__/index.ts | 5 ++ tests/code-actions/quick-fix.test.ts | 39 ++++++++++--- 6 files changed, 95 insertions(+), 24 deletions(-) diff --git a/src/providers/code-actions/index.ts b/src/providers/code-actions/index.ts index 1fa2bfa..11d66cd 100644 --- a/src/providers/code-actions/index.ts +++ b/src/providers/code-actions/index.ts @@ -1,10 +1,21 @@ +import type { ConfigurationTarget } from 'vscode' import { extractorEntries } from '#extractors' import { config } from '#state' -import { computed, watch } from 'reactive-vscode' -import { CodeActionKind, Disposable, languages } from 'vscode' +import { computed, useCommand, watch } from 'reactive-vscode' +import { CodeActionKind, Disposable, languages, workspace } from 'vscode' +import { scopedConfigs } from '../../generated-meta' import { QuickFixProvider } from './quick-fix' export function useCodeActions() { + useCommand('npmx.addToIgnore', async (scope: string, name: string, target: ConfigurationTarget) => { + scope = `ignore.${scope}` + const config = workspace.getConfiguration(scopedConfigs.scope) + const current = config.get(scope, []) + if (current.includes(name)) + return + await config.update(scope, [...current, name], target) + }) + const hasQuickFix = computed(() => config.diagnostics.upgrade || config.diagnostics.vulnerability) watch(hasQuickFix, (enabled, _, onCleanup) => { diff --git a/src/providers/code-actions/quick-fix.ts b/src/providers/code-actions/quick-fix.ts index a6b0175..1a99be6 100644 --- a/src/providers/code-actions/quick-fix.ts +++ b/src/providers/code-actions/quick-fix.ts @@ -1,5 +1,5 @@ import type { CodeActionContext, CodeActionProvider, Diagnostic, Range, TextDocument } from 'vscode' -import { CodeAction, CodeActionKind, WorkspaceEdit } from 'vscode' +import { CodeAction, CodeActionKind, ConfigurationTarget, WorkspaceEdit } from 'vscode' interface QuickFixRule { pattern: RegExp @@ -7,7 +7,7 @@ interface QuickFixRule { isPreferred?: boolean } -const quickFixRules: Record = { +const quickFixRules: Partial> = { upgrade: { pattern: /^New version available: (?\S+)$/, title: (target) => `Update to ${target}`, @@ -19,6 +19,16 @@ const quickFixRules: Record = { }, } +interface AddIgnoreRule { + pattern: RegExp +} + +const addIgnoreRules: Partial> = { + vulnerability: { + pattern: /^"(?\S+)" has .+ vulnerabilit/, + }, +} + function getDiagnosticCodeValue(diagnostic: Diagnostic): string | undefined { if (typeof diagnostic.code === 'string') return diagnostic.code @@ -34,20 +44,38 @@ export class QuickFixProvider implements CodeActionProvider { if (!code) return [] - const rule = quickFixRules[code] - if (!rule) - return [] + const actions: CodeAction[] = [] - const target = rule.pattern.exec(diagnostic.message)?.groups?.target - if (!target) - return [] + const quickFixRule = quickFixRules[code] + const target = quickFixRule?.pattern?.exec(diagnostic.message)?.groups?.target + if (target) { + const action = new CodeAction(quickFixRule.title(target), CodeActionKind.QuickFix) + action.isPreferred = quickFixRule.isPreferred ?? false + action.diagnostics = [diagnostic] + action.edit = new WorkspaceEdit() + action.edit.replace(document.uri, diagnostic.range, target) + actions.push(action) + } + + const addIgnoreRule = addIgnoreRules[code] + const ignoreTarget = addIgnoreRule?.pattern?.exec(diagnostic.message)?.groups?.target + if (ignoreTarget) { + for (const [title, configTarget] of [ + [`Ignore ${code} for "${ignoreTarget}" (Workspace)`, ConfigurationTarget.Workspace], + [`Ignore ${code} for "${ignoreTarget}" (User)`, ConfigurationTarget.Global], + ] as const) { + const action = new CodeAction(title, CodeActionKind.QuickFix) + action.diagnostics = [diagnostic] + action.command = { + title, + command: 'npmx.addToIgnore', + arguments: [code, ignoreTarget, configTarget], + } + actions.push(action) + } + } - const action = new CodeAction(rule.title(target), CodeActionKind.QuickFix) - action.isPreferred = rule.isPreferred ?? false - action.diagnostics = [diagnostic] - action.edit = new WorkspaceEdit() - action.edit.replace(document.uri, diagnostic.range, target) - return [action] + return actions }) } } diff --git a/src/providers/diagnostics/rules/vulnerability.ts b/src/providers/diagnostics/rules/vulnerability.ts index d652af0..5a377db 100644 --- a/src/providers/diagnostics/rules/vulnerability.ts +++ b/src/providers/diagnostics/rules/vulnerability.ts @@ -3,6 +3,7 @@ import type { DiagnosticRule } from '..' import { config } from '#state' import { getVulnerability, SEVERITY_LEVELS } from '#utils/api/vulnerability' import { npmxPackageUrl } from '#utils/links' +import { formatPackageId } from '#utils/package' import { formatUpgradeVersion } from '#utils/version' import lt from 'semver/functions/lt' import { DiagnosticSeverity, Uri } from 'vscode' @@ -64,7 +65,7 @@ export const checkVulnerability: DiagnosticRule = async ({ dep, parsed, exactVer return { node: dep.versionNode, - message: `This version has ${message.join(', ')} ${message.length === 1 ? 'vulnerability' : 'vulnerabilities'}.${messageSuffix}`, + message: `"${formatPackageId(dep.name, exactVersion)}" has ${message.join(', ')} ${message.length === 1 ? 'vulnerability' : 'vulnerabilities'}.${messageSuffix}`, severity: severity ?? DiagnosticSeverity.Error, code: { value: 'vulnerability', diff --git a/tests/__mocks__/vscode.ts b/tests/__mocks__/vscode.ts index 788f5ef..37ae376 100644 --- a/tests/__mocks__/vscode.ts +++ b/tests/__mocks__/vscode.ts @@ -20,6 +20,7 @@ export const { CompletionItemKind, CodeAction, CodeActionKind, + ConfigurationTarget, WorkspaceEdit, Diagnostic, DiagnosticSeverity, diff --git a/tests/__setup__/index.ts b/tests/__setup__/index.ts index cecb13e..a5b577e 100644 --- a/tests/__setup__/index.ts +++ b/tests/__setup__/index.ts @@ -4,4 +4,9 @@ import './msw' vi.mock('#state', () => ({ logger: { info: vi.fn(), warn: vi.fn() }, + config: { + ignore: { + vulnerability: [], + }, + }, })) diff --git a/tests/code-actions/quick-fix.test.ts b/tests/code-actions/quick-fix.test.ts index cdd3014..f952b1b 100644 --- a/tests/code-actions/quick-fix.test.ts +++ b/tests/code-actions/quick-fix.test.ts @@ -32,15 +32,40 @@ describe('quick fix provider', () => { expect(actions[0]!.title).toMatchInlineSnapshot('"Update to ^2.0.0"') }) - it('vulnerability', () => { + it('vulnerability with fix', () => { const diagnostic = createDiagnostic( { value: 'vulnerability', target: Uri.parse('https://npmx.dev') }, - 'This version has 1 high vulnerability. Upgrade to ^1.2.3 to fix.', + '"lodash@4.17.20" has 1 high vulnerability. Upgrade to ^4.17.21 to fix.', ) const actions = provideCodeActions([diagnostic]) - expect(actions).toHaveLength(1) - expect(actions[0]!.title).toMatchInlineSnapshot('"Update to ^1.2.3 to fix vulnerabilities"') + expect(actions).toHaveLength(3) + expect(actions[0]!.title).toMatchInlineSnapshot('"Update to ^4.17.21 to fix vulnerabilities"') + expect(actions[1]!.title).toMatchInlineSnapshot('"Ignore vulnerability for "lodash@4.17.20" (Workspace)"') + expect(actions[2]!.title).toMatchInlineSnapshot('"Ignore vulnerability for "lodash@4.17.20" (User)"') + }) + + it('vulnerability without fix', () => { + const diagnostic = createDiagnostic( + { value: 'vulnerability', target: Uri.parse('https://npmx.dev') }, + '"express@4.18.0" has 1 moderate vulnerability.', + ) + const actions = provideCodeActions([diagnostic]) + + expect(actions).toHaveLength(2) + expect(actions[0]!.title).toMatchInlineSnapshot('"Ignore vulnerability for "express@4.18.0" (Workspace)"') + expect(actions[1]!.title).toMatchInlineSnapshot('"Ignore vulnerability for "express@4.18.0" (User)"') + }) + + it('vulnerability for scoped package', () => { + const diagnostic = createDiagnostic( + { value: 'vulnerability', target: Uri.parse('https://npmx.dev') }, + '"@babel/core@7.0.0" has 1 critical vulnerability. Upgrade to ^7.1.0 to fix.', + ) + const actions = provideCodeActions([diagnostic]) + + expect(actions).toHaveLength(3) + expect(actions[1]!.title).toMatchInlineSnapshot('"Ignore vulnerability for "@babel/core@7.0.0" (Workspace)"') }) it('mixed diagnostics', () => { @@ -48,13 +73,13 @@ describe('quick fix provider', () => { createDiagnostic('upgrade', 'New version available: ^2.0.0'), createDiagnostic( { value: 'vulnerability', target: Uri.parse('https://npmx.dev') }, - 'This version has 1 high vulnerability. Upgrade to ^1.2.3 to fix.', + '"lodash@4.17.20" has 1 high vulnerability. Upgrade to ^4.17.21 to fix.', ), ] const actions = provideCodeActions(diagnostics) - expect(actions).toHaveLength(2) + expect(actions).toHaveLength(4) expect(actions[0]!.title).toMatchInlineSnapshot('"Update to ^2.0.0"') - expect(actions[1]!.title).toMatchInlineSnapshot('"Update to ^1.2.3 to fix vulnerabilities"') + expect(actions[1]!.title).toMatchInlineSnapshot('"Update to ^4.17.21 to fix vulnerabilities"') }) }) From a0ee384b9f47eeefd20bb73963a9c15359d19653 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sun, 1 Mar 2026 15:45:05 +0800 Subject: [PATCH 3/6] feat: allow ignore deprecation and replacement --- README.md | 26 ++++++++++--------- package.json | 16 ++++++++++++ src/providers/code-actions/index.ts | 2 +- src/providers/code-actions/quick-fix.ts | 6 +++++ .../diagnostics/rules/deprecation.ts | 4 +++ .../diagnostics/rules/replacement.ts | 14 ++++++---- tests/__setup__/index.ts | 2 ++ 7 files changed, 52 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 7f7f9c6..a21ca72 100644 --- a/README.md +++ b/README.md @@ -38,18 +38,20 @@ -| Key | Description | Type | Default | -| ----------------------------------- | --------------------------------------------------------------------------------------- | --------- | ------------------- | -| `npmx.hover.enabled` | Enable hover information for packages | `boolean` | `true` | -| `npmx.completion.version` | Version completion behavior | `string` | `"provenance-only"` | -| `npmx.completion.excludePrerelease` | Exclude prerelease versions (alpha, beta, rc, canary, etc.) from completion suggestions | `boolean` | `true` | -| `npmx.diagnostics.upgrade` | Show hints when a newer version of a package is available | `boolean` | `true` | -| `npmx.diagnostics.deprecation` | Show warnings for deprecated packages | `boolean` | `true` | -| `npmx.diagnostics.replacement` | Show suggestions for package replacements | `boolean` | `true` | -| `npmx.diagnostics.vulnerability` | Show warnings for packages with known vulnerabilities | `boolean` | `true` | -| `npmx.diagnostics.distTag` | Show warnings when a dependency uses a dist tag | `boolean` | `true` | -| `npmx.diagnostics.engineMismatch` | Show warnings when dependency engines mismatch with the current package | `boolean` | `true` | -| `npmx.ignore.vulnerability` | List of package names to ignore vulnerability warnings for (e.g. ["nuxt", "lodash"]) | `array` | `[]` | +| Key | Description | Type | Default | +| ----------------------------------- | ----------------------------------------------------------------------------------------- | --------- | ------------------- | +| `npmx.hover.enabled` | Enable hover information for packages | `boolean` | `true` | +| `npmx.completion.version` | Version completion behavior | `string` | `"provenance-only"` | +| `npmx.completion.excludePrerelease` | Exclude prerelease versions (alpha, beta, rc, canary, etc.) from completion suggestions | `boolean` | `true` | +| `npmx.diagnostics.upgrade` | Show hints when a newer version of a package is available | `boolean` | `true` | +| `npmx.diagnostics.deprecation` | Show warnings for deprecated packages | `boolean` | `true` | +| `npmx.diagnostics.replacement` | Show suggestions for package replacements | `boolean` | `true` | +| `npmx.diagnostics.vulnerability` | Show warnings for packages with known vulnerabilities | `boolean` | `true` | +| `npmx.diagnostics.distTag` | Show warnings when a dependency uses a dist tag | `boolean` | `true` | +| `npmx.diagnostics.engineMismatch` | Show warnings when dependency engines mismatch with the current package | `boolean` | `true` | +| `npmx.ignore.deprecation` | List of package names to ignore deprecation warnings for (e.g. ["nuxt", "lodash"]) | `array` | `[]` | +| `npmx.ignore.replacement` | List of package names to ignore replacement suggestions for (e.g. ["left-pad", "is-odd"]) | `array` | `[]` | +| `npmx.ignore.vulnerability` | List of package names to ignore vulnerability warnings for (e.g. ["nuxt", "lodash"]) | `array` | `[]` | diff --git a/package.json b/package.json index a610c91..a2b3863 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,22 @@ "default": true, "description": "Show warnings when dependency engines mismatch with the current package" }, + "npmx.ignore.deprecation": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "List of package names to ignore deprecation warnings for (e.g. [\"nuxt\", \"lodash\"])" + }, + "npmx.ignore.replacement": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "List of package names to ignore replacement suggestions for (e.g. [\"left-pad\", \"is-odd\"])" + }, "npmx.ignore.vulnerability": { "type": "array", "items": { diff --git a/src/providers/code-actions/index.ts b/src/providers/code-actions/index.ts index 11d66cd..ae7e708 100644 --- a/src/providers/code-actions/index.ts +++ b/src/providers/code-actions/index.ts @@ -16,7 +16,7 @@ export function useCodeActions() { await config.update(scope, [...current, name], target) }) - const hasQuickFix = computed(() => config.diagnostics.upgrade || config.diagnostics.vulnerability) + const hasQuickFix = computed(() => config.diagnostics.upgrade || config.diagnostics.deprecation || config.diagnostics.replacement || config.diagnostics.vulnerability) watch(hasQuickFix, (enabled, _, onCleanup) => { if (!enabled) diff --git a/src/providers/code-actions/quick-fix.ts b/src/providers/code-actions/quick-fix.ts index 1a99be6..e4195e2 100644 --- a/src/providers/code-actions/quick-fix.ts +++ b/src/providers/code-actions/quick-fix.ts @@ -24,6 +24,12 @@ interface AddIgnoreRule { } const addIgnoreRules: Partial> = { + deprecation: { + pattern: /^"(?\S+)" has been deprecated/, + }, + replacement: { + pattern: /^"(?\S+)"/, + }, vulnerability: { pattern: /^"(?\S+)" has .+ vulnerabilit/, }, diff --git a/src/providers/diagnostics/rules/deprecation.ts b/src/providers/diagnostics/rules/deprecation.ts index 5eaaa20..a419a30 100644 --- a/src/providers/diagnostics/rules/deprecation.ts +++ b/src/providers/diagnostics/rules/deprecation.ts @@ -1,4 +1,5 @@ import type { DiagnosticRule } from '..' +import { config } from '#state' import { npmxPackageUrl } from '#utils/links' import { formatPackageId } from '#utils/package' import { DiagnosticSeverity, DiagnosticTag, Uri } from 'vscode' @@ -7,6 +8,9 @@ export const checkDeprecation: DiagnosticRule = ({ dep, pkg, parsed, exactVersio if (!parsed || !exactVersion) return + if (config.ignore.deprecation.includes(dep.name)) + return + const versionInfo = pkg.versionsMeta[exactVersion] if (!versionInfo.deprecated) diff --git a/src/providers/diagnostics/rules/replacement.ts b/src/providers/diagnostics/rules/replacement.ts index be99efe..e3f7bb8 100644 --- a/src/providers/diagnostics/rules/replacement.ts +++ b/src/providers/diagnostics/rules/replacement.ts @@ -1,5 +1,6 @@ import type { ModuleReplacement } from 'module-replacements' import type { DiagnosticRule } from '..' +import { config } from '#state' import { getReplacement } from '#utils/api/replacement' import { DiagnosticSeverity, Uri } from 'vscode' @@ -20,26 +21,29 @@ function getReplacementInfo(replacement: ModuleReplacement) { switch (replacement.type) { case 'native': return { - message: `This can be replaced with ${replacement.replacement}, available since Node ${replacement.nodeVersion}.`, + message: `can be replaced with ${replacement.replacement}, available since Node ${replacement.nodeVersion}.`, link: getMdnUrl(replacement.mdnPath), } case 'simple': return { - message: `The community has flagged this package as redundant, with the advice:\n${replacement.replacement}.`, + message: `has been flagged as redundant, with the advice:\n${replacement.replacement}.`, } case 'documented': return { - message: 'The community has flagged this package as having more performant alternatives.', + message: 'has been flagged as having more performant alternatives.', link: getReplacementsDocUrl(replacement.docPath), } case 'none': return { - message: 'This package has been flagged as no longer needed, and its functionality is likely available natively in all engines.', + message: 'has been flagged as no longer needed, and its functionality is likely available natively in all engines.', } } } export const checkReplacement: DiagnosticRule = async ({ dep }) => { + if (config.ignore.replacement.includes(dep.name)) + return + const replacement = await getReplacement(dep.name) if (!replacement) return @@ -48,7 +52,7 @@ export const checkReplacement: DiagnosticRule = async ({ dep }) => { return { node: dep.nameNode, - message, + message: `"${dep.name}" ${message}`, severity: DiagnosticSeverity.Warning, code: link ? { value: 'replacement', target: Uri.parse(link) } : 'replacement', } diff --git a/tests/__setup__/index.ts b/tests/__setup__/index.ts index a5b577e..d243cad 100644 --- a/tests/__setup__/index.ts +++ b/tests/__setup__/index.ts @@ -6,6 +6,8 @@ vi.mock('#state', () => ({ logger: { info: vi.fn(), warn: vi.fn() }, config: { ignore: { + deprecation: [], + replacement: [], vulnerability: [], }, }, From c8f65c81e31deceed47115501b892278307aad54 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Sun, 1 Mar 2026 15:57:25 +0800 Subject: [PATCH 4/6] feat: allow ignore by package name --- README.md | 28 +++++++++---------- package.json | 6 ++-- .../diagnostics/rules/deprecation.ts | 7 +++-- .../diagnostics/rules/vulnerability.ts | 3 +- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index a21ca72..d1f6b58 100644 --- a/README.md +++ b/README.md @@ -38,20 +38,20 @@ -| Key | Description | Type | Default | -| ----------------------------------- | ----------------------------------------------------------------------------------------- | --------- | ------------------- | -| `npmx.hover.enabled` | Enable hover information for packages | `boolean` | `true` | -| `npmx.completion.version` | Version completion behavior | `string` | `"provenance-only"` | -| `npmx.completion.excludePrerelease` | Exclude prerelease versions (alpha, beta, rc, canary, etc.) from completion suggestions | `boolean` | `true` | -| `npmx.diagnostics.upgrade` | Show hints when a newer version of a package is available | `boolean` | `true` | -| `npmx.diagnostics.deprecation` | Show warnings for deprecated packages | `boolean` | `true` | -| `npmx.diagnostics.replacement` | Show suggestions for package replacements | `boolean` | `true` | -| `npmx.diagnostics.vulnerability` | Show warnings for packages with known vulnerabilities | `boolean` | `true` | -| `npmx.diagnostics.distTag` | Show warnings when a dependency uses a dist tag | `boolean` | `true` | -| `npmx.diagnostics.engineMismatch` | Show warnings when dependency engines mismatch with the current package | `boolean` | `true` | -| `npmx.ignore.deprecation` | List of package names to ignore deprecation warnings for (e.g. ["nuxt", "lodash"]) | `array` | `[]` | -| `npmx.ignore.replacement` | List of package names to ignore replacement suggestions for (e.g. ["left-pad", "is-odd"]) | `array` | `[]` | -| `npmx.ignore.vulnerability` | List of package names to ignore vulnerability warnings for (e.g. ["nuxt", "lodash"]) | `array` | `[]` | +| Key | Description | Type | Default | +| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | --------- | ------------------- | +| `npmx.hover.enabled` | Enable hover information for packages | `boolean` | `true` | +| `npmx.completion.version` | Version completion behavior | `string` | `"provenance-only"` | +| `npmx.completion.excludePrerelease` | Exclude prerelease versions (alpha, beta, rc, canary, etc.) from completion suggestions | `boolean` | `true` | +| `npmx.diagnostics.upgrade` | Show hints when a newer version of a package is available | `boolean` | `true` | +| `npmx.diagnostics.deprecation` | Show warnings for deprecated packages | `boolean` | `true` | +| `npmx.diagnostics.replacement` | Show suggestions for package replacements | `boolean` | `true` | +| `npmx.diagnostics.vulnerability` | Show warnings for packages with known vulnerabilities | `boolean` | `true` | +| `npmx.diagnostics.distTag` | Show warnings when a dependency uses a dist tag | `boolean` | `true` | +| `npmx.diagnostics.engineMismatch` | Show warnings when dependency engines mismatch with the current package | `boolean` | `true` | +| `npmx.ignore.deprecation` | List of packages to ignore deprecation warnings for. Supports both "name" and "name@version" (e.g. ["request", "uuid@3.4.0"]) | `array` | `[]` | +| `npmx.ignore.replacement` | List of package names to ignore replacement suggestions for (e.g. ["find-up", "axios"]) | `array` | `[]` | +| `npmx.ignore.vulnerability` | List of packages to ignore vulnerability warnings for. Supports both "name" and "name@version" (e.g. ["lodash", "express@4.18.0"]) | `array` | `[]` | diff --git a/package.json b/package.json index a2b3863..7754cf7 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,7 @@ "type": "string" }, "default": [], - "description": "List of package names to ignore deprecation warnings for (e.g. [\"nuxt\", \"lodash\"])" + "description": "List of packages to ignore deprecation warnings for. Supports both \"name\" and \"name@version\" (e.g. [\"request\", \"uuid@3.4.0\"])" }, "npmx.ignore.replacement": { "type": "array", @@ -113,7 +113,7 @@ "type": "string" }, "default": [], - "description": "List of package names to ignore replacement suggestions for (e.g. [\"left-pad\", \"is-odd\"])" + "description": "List of package names to ignore replacement suggestions for (e.g. [\"find-up\", \"axios\"])" }, "npmx.ignore.vulnerability": { "type": "array", @@ -121,7 +121,7 @@ "type": "string" }, "default": [], - "description": "List of package names to ignore vulnerability warnings for (e.g. [\"nuxt\", \"lodash\"])" + "description": "List of packages to ignore vulnerability warnings for. Supports both \"name\" and \"name@version\" (e.g. [\"lodash\", \"express@4.18.0\"])" } } }, diff --git a/src/providers/diagnostics/rules/deprecation.ts b/src/providers/diagnostics/rules/deprecation.ts index a419a30..dfc7b54 100644 --- a/src/providers/diagnostics/rules/deprecation.ts +++ b/src/providers/diagnostics/rules/deprecation.ts @@ -8,14 +8,15 @@ export const checkDeprecation: DiagnosticRule = ({ dep, pkg, parsed, exactVersio if (!parsed || !exactVersion) return - if (config.ignore.deprecation.includes(dep.name)) - return - const versionInfo = pkg.versionsMeta[exactVersion] if (!versionInfo.deprecated) return + const ignoreList = config.ignore.deprecation + if (ignoreList.includes(dep.name) || ignoreList.includes(formatPackageId(dep.name, exactVersion))) + return + return { node: dep.versionNode, message: `"${formatPackageId(dep.name, exactVersion)}" has been deprecated: ${versionInfo.deprecated}`, diff --git a/src/providers/diagnostics/rules/vulnerability.ts b/src/providers/diagnostics/rules/vulnerability.ts index 5a377db..3e4e25b 100644 --- a/src/providers/diagnostics/rules/vulnerability.ts +++ b/src/providers/diagnostics/rules/vulnerability.ts @@ -32,7 +32,8 @@ export const checkVulnerability: DiagnosticRule = async ({ dep, parsed, exactVer if (!parsed || !exactVersion) return - if (config.ignore.vulnerability.includes(dep.name)) + const ignoreList = config.ignore.vulnerability + if (ignoreList.includes(dep.name) || ignoreList.includes(formatPackageId(dep.name, exactVersion))) return const result = await getVulnerability({ name: dep.name, version: exactVersion }) From 11c1331f01b5da4db699298c4b8acb660e86ab61 Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Mon, 2 Mar 2026 17:29:24 +0800 Subject: [PATCH 5/6] feat: allow ignore upgrade --- README.md | 29 +++++++++++----------- package.json | 14 ++++++++--- src/providers/diagnostics/rules/upgrade.ts | 6 +++++ tests/__setup__/index.ts | 1 + 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index d1f6b58..0c1d7d4 100644 --- a/README.md +++ b/README.md @@ -38,20 +38,21 @@ -| Key | Description | Type | Default | -| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | --------- | ------------------- | -| `npmx.hover.enabled` | Enable hover information for packages | `boolean` | `true` | -| `npmx.completion.version` | Version completion behavior | `string` | `"provenance-only"` | -| `npmx.completion.excludePrerelease` | Exclude prerelease versions (alpha, beta, rc, canary, etc.) from completion suggestions | `boolean` | `true` | -| `npmx.diagnostics.upgrade` | Show hints when a newer version of a package is available | `boolean` | `true` | -| `npmx.diagnostics.deprecation` | Show warnings for deprecated packages | `boolean` | `true` | -| `npmx.diagnostics.replacement` | Show suggestions for package replacements | `boolean` | `true` | -| `npmx.diagnostics.vulnerability` | Show warnings for packages with known vulnerabilities | `boolean` | `true` | -| `npmx.diagnostics.distTag` | Show warnings when a dependency uses a dist tag | `boolean` | `true` | -| `npmx.diagnostics.engineMismatch` | Show warnings when dependency engines mismatch with the current package | `boolean` | `true` | -| `npmx.ignore.deprecation` | List of packages to ignore deprecation warnings for. Supports both "name" and "name@version" (e.g. ["request", "uuid@3.4.0"]) | `array` | `[]` | -| `npmx.ignore.replacement` | List of package names to ignore replacement suggestions for (e.g. ["find-up", "axios"]) | `array` | `[]` | -| `npmx.ignore.vulnerability` | List of packages to ignore vulnerability warnings for. Supports both "name" and "name@version" (e.g. ["lodash", "express@4.18.0"]) | `array` | `[]` | +| Key | Description | Type | Default | +| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | --------- | ------------------- | +| `npmx.hover.enabled` | Enable hover information for packages | `boolean` | `true` | +| `npmx.completion.version` | Version completion behavior | `string` | `"provenance-only"` | +| `npmx.completion.excludePrerelease` | Exclude prerelease versions (alpha, beta, rc, canary, etc.) from completion suggestions | `boolean` | `true` | +| `npmx.diagnostics.upgrade` | Show hints when a newer version of a package is available | `boolean` | `true` | +| `npmx.diagnostics.deprecation` | Show warnings for deprecated packages | `boolean` | `true` | +| `npmx.diagnostics.replacement` | Show suggestions for package replacements | `boolean` | `true` | +| `npmx.diagnostics.vulnerability` | Show warnings for packages with known vulnerabilities | `boolean` | `true` | +| `npmx.diagnostics.distTag` | Show warnings when a dependency uses a dist tag | `boolean` | `true` | +| `npmx.diagnostics.engineMismatch` | Show warnings when dependency engines mismatch with the current package | `boolean` | `true` | +| `npmx.ignore.upgrade` | List of packages to ignore upgrade hints. Supports both "name" and "name@version" (e.g. ["request", "uuid@3.4.0"]) | `array` | `[]` | +| `npmx.ignore.deprecation` | List of packages to ignore deprecation warnings. Supports both "name" and "name@version" (e.g. ["request", "uuid@3.4.0"]) | `array` | `[]` | +| `npmx.ignore.replacement` | List of package names to ignore replacement suggestions. (e.g. ["find-up", "axios"]) | `array` | `[]` | +| `npmx.ignore.vulnerability` | List of packages to ignore vulnerability warnings. Supports both "name" and "name@version" (e.g. ["lodash", "express@4.18.0"]) | `array` | `[]` | diff --git a/package.json b/package.json index 7754cf7..615c4e2 100644 --- a/package.json +++ b/package.json @@ -99,13 +99,21 @@ "default": true, "description": "Show warnings when dependency engines mismatch with the current package" }, + "npmx.ignore.upgrade": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "List of packages to ignore upgrade hints. Supports both \"name\" and \"name@version\" (e.g. [\"request\", \"uuid@3.4.0\"])" + }, "npmx.ignore.deprecation": { "type": "array", "items": { "type": "string" }, "default": [], - "description": "List of packages to ignore deprecation warnings for. Supports both \"name\" and \"name@version\" (e.g. [\"request\", \"uuid@3.4.0\"])" + "description": "List of packages to ignore deprecation warnings. Supports both \"name\" and \"name@version\" (e.g. [\"request\", \"uuid@3.4.0\"])" }, "npmx.ignore.replacement": { "type": "array", @@ -113,7 +121,7 @@ "type": "string" }, "default": [], - "description": "List of package names to ignore replacement suggestions for (e.g. [\"find-up\", \"axios\"])" + "description": "List of package names to ignore replacement suggestions. (e.g. [\"find-up\", \"axios\"])" }, "npmx.ignore.vulnerability": { "type": "array", @@ -121,7 +129,7 @@ "type": "string" }, "default": [], - "description": "List of packages to ignore vulnerability warnings for. Supports both \"name\" and \"name@version\" (e.g. [\"lodash\", \"express@4.18.0\"])" + "description": "List of packages to ignore vulnerability warnings. Supports both \"name\" and \"name@version\" (e.g. [\"lodash\", \"express@4.18.0\"])" } } }, diff --git a/src/providers/diagnostics/rules/upgrade.ts b/src/providers/diagnostics/rules/upgrade.ts index 17643b8..c543ee5 100644 --- a/src/providers/diagnostics/rules/upgrade.ts +++ b/src/providers/diagnostics/rules/upgrade.ts @@ -1,7 +1,9 @@ import type { DependencyInfo } from '#types/extractor' import type { ParsedVersion } from '#utils/version' import type { DiagnosticRule, NodeDiagnosticInfo } from '..' +import { config } from '#state' import { npmxPackageUrl } from '#utils/links' +import { formatPackageId } from '#utils/package' import { formatUpgradeVersion } from '#utils/version' import gt from 'semver/functions/gt' import lte from 'semver/functions/lte' @@ -24,6 +26,10 @@ export const checkUpgrade: DiagnosticRule = ({ dep, pkg, parsed, exactVersion }) if (!parsed || !exactVersion) return + const ignoreList = config.ignore.upgrade + if (ignoreList.includes(dep.name) || ignoreList.includes(formatPackageId(dep.name, exactVersion))) + return + if (Object.hasOwn(pkg.distTags, exactVersion)) return diff --git a/tests/__setup__/index.ts b/tests/__setup__/index.ts index d243cad..eb022f0 100644 --- a/tests/__setup__/index.ts +++ b/tests/__setup__/index.ts @@ -6,6 +6,7 @@ vi.mock('#state', () => ({ logger: { info: vi.fn(), warn: vi.fn() }, config: { ignore: { + upgrade: [], deprecation: [], replacement: [], vulnerability: [], From c85a43e3c5f43f706c04dc34fa35ae88ac12316f Mon Sep 17 00:00:00 2001 From: Vida Xie Date: Mon, 2 Mar 2026 17:46:45 +0800 Subject: [PATCH 6/6] add configration scope --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index 615c4e2..9ecbe8a 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,7 @@ "description": "Show warnings when dependency engines mismatch with the current package" }, "npmx.ignore.upgrade": { + "scope": "resource", "type": "array", "items": { "type": "string" @@ -108,6 +109,7 @@ "description": "List of packages to ignore upgrade hints. Supports both \"name\" and \"name@version\" (e.g. [\"request\", \"uuid@3.4.0\"])" }, "npmx.ignore.deprecation": { + "scope": "resource", "type": "array", "items": { "type": "string" @@ -116,6 +118,7 @@ "description": "List of packages to ignore deprecation warnings. Supports both \"name\" and \"name@version\" (e.g. [\"request\", \"uuid@3.4.0\"])" }, "npmx.ignore.replacement": { + "scope": "resource", "type": "array", "items": { "type": "string" @@ -124,6 +127,7 @@ "description": "List of package names to ignore replacement suggestions. (e.g. [\"find-up\", \"axios\"])" }, "npmx.ignore.vulnerability": { + "scope": "resource", "type": "array", "items": { "type": "string"