@@ -7,12 +7,110 @@ import { encodePackageName } from './npm'
77export const NPMX_DEV_API = 'https://npmx.dev/api'
88
99export const getReplacement = memoize < string , Promise < ModuleReplacement > > ( async ( name ) => {
10- logger . info ( `Fetching replacement for ${ name } ` )
10+ logger . info ( `Fetching replacements for ${ name } ` )
1111 const encodedName = encodePackageName ( name )
1212
1313 const result = await ofetch < ModuleReplacement > ( `${ NPMX_DEV_API } /replacements/${ encodedName } ` )
14- // Fallback for cache compatibility (LRUCache rejects null/undefined)
15- ?? { }
16- logger . info ( `Fetched replacement for ${ name } ` )
14+ logger . info ( `Fetched replacements for ${ name } ` )
15+
16+ return result
17+ } )
18+
19+ /**
20+ * Severity levels in priority order (highest first)
21+ */
22+ export const SEVERITY_LEVELS = [ 'critical' , 'high' , 'moderate' , 'low' ] as const
23+
24+ /**
25+ * Severity level derived from CVSS score
26+ */
27+ export type OsvSeverityLevel = ( typeof SEVERITY_LEVELS ) [ number ] | 'unknown'
28+
29+ /**
30+ * Simplified vulnerability info for display
31+ */
32+ export interface VulnerabilitySummary {
33+ id : string
34+ summary : string
35+ severity : OsvSeverityLevel
36+ aliases : string [ ]
37+ url : string
38+ }
39+
40+ /** Depth in dependency tree */
41+ export type DependencyDepth = 'root' | 'direct' | 'transitive'
42+
43+ /**
44+ * Vulnerability info for a single package in the tree
45+ */
46+ export interface PackageVulnerabilityInfo {
47+ name : string
48+ version : string
49+ /** Depth in dependency tree: root (0), direct (1), transitive (2+) */
50+ depth : DependencyDepth
51+ /** Dependency path from root package */
52+ path : string [ ]
53+ vulnerabilities : VulnerabilitySummary [ ]
54+ counts : {
55+ total : number
56+ critical : number
57+ high : number
58+ moderate : number
59+ low : number
60+ }
61+ }
62+
63+ /**
64+ * Deprecated package info in the dependency tree
65+ */
66+ export interface DeprecatedPackageInfo {
67+ name : string
68+ version : string
69+ /** Depth in dependency tree: root (0), direct (1), transitive (2+) */
70+ depth : DependencyDepth
71+ /** Dependency path from root package */
72+ path : string [ ]
73+ /** Deprecation message */
74+ message : string
75+ }
76+
77+ /**
78+ * Result of dependency tree analysis
79+ */
80+ export interface VulnerabilityTreeResult {
81+ /** Root package name */
82+ package : string
83+ /** Root package version */
84+ version : string
85+ /** All packages with vulnerabilities in the tree */
86+ vulnerablePackages : PackageVulnerabilityInfo [ ]
87+ /** All deprecated packages in the tree */
88+ deprecatedPackages : DeprecatedPackageInfo [ ]
89+ /** Total packages analyzed */
90+ totalPackages : number
91+ /** Number of packages that could not be checked (OSV query failed) */
92+ failedQueries : number
93+ /** Aggregated counts across all packages */
94+ totalCounts : {
95+ total : number
96+ critical : number
97+ high : number
98+ moderate : number
99+ low : number
100+ }
101+ }
102+
103+ export const getVulnerability = memoize < {
104+ name : string
105+ version : string
106+ } , Promise < VulnerabilityTreeResult > > ( async ( { name, version } ) => {
107+ logger . info ( `Fetching vulnerabilities for ${ name } ` )
108+ const encodedName = encodePackageName ( name )
109+
110+ const result = await ofetch ( `${ NPMX_DEV_API } /registry/vulnerabilities/${ encodedName } /v/${ version } ` )
111+ logger . info ( `Fetched vulnerabilities for ${ name } ` )
112+
17113 return result
114+ } , {
115+ getKey : ( { name : packageName , version } ) => `${ packageName } :${ version } ` ,
18116} )
0 commit comments