Skip to content

Commit 3a58861

Browse files
committed
feat: update
1 parent 95240a9 commit 3a58861

File tree

3 files changed

+68
-49
lines changed

3 files changed

+68
-49
lines changed

app/pages/package/[[org]]/[name]/versions.vue

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ interface NpmWebsiteVersionDownload {
2323
}
2424
2525
interface NpmWebsiteVersionsResponse {
26-
versions: NpmWebsiteVersionDownload[]
26+
packages: Array<{
27+
packageName: string
28+
versions: NpmWebsiteVersionDownload[]
29+
}>
2730
}
2831
2932
/** Number of flat items (headers + version rows) to render statically during SSR */
@@ -59,23 +62,30 @@ const versionStrings = computed(() => versionSummary.value?.versions ?? [])
5962
const versionTimes = computed(() => versionSummary.value?.time ?? {})
6063
6164
const { data: npmWebsiteVersions } = useLazyFetch<NpmWebsiteVersionsResponse>(
62-
() => `/api/registry/npmjs-versions/${encodeURIComponent(packageName.value)}`,
65+
() => '/api/registry/downloads/versions',
6366
{
64-
key: () => `npmjs-versions:${packageName.value}`,
67+
key: () => `downloads-versions:${packageName.value}`,
68+
query: computed(() => ({ packages: packageName.value })),
6569
deep: false,
66-
default: () => ({ versions: [] }),
70+
default: () => ({ packages: [] }),
6771
getCachedData(key, nuxtApp) {
6872
return nuxtApp.static.data[key] ?? nuxtApp.payload.data[key]
6973
},
7074
},
7175
)
7276
77+
const packageVersions = computed(() => {
78+
return (
79+
npmWebsiteVersions.value?.packages.find(pkg => pkg.packageName === packageName.value)?.versions ?? []
80+
)
81+
})
82+
7383
const numberFormatter = useNumberFormatter()
7484
const { t } = useI18n()
7585
const versionDownloadsMap = computed(
7686
() =>
7787
new Map(
78-
(npmWebsiteVersions.value?.versions ?? []).map(({ version, downloads }) => [
88+
packageVersions.value.map(({ version, downloads }) => [
7989
version,
8090
downloads,
8191
]),

server/api/registry/downloads/[...slug].get.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as v from 'valibot'
22
import { hash } from 'ohash'
3+
import { fetchNpmVersionDownloadsFromApi } from '#server/utils/npm-website-versions'
34

45
/**
56
* Raw response from npm downloads API
@@ -15,6 +16,7 @@ interface NpmVersionDownloadsResponse {
1516
*/
1617
const QuerySchema = v.object({
1718
mode: v.optional(v.picklist(['major', 'minor'] as const), 'major'),
19+
packages: v.optional(v.union([v.string(), v.array(v.string())])),
1820
filterThreshold: v.optional(
1921
v.pipe(
2022
v.string(),
@@ -25,10 +27,19 @@ const QuerySchema = v.object({
2527
filterOldVersions: v.optional(v.picklist(['true', 'false'] as const), 'false'),
2628
})
2729

30+
function normalizePackages(packages: string | string[] | undefined): string[] {
31+
if (!packages) return []
32+
33+
const values = Array.isArray(packages) ? packages : [packages]
34+
return [...new Set(values.flatMap(value => value.split(',').map(pkg => pkg.trim())).filter(Boolean))]
35+
}
36+
2837
/**
2938
* GET /api/registry/downloads/:name/versions or /api/registry/downloads/@scope/name/versions
39+
* GET /api/registry/downloads/versions?packages=pkg-a,pkg-b
3040
*
31-
* Fetch per-version download statistics and group by major or minor version.
41+
* Fetch per-version download statistics and group by major or minor version,
42+
* or fetch raw per-version download lists for one or more packages.
3243
* Data is cached for 1 hour with stale-while-revalidate.
3344
*
3445
* Query parameters:
@@ -50,6 +61,47 @@ export default defineCachedEventHandler(
5061
})
5162
}
5263

64+
try {
65+
const query = getQuery(event)
66+
const parsed = v.parse(QuerySchema, query)
67+
// Supports: /downloads/versions?packages=a,b and repeated ?packages=a&packages=b
68+
if (pkgParamSegments.length === 1) {
69+
const packageNames = normalizePackages(parsed.packages)
70+
71+
if (packageNames.length === 0) {
72+
throw createError({
73+
statusCode: 400,
74+
message: 'At least one package is required via query `packages`',
75+
})
76+
}
77+
78+
try {
79+
const packages = await Promise.all(
80+
packageNames.map(async packageName => ({
81+
packageName,
82+
versions: await fetchNpmVersionDownloadsFromApi(packageName),
83+
})),
84+
)
85+
86+
return {
87+
packages,
88+
timestamp: new Date().toISOString(),
89+
}
90+
} catch (error: unknown) {
91+
handleApiError(error, {
92+
statusCode: 502,
93+
message: 'Failed to fetch version download data from npm API',
94+
})
95+
}
96+
}
97+
} catch (error: unknown) {
98+
handleApiError(error, {
99+
statusCode: 502,
100+
message: 'Failed to fetch version download data from npm API',
101+
})
102+
}
103+
104+
53105
const segments = pkgParamSegments.slice(0, -1)
54106

55107
const { rawPackageName } = parsePackageParams(segments)

server/api/registry/npmjs-versions/[...pkg].get.ts

Lines changed: 0 additions & 43 deletions
This file was deleted.

0 commit comments

Comments
 (0)