@@ -8,16 +8,21 @@ import type {
88import { encodePackageName } from '#shared/utils/npm'
99import type { PackageAnalysisResponse } from './usePackageAnalysis'
1010import { isBinaryOnlyPackage } from '#shared/utils/binary-detection'
11+ import { formatBytes } from '~/utils/formatters'
12+ import { getDependencyCount } from '~/utils/npm/dependency-count'
1113
1214export interface PackageComparisonData {
1315 package : ComparisonPackage
1416 downloads ?: number
1517 /** Package's own unpacked size (from dist.unpackedSize) */
1618 packageSize ?: number
19+ /** Number of direct dependencies */
20+ directDeps : number | null
1721 /** Install size data (fetched lazily) */
1822 installSize ?: {
1923 selfSize : number
2024 totalSize : number
25+ /** Total dependency count */
2126 dependencyCount : number
2227 }
2328 analysis ?: PackageAnalysisResponse
@@ -139,6 +144,7 @@ export function usePackageComparison(packageNames: MaybeRefOrGetter<string[]>) {
139144 } ,
140145 downloads : downloads ?. downloads ,
141146 packageSize,
147+ directDeps : versionData ? getDependencyCount ( versionData ) : null ,
142148 installSize : undefined , // Will be filled in second pass
143149 analysis : analysis ?? undefined ,
144150 vulnerabilities : {
@@ -230,7 +236,7 @@ export function usePackageComparison(packageNames: MaybeRefOrGetter<string[]>) {
230236 function isFacetLoading ( facet : ComparisonFacet ) : boolean {
231237 if ( ! installSizeLoading . value ) return false
232238 // These facets depend on install-size API
233- return facet === 'installSize' || facet === 'dependencies '
239+ return facet === 'installSize' || facet === 'totalDependencies '
234240 }
235241
236242 // Check if a specific column (package) is loading
@@ -255,40 +261,40 @@ function computeFacetValue(
255261 t : ( key : string , params ?: Record < string , unknown > ) => string ,
256262) : FacetValue | null {
257263 switch ( facet ) {
258- case 'downloads' :
264+ case 'downloads' : {
259265 if ( data . downloads === undefined ) return null
260266 return {
261267 raw : data . downloads ,
262268 display : formatCompactNumber ( data . downloads ) ,
263269 status : 'neutral' ,
264270 }
265-
266- case 'packageSize' :
271+ }
272+ case 'packageSize' : {
267273 if ( ! data . packageSize ) return null
268274 return {
269275 raw : data . packageSize ,
270276 display : formatBytes ( data . packageSize ) ,
271277 status : data . packageSize > 5 * 1024 * 1024 ? 'warning' : 'neutral' ,
272278 }
273-
274- case 'installSize' :
279+ }
280+ case 'installSize' : {
275281 if ( ! data . installSize ) return null
276282 return {
277283 raw : data . installSize . totalSize ,
278284 display : formatBytes ( data . installSize . totalSize ) ,
279285 status : data . installSize . totalSize > 50 * 1024 * 1024 ? 'warning' : 'neutral' ,
280286 }
281-
282- case 'moduleFormat' :
287+ }
288+ case 'moduleFormat' : {
283289 if ( ! data . analysis ) return null
284290 const format = data . analysis . moduleFormat
285291 return {
286292 raw : format ,
287293 display : format === 'dual' ? 'ESM + CJS' : format . toUpperCase ( ) ,
288294 status : format === 'esm' || format === 'dual' ? 'good' : 'neutral' ,
289295 }
290-
291- case 'types' :
296+ }
297+ case 'types' : {
292298 if ( data . isBinaryOnly ) {
293299 return {
294300 raw : 'binary' ,
@@ -309,8 +315,8 @@ function computeFacetValue(
309315 : t ( 'compare.facets.values.types_none' ) ,
310316 status : types . kind === 'included' ? 'good' : types . kind === '@types' ? 'info' : 'bad' ,
311317 }
312-
313- case 'engines' :
318+ }
319+ case 'engines' : {
314320 const engines = data . metadata ?. engines
315321 if ( ! engines ?. node ) {
316322 return { raw : null , display : t ( 'compare.facets.values.any' ) , status : 'neutral' }
@@ -320,8 +326,8 @@ function computeFacetValue(
320326 display : `Node ${ engines . node } ` ,
321327 status : 'neutral' ,
322328 }
323-
324- case 'vulnerabilities' :
329+ }
330+ case 'vulnerabilities' : {
325331 if ( ! data . vulnerabilities ) return null
326332 const count = data . vulnerabilities . count
327333 const sev = data . vulnerabilities . severity
@@ -337,8 +343,8 @@ function computeFacetValue(
337343 } ) ,
338344 status : count === 0 ? 'good' : sev . critical > 0 || sev . high > 0 ? 'bad' : 'warning' ,
339345 }
340-
341- case 'lastUpdated' :
346+ }
347+ case 'lastUpdated' : {
342348 if ( ! data . metadata ?. lastUpdated ) return null
343349 const date = new Date ( data . metadata . lastUpdated )
344350 return {
@@ -347,8 +353,8 @@ function computeFacetValue(
347353 status : isStale ( date ) ? 'warning' : 'neutral' ,
348354 type : 'date' ,
349355 }
350-
351- case 'license' :
356+ }
357+ case 'license' : {
352358 const license = data . metadata ?. license
353359 if ( ! license ) {
354360 return { raw : null , display : t ( 'compare.facets.values.unknown' ) , status : 'warning' }
@@ -358,17 +364,17 @@ function computeFacetValue(
358364 display : license ,
359365 status : 'neutral' ,
360366 }
361-
362- case 'dependencies' :
363- if ( ! data . installSize ) return null
364- const depCount = data . installSize . dependencyCount
367+ }
368+ case 'dependencies' : {
369+ const depCount = data . directDeps
370+ if ( depCount === null ) return null
365371 return {
366372 raw : depCount ,
367373 display : String ( depCount ) ,
368- status : depCount > 50 ? 'warning' : 'neutral' ,
374+ status : depCount > 10 ? 'warning' : 'neutral' ,
369375 }
370-
371- case 'deprecated' :
376+ }
377+ case 'deprecated' : {
372378 const isDeprecated = ! ! data . metadata ?. deprecated
373379 return {
374380 raw : isDeprecated ,
@@ -377,22 +383,23 @@ function computeFacetValue(
377383 : t ( 'compare.facets.values.not_deprecated' ) ,
378384 status : isDeprecated ? 'bad' : 'good' ,
379385 }
380-
386+ }
381387 // Coming soon facets
382- case 'totalDependencies' :
383- return null
384-
385- default :
388+ case 'totalDependencies' : {
389+ if ( ! data . installSize ) return null
390+ const totalDepCount = data . installSize . dependencyCount
391+ return {
392+ raw : totalDepCount ,
393+ display : String ( totalDepCount ) ,
394+ status : totalDepCount > 50 ? 'warning' : 'neutral' ,
395+ }
396+ }
397+ default : {
386398 return null
399+ }
387400 }
388401}
389402
390- function formatBytes ( bytes : number ) : string {
391- if ( bytes < 1024 ) return `${ bytes } B`
392- if ( bytes < 1024 * 1024 ) return `${ ( bytes / 1024 ) . toFixed ( 1 ) } kB`
393- return `${ ( bytes / ( 1024 * 1024 ) ) . toFixed ( 1 ) } MB`
394- }
395-
396403function isStale ( date : Date ) : boolean {
397404 const now = new Date ( )
398405 const diffMs = now . getTime ( ) - date . getTime ( )
0 commit comments