···6868 return encodeURIComponent(name)
6969}
70707171-/** Maximum number of versions to include in the client payload */
7272-const MAX_VERSIONS = 20
7171+/** Number of recent versions to include in initial payload */
7272+const RECENT_VERSIONS_COUNT = 5
73737474/**
7575 * Transform a full Packument into a slimmed version for client-side use.
7676 * Reduces payload size by:
7777 * - Removing readme (fetched separately)
7878- * - Limiting versions to recent MAX_VERSIONS
7878+ * - Including only: 5 most recent versions + one version per dist-tag
7979 * - Stripping unnecessary fields from version objects
8080 */
8181function transformPackument(pkg: Packument): SlimPackument {
8282- // Sort versions by publish time (newest first)
8383- const sortedVersionKeys = Object.keys(pkg.versions)
8484- .filter(v => pkg.time[v]) // Only versions with timestamps
8282+ // Get versions pointed to by dist-tags
8383+ const distTagVersions = new Set(Object.values(pkg['dist-tags'] ?? {}))
8484+8585+ // Get 5 most recent versions by publish time
8686+ const recentVersions = Object.keys(pkg.versions)
8787+ .filter(v => pkg.time[v])
8588 .sort((a, b) => {
8689 const timeA = pkg.time[a]
8790 const timeB = pkg.time[b]
8891 if (!timeA || !timeB) return 0
8992 return new Date(timeB).getTime() - new Date(timeA).getTime()
9093 })
9191- .slice(0, MAX_VERSIONS)
9494+ .slice(0, RECENT_VERSIONS_COUNT)
92959393- // Always include the latest dist-tag version even if not in top MAX_VERSIONS
9494- const latestTag = pkg['dist-tags']?.latest
9595- if (latestTag && !sortedVersionKeys.includes(latestTag)) {
9696- sortedVersionKeys.push(latestTag)
9797- }
9696+ // Combine: recent versions + dist-tag versions (deduplicated)
9797+ const includedVersions = new Set([...recentVersions, ...distTagVersions])
98989999 // Build filtered versions object
100100 const filteredVersions: Record<string, PackumentVersion> = {}
101101- for (const v of sortedVersionKeys) {
101101+ for (const v of includedVersions) {
102102 const version = pkg.versions[v]
103103 if (version) {
104104 // Strip readme and scripts from each version to reduce size
···107107 }
108108 }
109109110110- // Build filtered time object (only for included versions)
110110+ // Build filtered time object (only for included versions + metadata)
111111 const filteredTime: Record<string, string> = {}
112112 if (pkg.time.modified) filteredTime.modified = pkg.time.modified
113113 if (pkg.time.created) filteredTime.created = pkg.time.created
114114- for (const v of sortedVersionKeys) {
114114+ for (const v of includedVersions) {
115115 if (pkg.time[v]) filteredTime[v] = pkg.time[v]
116116 }
117117···138138139139 return useLazyAsyncData(
140140 () => `package:${toValue(name)}`,
141141- () => registry.fetchPackage(toValue(name)),
142142- { transform: transformPackument },
141141+ () => registry.fetchPackage(toValue(name)).then(r => transformPackument(r)),
143142 )
144143}
145144