kopia lustrzana https://github.com/badgen/badgen.net
Add npm badge v2
rodzic
6ee095a7fe
commit
a62b9a06bc
|
@ -0,0 +1,160 @@
|
|||
import cheerio from 'cheerio'
|
||||
import got from '../libs/got'
|
||||
import { millify, stars, version, versionColor } from '../libs/utils'
|
||||
import {
|
||||
badgenServe,
|
||||
BadgenServeMeta as Meta,
|
||||
BadgenServeHandlers as Handlers,
|
||||
BadgenServeHandlerArgs as Args
|
||||
} from '../libs/badgen-serve'
|
||||
|
||||
// https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md
|
||||
// https://github.com/npm/registry/blob/master/docs/download-counts.md
|
||||
// https://unpkg.com/
|
||||
|
||||
export const meta: Meta = {
|
||||
title: 'npm',
|
||||
examples: {
|
||||
'/npm/v/express': 'version',
|
||||
'/npm/v/ava': 'version',
|
||||
'/npm/v/ava/next': 'version (tag)',
|
||||
'/npm/v/next/canary': 'version (tag)',
|
||||
'/npm/v/@babel/core': 'version (scoped package)',
|
||||
'/npm/v/@nestjs/core/beta': 'version (scoped & tag)',
|
||||
'/npm/dw/express': 'weekly downloads',
|
||||
'/npm/dm/express': 'monthly downloads',
|
||||
'/npm/dy/express': 'yearly downloads',
|
||||
'/npm/dt/express': 'total downloads',
|
||||
'/npm/license/lodash': 'license',
|
||||
'/npm/node/lodash': 'node version',
|
||||
'/npm/dependents/got': 'dependents'
|
||||
}
|
||||
}
|
||||
|
||||
export const handlers: Handlers = {
|
||||
'/npm/:topic/:scope<@.+>/:pkg/:tag?': handler,
|
||||
'/npm/:topic/:pkg/:tag?': handler
|
||||
}
|
||||
|
||||
export default badgenServe(handlers)
|
||||
|
||||
async function handler ({ topic, scope, pkg, tag }: Args) {
|
||||
const npmName = scope ? `${scope}/${pkg}` : pkg
|
||||
|
||||
switch (topic) {
|
||||
case 'v':
|
||||
return unpkg('version', npmName, tag)
|
||||
case 'license':
|
||||
return unpkg('license', npmName, tag)
|
||||
case 'node':
|
||||
return unpkg('node', npmName, tag)
|
||||
case 'dt':
|
||||
return download('total', npmName)
|
||||
case 'dd':
|
||||
return download('last-day', npmName) // might deprecate this
|
||||
case 'dw':
|
||||
return download('last-week', npmName)
|
||||
case 'dm':
|
||||
return download('last-month', npmName)
|
||||
case 'dy':
|
||||
return download('last-year', npmName)
|
||||
case 'dependents':
|
||||
return dependents(npmName)
|
||||
default:
|
||||
return {
|
||||
subject: 'npm',
|
||||
status: 'unknown',
|
||||
color: 'grey'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function unpkg (topic, pkg, tag = 'latest') {
|
||||
const endpoint = `https://unpkg.com/${pkg}@${tag}/package.json`
|
||||
const meta = await got(endpoint).then(res => res.body)
|
||||
|
||||
switch (topic) {
|
||||
case 'version': {
|
||||
return {
|
||||
subject: `npm${tag === 'latest' ? '' : '@' + tag}`,
|
||||
status: version(meta.version),
|
||||
color: tag === 'latest' ? versionColor(meta.version) : 'cyan'
|
||||
}
|
||||
}
|
||||
case 'license': {
|
||||
return {
|
||||
subject: 'license',
|
||||
status: meta.license || 'unknown',
|
||||
color: 'blue'
|
||||
}
|
||||
}
|
||||
case 'node': {
|
||||
return {
|
||||
subject: 'node',
|
||||
status: (meta.engines && meta.engines.node) || '*',
|
||||
color: 'green'
|
||||
}
|
||||
}
|
||||
default: {
|
||||
return {
|
||||
subject: 'npm',
|
||||
status: 'unknown',
|
||||
color: 'grey'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const download = async (period, npmName, tag = 'latest') => {
|
||||
const endpoint = ['https://api.npmjs.org/downloads']
|
||||
const isTotal = period === 'total'
|
||||
|
||||
if (isTotal) {
|
||||
endpoint.push(`range/2005-01-01:${new Date().getFullYear() + 1}-01-01`)
|
||||
} else {
|
||||
endpoint.push(`point/${period}`)
|
||||
}
|
||||
|
||||
endpoint.push(npmName)
|
||||
// endpoint.push(tag)
|
||||
|
||||
const { downloads } = await got(endpoint.join('/')).then(
|
||||
res => res.body,
|
||||
err => err.response.statusCode === 404 && { downloads: 0 }
|
||||
)
|
||||
|
||||
const count = typeof downloads === 'number'
|
||||
? downloads
|
||||
: downloads.reduce((accu, { downloads }) => {
|
||||
return accu + downloads
|
||||
}, 0)
|
||||
|
||||
const per = isTotal ? '' : period.replace('last-', '/')
|
||||
|
||||
return {
|
||||
subject: 'downloads',
|
||||
status: millify(count) + per,
|
||||
color: 'green'
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/astur/check-npm-dependents/blob/master/index.js
|
||||
async function dependents (name) {
|
||||
const html = await got(`https://www.npmjs.com/package/${name}`, {
|
||||
// @ts-ignore
|
||||
json: false
|
||||
}).then(res => res.body)
|
||||
|
||||
return {
|
||||
subject: 'dependents',
|
||||
status: parseDependents(html),
|
||||
color: 'green'
|
||||
}
|
||||
}
|
||||
|
||||
const parseDependents = html => {
|
||||
const $ = cheerio.load(html)
|
||||
const depLink = $('a[href="?activeTab=dependents"]')
|
||||
if (depLink.length !== 1) return -1
|
||||
return depLink.text().replace(/[^0-9]/g, '')
|
||||
}
|
|
@ -37,6 +37,17 @@ export function badgenServe (handlers: BadgenServeHandlers): Function {
|
|||
const params = await handlers[matchedScheme](matchedArgs)
|
||||
return serveBadge(req, res, { params, query })
|
||||
} catch (error) {
|
||||
if (error.statusCode === 404) {
|
||||
return serveBadge(req, res, {
|
||||
code: 404,
|
||||
params: {
|
||||
subject: pathname.split('/')[1],
|
||||
status: '404',
|
||||
color: 'grey'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
console.error(error)
|
||||
return serveBadge(req, res, {
|
||||
code: 500,
|
||||
|
|
|
@ -6,6 +6,7 @@ const rel = (...args) => path.resolve(__dirname, ...args)
|
|||
// sort live badge examples manually
|
||||
const liveBadgeExampleList = [
|
||||
'github',
|
||||
'npm',
|
||||
'appveyor',
|
||||
'amo',
|
||||
'apm',
|
||||
|
|
Ładowanie…
Reference in New Issue