@@ -55,16 +55,23 @@ async function fetchTimeline(offset: number): Promise<TimelineResponse> {
5555}
5656
5757// Initial load — useAsyncData serializes the full response across SSR → client
58- const { data : initialTimeline } = await useAsyncData (` timeline:${packageName .value } ` , () =>
59- fetchTimeline (0 ),
58+ const initialLoadError = ref (false )
59+
60+ const { data : initialTimeline } = await useAsyncData (
61+ ` timeline:${packageName .value } ` ,
62+ () => fetchTimeline (0 ),
63+ { watch: [packageName ] },
6064)
6165
6266watch (
6367 initialTimeline ,
6468 data => {
69+ initialLoadError .value = false
6570 if (data ) {
6671 timelineEntries .value = data .versions
6772 totalVersions .value = data .total
73+ } else {
74+ initialLoadError .value = true
6875 }
6976 },
7077 { immediate: true },
@@ -93,18 +100,23 @@ const fetchingVersions = shallowReactive(new Set<string>())
93100
94101const sizesLoading = computed (() => fetchingVersions .size > 0 )
95102
103+ function sizeKey(ver : string ) {
104+ return ` ${packageName .value }@${ver } `
105+ }
106+
96107async function fetchSize(ver : string ) {
97- if (sizeCache .has (ver ) || fetchingVersions .has (ver )) return
98- fetchingVersions .add (ver )
108+ const key = sizeKey (ver )
109+ if (sizeCache .has (key ) || fetchingVersions .has (key )) return
110+ fetchingVersions .add (key )
99111 try {
100112 const data = await $fetch <InstallSizeResult >(
101113 ` /api/registry/install-size/${packageName .value }/v/${ver } ` ,
102114 )
103- sizeCache .set (ver , data )
115+ sizeCache .set (key , data )
104116 } catch {
105117 // silently skip — size data is best-effort
106118 } finally {
107- fetchingVersions .delete (ver )
119+ fetchingVersions .delete (key )
108120 }
109121}
110122
@@ -151,8 +163,8 @@ const versionSubEvents = computed(() => {
151163 const events: SubEvent [] = []
152164
153165 // Size changes
154- const currentSize = sizeCache .get (current .version )
155- const previousSize = sizeCache .get (previous .version )
166+ const currentSize = sizeCache .get (sizeKey ( current .version ) )
167+ const previousSize = sizeCache .get (sizeKey ( previous .version ) )
156168 if (currentSize && previousSize ) {
157169 const sizeRatio =
158170 previousSize .totalSize > 0
@@ -386,7 +398,14 @@ useSeoMeta({
386398 </p >
387399 </div >
388400
389- <!-- Empty state -->
401+ <!-- Error state -->
402+ <div v-else-if =" initialLoadError" class =" py-20 text-center" >
403+ <p class =" text-sm text-red-600 dark:text-red-400" >
404+ {{ $t('package.timeline.load_error') }}
405+ </p >
406+ </div >
407+
408+ <!-- Loading state -->
390409 <div v-else-if =" !timelineEntries.length" class =" py-20 text-center" >
391410 <span class =" i-svg-spinners:ring-resize w-5 h-5 text-fg-subtle" />
392411 </div >
0 commit comments