Skip to content

Commit ca7f3c2

Browse files
authored
feat: assets list/folder (#26)
1 parent 34150eb commit ca7f3c2

File tree

9 files changed

+204
-17
lines changed

9 files changed

+204
-17
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<script setup lang="ts">
2+
import type { Asset as AssetInfo } from '@rolldown/debug'
3+
import type { ModuleDest, SessionContext } from '~~/shared/types'
4+
import { computed } from 'vue'
5+
import { toTree } from '../../utils/format'
6+
7+
const props = defineProps<{
8+
assets: AssetInfo[]
9+
session: SessionContext
10+
}>()
11+
const assetTree = computed(() => {
12+
const nodes: ModuleDest[] = []
13+
props.assets.forEach((i) => {
14+
nodes.push({
15+
full: i.filename,
16+
path: i.filename,
17+
})
18+
})
19+
return toTree(nodes, 'Project')
20+
})
21+
</script>
22+
23+
<template>
24+
<div flex="~ gap-2">
25+
<DisplayTreeNode
26+
v-if="assets?.length"
27+
flex-1
28+
:node="assetTree"
29+
icon="i-catppuccin:folder-dist catppuccin"
30+
icon-open="i-catppuccin:folder-dist-open catppuccin"
31+
:link="true"
32+
link-query-key="asset"
33+
/>
34+
</div>
35+
</template>
36+
37+
<style scoped>
38+
39+
</style>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<script setup lang="ts">
2+
import type { Asset as AssetInfo } from '@rolldown/debug'
3+
4+
defineProps<{
5+
assets: AssetInfo[]
6+
}>()
7+
</script>
8+
9+
<template>
10+
<div p4>
11+
<div flex="~ col gap-1">
12+
<template v-for="asset in assets" :key="asset.id">
13+
<NuxtLink
14+
:to="{ query: { asset: asset.filename } }"
15+
font-mono border="~ rounded base" px2 py1 text-sm hover="bg-active"
16+
>
17+
<div flex="~ gap-1">
18+
<DisplayFileIcon :filename="asset.filename" />
19+
{{ asset.filename }}
20+
</div>
21+
</NuxtLink>
22+
</template>
23+
</div>
24+
</div>
25+
</template>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<script setup lang="ts">
2+
import type { RolldownAssetInfo, RolldownChunkInfo, SessionContext } from '~~/shared/types'
3+
import { useRpc } from '#imports'
4+
import { useAsyncState } from '@vueuse/core'
5+
6+
const props = defineProps<{
7+
asset: string
8+
session: SessionContext
9+
}>()
10+
11+
const emit = defineEmits<{
12+
(e: 'close'): void
13+
}>()
14+
15+
const rpc = useRpc()
16+
const { state } = useAsyncState(
17+
async () => {
18+
const res = await rpc.value!['vite:rolldown:get-asset-details']?.({
19+
session: props.session.id,
20+
id: props.asset,
21+
})
22+
return {
23+
asset: { ...res?.asset, type: 'asset' },
24+
chunks: [{ ...res?.chunk, type: 'chunk' }],
25+
} satisfies {
26+
asset: RolldownAssetInfo
27+
chunks: RolldownChunkInfo[]
28+
}
29+
},
30+
null,
31+
)
32+
</script>
33+
34+
<template>
35+
<div v-if="state?.asset" p4 relative h-full w-full of-auto pt12>
36+
<DisplayCloseButton
37+
absolute right-2 top-1.5
38+
@click="emit('close')"
39+
/>
40+
<DataAssetDetails :asset="state.asset" :session="session" :chunks="state?.chunks" />
41+
</div>
42+
</template>

packages/devtools/src/app/components/display/TreeNode.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ const props = withDefaults(defineProps<{
88
icon?: string
99
iconOpen?: string
1010
link?: string | boolean
11+
linkQueryKey?: string
1112
padding?: number
1213
open?: boolean
1314
}>(), {
1415
icon: 'i-catppuccin:folder icon-catppuccin',
1516
iconOpen: 'i-catppuccin:folder-open icon-catppuccin',
1617
padding: 0,
18+
linkQueryKey: 'module',
1719
})
1820
1921
const emit = defineEmits<{
@@ -53,11 +55,13 @@ function select(node: ModuleDest) {
5355
v-for="e of Object.entries(node.children)"
5456
:key="e[0]" :node="e[1]" :link="link"
5557
:padding="padding + 1"
58+
:link-query-key="linkQueryKey"
59+
@select="select"
5660
/>
5761
<template v-for="i of node.items" :key="i.full">
5862
<component
5963
:is="link ? NuxtLink : 'div'"
60-
:to="link ? (typeof link === 'string' ? link : { path: route.path, query: { ...route.query, module: i.full }, hash: location.hash }) : undefined"
64+
:to="link ? (typeof link === 'string' ? link : { path: route.path, query: { ...route.query, [linkQueryKey]: i.full }, hash: location.hash }) : undefined"
6165
text-sm
6266
ws-nowrap
6367
flex="~ gap-1"

packages/devtools/src/app/pages/session/[session].vue

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ function closeFlowPanel() {
2525
router.replace({ query: { ...route.query, module: undefined } })
2626
}
2727
28+
function closeAssetPanel() {
29+
router.replace({ query: { ...route.query, asset: undefined } })
30+
}
31+
2832
useSideNav(() => {
2933
if (!session.meta)
3034
return []
@@ -101,5 +105,25 @@ onMounted(async () => {
101105
/>
102106
</div>
103107
</div>
108+
109+
<!-- for assets -->
110+
<div
111+
v-if="route.query.asset" fixed inset-0
112+
backdrop-blur-8 backdrop-brightness-95 z-panel-content
113+
>
114+
<div
115+
:key="(route.query.asset as string)"
116+
v-on-click-outside="closeAssetPanel"
117+
fixed right-0 bottom-0 top-30 z-panel-content of-auto
118+
bg-glass border="l t base rounded-tl-xl"
119+
class="left-20 xl:left-100 2xl:left-150"
120+
>
121+
<DataAssetDetailsLoader
122+
:asset="(route.query.asset as string)"
123+
:session="session"
124+
@close="closeAssetPanel"
125+
/>
126+
</div>
127+
</div>
104128
</div>
105129
</template>
Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,31 @@
11
<script setup lang="ts">
22
import type { SessionContext } from '~~/shared/types'
3+
import type { ClientSettings } from '~/state/settings'
34
import { useRpc } from '#imports'
45
import { useAsyncState } from '@vueuse/core'
6+
import { settings } from '~/state/settings'
57
68
const props = defineProps<{
79
session: SessionContext
810
}>()
911
12+
const assetViewTpyes = [
13+
{
14+
label: 'List',
15+
value: 'list',
16+
icon: 'i-ph-list-duotone',
17+
},
18+
{
19+
label: 'Folder',
20+
value: 'folder',
21+
icon: 'i-ph-folder-duotone',
22+
},
23+
{
24+
label: 'Flamechart',
25+
value: 'flamechart',
26+
icon: 'i-ph-chart-donut-duotone',
27+
},
28+
] as const
1029
const rpc = useRpc()
1130
const { state: assets, isLoading } = useAsyncState(
1231
async () => {
@@ -16,26 +35,35 @@ const { state: assets, isLoading } = useAsyncState(
1635
},
1736
null,
1837
)
38+
39+
function toggleDisplay(type: ClientSettings['assetViewType']) {
40+
settings.value.assetViewType = type
41+
}
1942
</script>
2043

2144
<template>
2245
<VisualLoading v-if="isLoading" />
23-
<div p5 flex="~ col gap-4">
24-
Assets
25-
<!--
26-
WIP:
27-
- Use tree view to show assets
28-
- Show asssets detail on the right panel
29-
- View of Flamechart with nanovis
30-
-->
31-
<template v-for="asset of assets" :key="asset.filename">
32-
<pre>{{
33-
{
34-
filename: asset.filename,
35-
size: asset.size,
36-
chunk: asset.chunk_id,
37-
}
38-
}}</pre>
46+
<div v-else p4 flex="~ col gap-4">
47+
<div flex="~ gap-2">
48+
<button
49+
v-for="viewType of assetViewTpyes"
50+
:key="viewType.value"
51+
btn-action
52+
:class="settings.assetViewType === viewType.value ? 'bg-active' : 'grayscale op50'"
53+
@click="toggleDisplay(viewType.value)"
54+
>
55+
<div :class="viewType.icon" />
56+
{{ viewType.label }}
57+
</button>
58+
</div>
59+
<template v-if="settings.assetViewType === 'list'">
60+
<AssetsList v-if="assets?.length" :assets="assets" :session="session" />
61+
</template>
62+
<template v-else-if="settings.assetViewType === 'folder'">
63+
<AssetsFolder v-if="assets?.length" :assets="assets" :session="session" />
64+
</template>
65+
<template v-else>
66+
WIP: Flamechart view
3967
</template>
4068
</div>
4169
</template>

packages/devtools/src/app/state/settings.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface ClientSettings {
1313
flowExpandAssets: boolean
1414
flowShowAllTransforms: boolean
1515
flowShowAllLoads: boolean
16+
assetViewType: 'list' | 'folder' | 'flamechart'
1617
}
1718

1819
export const settings = useLocalStorage<ClientSettings>(
@@ -28,6 +29,7 @@ export const settings = useLocalStorage<ClientSettings>(
2829
flowExpandAssets: true,
2930
flowShowAllTransforms: false,
3031
flowShowAllLoads: false,
32+
assetViewType: 'list',
3133
},
3234
{
3335
mergeDefaults: true,
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { defineRpcFunction } from '../utils'
2+
3+
export const rolldownGetAssetDetails = defineRpcFunction({
4+
name: 'vite:rolldown:get-asset-details',
5+
type: 'query',
6+
setup: ({ manager }) => {
7+
return {
8+
handler: async ({ session, id }: { session: string, id: string }) => {
9+
const reader = await manager.loadSession(session)
10+
const assets = await reader.manager.assets
11+
const chunks = await reader.manager.chunks
12+
const asset = assets.get(id)!
13+
const chunk = chunks.get(asset.chunk_id!)!
14+
return {
15+
asset,
16+
chunk,
17+
}
18+
},
19+
}
20+
},
21+
})

packages/devtools/src/node/rpc/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { DefinitionsToFunctions, FilterDefinitions } from './types'
22
import { getPayload } from './functions/get-payload'
33
import { openInEditor } from './functions/open-in-editor'
44
import { openInFinder } from './functions/open-in-finder'
5+
import { rolldownGetAssetDetails } from './functions/rolldown-get-asset-details'
56
import { rolldownGetAssetsList } from './functions/rolldown-get-assets-list'
67
import { rolldownGetChunksGraph } from './functions/rolldown-get-chunks-graph'
78
import { rolldownGetModuleInfo } from './functions/rolldown-get-module-info'
@@ -23,6 +24,7 @@ export const rpcFunctions = [
2324
rolldownGetModuleTransforms,
2425
rolldownGetChunksGraph,
2526
rolldownGetAssetsList,
27+
rolldownGetAssetDetails,
2628
] as const
2729

2830
export type ServerFunctions = DefinitionsToFunctions<typeof rpcFunctions>

0 commit comments

Comments
 (0)