diff --git a/services/pub/pub-popularity.service.js b/services/pub/pub-popularity.service.js new file mode 100644 index 0000000000000..f0ed56e0cf75c --- /dev/null +++ b/services/pub/pub-popularity.service.js @@ -0,0 +1,53 @@ +import Joi from 'joi' +import { floorCount } from '../color-formatters.js' +import { BaseJsonService } from '../index.js' + +const documentation = `

A measure of how many developers use a package, providing insight into what other developers are using.

` + +const keywords = ['dart', 'flutter'] + +const schema = Joi.object({ + popularityScore: Joi.number().min(0).max(1).required(), +}).required() + +const title = 'Pub Popularity' + +export default class PubPopularity extends BaseJsonService { + static category = 'rating' + + static route = { base: 'pub/popularity', pattern: ':packageName' } + + static examples = [ + { + title, + keywords, + documentation, + namedParams: { packageName: 'analysis_options' }, + staticPreview: this.render({ popularityScore: 0.9 }), + }, + ] + + static defaultBadgeData = { label: 'popularity' } + + static render({ popularityScore }) { + const roundedScore = Math.round(popularityScore * 100) + return { + label: 'popularity', + message: `${roundedScore}%`, + color: floorCount(roundedScore, 40, 60, 80), + } + } + + 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 popularityScore = score.popularityScore + return this.constructor.render({ popularityScore }) + } +} diff --git a/services/pub/pub-popularity.tester.js b/services/pub/pub-popularity.tester.js new file mode 100644 index 0000000000000..ea9953e03672d --- /dev/null +++ b/services/pub/pub-popularity.tester.js @@ -0,0 +1,23 @@ +import { isIntegerPercentage } from '../test-validators.js' +import { createServiceTester } from '../tester.js' + +export const t = await createServiceTester() + +t.create('pub popularity (valid)').get('/analysis_options.json').expectBadge({ + label: 'popularity', + message: isIntegerPercentage, +}) + +t.create('pub popularity (not found)') + .get('/analysisoptions.json') + .expectBadge({ + label: 'popularity', + message: 'not found', + color: 'red', + }) + +t.create('pub popularity (invalid)').get('/analysis-options.json').expectBadge({ + label: 'popularity', + message: 'invalid', + color: 'lightgrey', +})