diff --git a/services/pub/pub-downloads.service.js b/services/pub/pub-downloads.service.js new file mode 100644 index 0000000000000..eb79c0558e8ca --- /dev/null +++ b/services/pub/pub-downloads.service.js @@ -0,0 +1,53 @@ +import Joi from 'joi' +import { BaseJsonService, pathParams } from '../index.js' +import { renderDownloadsBadge } from '../downloads.js' +import { nonNegativeInteger } from '../validators.js' +import { baseDescription } from './pub-common.js' + +const description = `${baseDescription} +
This badge shows a measure of how many developers have downloaded a package monthly.
` + +const schema = Joi.object({ + downloadCount30Days: nonNegativeInteger, +}).required() + +export default class PubDownloads extends BaseJsonService { + static category = 'downloads' + + static route = { base: 'pub/dm', pattern: ':packageName' } + + static openApi = { + '/pub/dm/{packageName}': { + get: { + summary: 'Pub Monthly Downloads', + description, + parameters: pathParams({ + name: 'packageName', + example: 'analysis_options', + }), + }, + }, + } + + static defaultBadgeData = { label: 'downloads' } + + static render({ downloadCount30Days }) { + return renderDownloadsBadge({ + downloads: downloadCount30Days, + interval: 'month', + }) + } + + async fetch({ packageName }) { + return this._requestJson({ + schema, + url: `https://pub.dev/api/packages/${packageName}/score`, + }) + } + + async handle({ packageName }) { + const score = await this.fetch({ packageName }) + const downloadCount30Days = score.downloadCount30Days + return this.constructor.render({ downloadCount30Days }) + } +} diff --git a/services/pub/pub-downloads.tester.js b/services/pub/pub-downloads.tester.js new file mode 100644 index 0000000000000..6dc55a8082116 --- /dev/null +++ b/services/pub/pub-downloads.tester.js @@ -0,0 +1,28 @@ +import { isMetricOverTimePeriod } from '../test-validators.js' +import { createServiceTester } from '../tester.js' + +export const t = await createServiceTester() + +t.create('pub monthly downloads (valid)') + .get('/analysis_options.json') + .expectBadge({ + label: 'downloads', + message: isMetricOverTimePeriod, + color: 'green', + }) + +t.create('pub monthly downloads (not found)') + .get('/analysisoptions.json') + .expectBadge({ + label: 'downloads', + message: 'not found', + color: 'red', + }) + +t.create('pub monthly downloads (invalid)') + .get('/analysis-options.json') + .expectBadge({ + label: 'downloads', + message: 'invalid', + color: 'lightgrey', + })