Skip to content

Commit d9d4648

Browse files
committed
feat: add more types
1 parent 5f46f9d commit d9d4648

File tree

1 file changed

+52
-6
lines changed

1 file changed

+52
-6
lines changed

server/api/registry/badge/[type]/[...pkg].get.ts

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { handleApiError } from '#server/utils/error-handler'
99
const NPM_DOWNLOADS_API = 'https://api.npmjs.org/downloads/point'
1010
const OSV_QUERY_API = 'https://api.osv.dev/v1/query'
1111
const BUNDLEPHOBIA_API = 'https://bundlephobia.com/api/size'
12+
const NPMS_API = 'https://api.npms.io/v2/package'
1213

1314
const QUERY_SCHEMA = v.object({
1415
color: v.optional(v.string()),
@@ -63,7 +64,7 @@ function getLatestVersion(pkgData: globalThis.Packument): string | undefined {
6364

6465
async function fetchDownloads(
6566
packageName: string,
66-
period: 'last-month' | 'last-week',
67+
period: 'last-day' | 'last-week' | 'last-month' | 'last-year',
6768
): Promise<number> {
6869
try {
6970
const response = await fetch(`${NPM_DOWNLOADS_API}/${period}/${packageName}`)
@@ -74,6 +75,16 @@ async function fetchDownloads(
7475
}
7576
}
7677

78+
async function fetchNpmsScore(packageName: string) {
79+
try {
80+
const response = await fetch(`${NPMS_API}/${encodeURIComponent(packageName)}`)
81+
const data = await response.json()
82+
return data.score
83+
} catch {
84+
return null
85+
}
86+
}
87+
7788
async function fetchVulnerabilities(packageName: string, version: string): Promise<number> {
7889
try {
7990
const response = await fetch(OSV_QUERY_API, {
@@ -116,15 +127,11 @@ const badgeStrategies = {
116127
'size': async (pkgData: globalThis.Packument) => {
117128
const latest = getLatestVersion(pkgData)
118129
const versionData = latest ? pkgData.versions?.[latest] : undefined
119-
120-
// Fallback to unpacked size if bundlephobia fails or latest is missing
121130
let bytes = versionData?.dist?.unpackedSize ?? 0
122-
123131
if (latest) {
124132
const installSize = await fetchInstallSize(pkgData.name, latest)
125133
if (installSize !== null) bytes = installSize
126134
}
127-
128135
return { label: 'install size', value: formatBytes(bytes), color: COLORS.purple }
129136
},
130137

@@ -133,11 +140,26 @@ const badgeStrategies = {
133140
return { label: 'downloads/mo', value: formatNumber(count), color: COLORS.orange }
134141
},
135142

143+
'downloads-day': async (pkgData: globalThis.Packument) => {
144+
const count = await fetchDownloads(pkgData.name, 'last-day')
145+
return { label: 'downloads/day', value: formatNumber(count), color: COLORS.orange }
146+
},
147+
136148
'downloads-week': async (pkgData: globalThis.Packument) => {
137149
const count = await fetchDownloads(pkgData.name, 'last-week')
138150
return { label: 'downloads/wk', value: formatNumber(count), color: COLORS.orange }
139151
},
140152

153+
'downloads-month': async (pkgData: globalThis.Packument) => {
154+
const count = await fetchDownloads(pkgData.name, 'last-month')
155+
return { label: 'downloads/mo', value: formatNumber(count), color: COLORS.orange }
156+
},
157+
158+
'downloads-year': async (pkgData: globalThis.Packument) => {
159+
const count = await fetchDownloads(pkgData.name, 'last-year')
160+
return { label: 'downloads/yr', value: formatNumber(count), color: COLORS.orange }
161+
},
162+
141163
'vulnerabilities': async (pkgData: globalThis.Packument) => {
142164
const latest = getLatestVersion(pkgData)
143165
const count = latest ? await fetchVulnerabilities(pkgData.name, latest) : 0
@@ -192,9 +214,33 @@ const badgeStrategies = {
192214
color: isDeprecated ? COLORS.red : COLORS.green,
193215
}
194216
},
217+
218+
'quality': async (pkgData: globalThis.Packument) => {
219+
const score = await fetchNpmsScore(pkgData.name)
220+
const value = score ? `${Math.round(score.detail.quality * 100)}%` : 'unknown'
221+
return { label: 'quality', value, color: COLORS.purple }
222+
},
223+
224+
'popularity': async (pkgData: globalThis.Packument) => {
225+
const score = await fetchNpmsScore(pkgData.name)
226+
const value = score ? `${Math.round(score.detail.popularity * 100)}%` : 'unknown'
227+
return { label: 'popularity', value, color: COLORS.cyan }
228+
},
229+
230+
'maintenance': async (pkgData: globalThis.Packument) => {
231+
const score = await fetchNpmsScore(pkgData.name)
232+
const value = score ? `${Math.round(score.detail.maintenance * 100)}%` : 'unknown'
233+
return { label: 'maintenance', value, color: COLORS.yellow }
234+
},
235+
236+
'score': async (pkgData: globalThis.Packument) => {
237+
const score = await fetchNpmsScore(pkgData.name)
238+
const value = score ? `${Math.round(score.final * 100)}%` : 'unknown'
239+
return { label: 'score', value, color: COLORS.blue }
240+
},
195241
}
196242

197-
const BadgeTypeSchema = v.picklist(Object.keys(badgeStrategies))
243+
const BadgeTypeSchema = v.picklist(Object.keys(badgeStrategies) as [string, ...string[]])
198244

199245
export default defineCachedEventHandler(
200246
async event => {

0 commit comments

Comments
 (0)