11<script setup lang="ts">
2- import type { PackageInfo , SessionContext } from ' ~~/shared/types/data'
2+ import type { PackageInfo , PackageMeta , SessionContext } from ' ~~/shared/types/data'
33import type { ClientSettings } from ' ~/state/settings'
44import type { PackageChartInfo , PackageChartNode } from ' ~/types/chart'
55import { computedWithControl , useAsyncState , useMouse } from ' @vueuse/core'
@@ -33,13 +33,19 @@ const packageTypeRules = [
3333 description: ' Transitive Dependencies' ,
3434 icon: ' i-octicon:package-24 light:filter-invert-30!' ,
3535 },
36+ {
37+ match: / . * / ,
38+ name: ' unbundled' ,
39+ description: ' Unbundled Dependencies' ,
40+ icon: ' i-ph-package-duotone' ,
41+ },
3642]
3743const rpc = useRpc ()
38- const searchValue = ref <{ search: string , selected: string [] }>({
44+ const searchValue = ref <{ search: string , selected: string [] | null }>({
3945 search: ' ' ,
4046 selected: [' direct' , ' transitive' ],
4147})
42- const { state : packages , isLoading } = useAsyncState (
48+ const { state : packageMeta , isLoading } = useAsyncState < PackageMeta | null > (
4349 async () => {
4450 return await rpc .value .call (
4551 ' vite:rolldown:get-packages' ,
@@ -48,26 +54,43 @@ const { state: packages, isLoading } = useAsyncState(
4854 },
4955 null ,
5056)
57+ const isSupported = computed (() => packageMeta .value ?.isSupported ?? true )
58+ const packages = computed (() => packageMeta .value ?.packages ?? [])
5159
5260const fuse = computedWithControl (
5361 () => packages .value ,
54- () => new Fuse (packages .value ! , {
62+ () => new Fuse (packages .value , {
5563 includeScore: true ,
5664 keys: [' name' ],
5765 ignoreLocation: true ,
5866 threshold: 0.4 ,
5967 }),
6068)
6169
62- const duplicatePackagesCount = computed (() => {
63- if (! packages .value ) {
64- return 0
65- }
66- return Object .values (packages .value ! .reduce ((acc , p ) => {
67- acc [p .name ] = (acc [p .name ] || 0 ) + 1
68- return acc
69- }, {} as Record <string , number >)).filter (count => count > 1 ).length
70- })
70+ const searched = computed (() => (
71+ searchValue .value .search
72+ ? fuse .value .search (searchValue .value .search ).map (r => r .item )
73+ : [... packages .value ]),
74+ )
75+
76+ function matchesSelectedPackageType(item : PackageInfo ) {
77+ const selected = searchValue .value .selected
78+ if (! selected )
79+ return true
80+
81+ if (item .isUsed === false )
82+ return selected .includes (' unbundled' )
83+
84+ return selected .includes (item .type || ' ' )
85+ }
86+
87+ const filteredPackages = computed (() => searched .value .filter (matchesSelectedPackageType ))
88+
89+ const duplicatePackagesCount = computed (() => new Set (
90+ packages .value
91+ .filter (item => item .duplicated )
92+ .map (item => item .name ),
93+ ).size )
7194
7295const packageViewTypes = computed (() => [
7396 {
@@ -87,21 +110,15 @@ const packageViewTypes = computed(() => [
87110 },
88111] as const )
89112
90- const searched = computed (() => (
91- searchValue .value .search
92- ? fuse .value .search (searchValue .value .search ).map (r => r .item )
93- : [... (packages .value || [])]),
94- )
95-
96113const normalizedPackages = computed (() => {
97114 const packagesSizeSortType = settings .value .packageSizeSortType
98- const data = searched .value .toSorted ((a , b ) => (a .name || ' ' ).localeCompare (b .name || ' ' ))
115+ const data = filteredPackages .value .toSorted ((a , b ) => (a .name || ' ' ).localeCompare (b .name || ' ' ))
99116
100117 const sortedPackages = packagesSizeSortType
101118 ? data .sort ((a , b ) => packagesSizeSortType === ' asc' ? a .transformedCodeSize - b .transformedCodeSize : b .transformedCodeSize - a .transformedCodeSize )
102119 : data
103120
104- return sortedPackages . filter ( item => ! searchValue . value . selected || searchValue . value . selected . some ( rule => rule . match ( item . type ! )))
121+ return sortedPackages
105122})
106123
107124function toggleDisplay(type : ClientSettings [' packageViewType' ]) {
@@ -123,7 +140,7 @@ const { tree, chartOptions, graph, nodeHover, nodeSelected, selectedNode, select
123140 },
124141 onClick(node ) {
125142 if (node .meta ?.type === ' package' ) {
126- router .replace ({ query: { ... route .query , package: ` ${ node .meta ?. name }@${ node . meta ?. version } ` } })
143+ router .replace ({ query: { ... route .query , package: node .meta . id } })
127144 }
128145 },
129146 onLeave() {
@@ -151,6 +168,14 @@ watch(() => settings.value.packageViewType, () => {
151168
152169<template >
153170 <VisualLoading v-if =" isLoading " />
171+ <div v-else-if =" !isSupported" h-full flex =" ~ col gap-2 items-center justify-center" p4 text-center >
172+ <p m0 op50 >
173+ Package graph is not available for this build
174+ </p >
175+ <p m0 op40 text-sm >
176+ Rebuild with Rolldown 1.0.2 or later to generate it.
177+ </p >
178+ </div >
154179 <div v-else relative h-full min-h-0 flex =" ~ col" >
155180 <div sticky left-4 right-4 top-4 z-panel-nav p-4 >
156181 <DataSearchPanel v-model =" searchValue " :rules =" packageTypeRules " >
@@ -179,7 +204,7 @@ watch(() => settings.value.packageViewType, () => {
179204 <div
180205 fixed bottom-4 py-1 px-2 bg-glass left =" 1/2" translate-x =" -1/2" border =" ~ base rounded-full" text =" center xs"
181206 >
182- <span op50 >{{ searched .length }} of {{ packages? .length || 0 }}</span >
207+ <span op50 >{{ normalizedPackages .length }} of {{ packages.length }}</span >
183208 </div >
184209 </template >
185210 <template v-else-if =" settings .packageViewType === ' treemap' " >
@@ -203,7 +228,7 @@ watch(() => settings.value.packageViewType, () => {
203228 </span >
204229 </template >
205230 <template v-else-if =" settings .packageViewType === ' duplicate-packages' " >
206- <PackagesDuplicated :packages =" normalizedPackages " :session =" session " />
231+ <PackagesDuplicated :packages =" packages " :session =" session " />
207232 </template >
208233 </div >
209234 <DisplayGraphHoverView :hover-x =" mouse .x " :hover-y =" mouse .y " >
0 commit comments