From b76d7b978f0a26a0d7276acba66dd3b5d3f50046 Mon Sep 17 00:00:00 2001 From: Dheepak Krishnamurthy Date: Sat, 20 Feb 2021 23:08:40 -0700 Subject: [PATCH 1/2] Add homebrew downloads badge --- .../homebrew/homebrew-downloads.service.js | 82 +++++++++++++++++++ .../homebrew/homebrew-downloads.tester.js | 28 +++++++ ...service.js => homebrew-version.service.js} | 4 +- ...w.tester.js => homebrew-version.tester.js} | 0 services/test-validators.js | 6 +- 5 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 services/homebrew/homebrew-downloads.service.js create mode 100644 services/homebrew/homebrew-downloads.tester.js rename services/homebrew/{homebrew.service.js => homebrew-version.service.js} (89%) rename services/homebrew/{homebrew.tester.js => homebrew-version.tester.js} (100%) diff --git a/services/homebrew/homebrew-downloads.service.js b/services/homebrew/homebrew-downloads.service.js new file mode 100644 index 0000000000000..73b6a77d82798 --- /dev/null +++ b/services/homebrew/homebrew-downloads.service.js @@ -0,0 +1,82 @@ +'use strict' + +const Joi = require('joi') +const { downloadCount } = require('../color-formatters') +const { metric } = require('../text-formatters') +const { BaseJsonService } = require('..') +const { nonNegativeInteger } = require('../validators') + +function getSchema({ formula }) { + return Joi.object({ + analytics: Joi.object({ + install: Joi.object({ + '30d': Joi.object({ [formula]: nonNegativeInteger }).required(), + '90d': Joi.object({ [formula]: nonNegativeInteger }).required(), + '365d': Joi.object({ [formula]: nonNegativeInteger }).required(), + }).required(), + install_on_request: Joi.object({ + '30d': Joi.object({ [formula]: nonNegativeInteger }).required(), + '90d': Joi.object({ [formula]: nonNegativeInteger }).required(), + '365d': Joi.object({ [formula]: nonNegativeInteger }).required(), + }).required(), + }).required(), + }).required() +} + +const periodMap = { + dm: { + api_field: '30d', + suffix: '/month', + }, + dq: { + api_field: '90d', + suffix: '/quarter', + }, + dy: { + api_field: '365d', + suffix: '/year', + }, +} + +module.exports = class HomebrewDownloads extends BaseJsonService { + static category = 'downloads' + + static route = { + base: 'homebrew', + pattern: 'installs/:interval(dm|dq|dy)/:formula', + } + + static examples = [ + { + title: 'homebrew downloads', + namedParams: { interval: 'dm', formula: 'cake' }, + staticPreview: this.render({ interval: 'dm', downloads: 93 }), + }, + ] + + static defaultBadgeData = { label: 'downloads' } + + static render({ interval, downloads }) { + return { + message: `${metric(downloads)}${periodMap[interval].suffix}`, + color: downloadCount(downloads), + } + } + + async fetch({ formula }) { + const schema = getSchema({ formula }) + return this._requestJson({ + schema, + url: `https://formulae.brew.sh/api/formula/${formula}.json`, + errorMessages: { 404: 'formula not found' }, + }) + } + + async handle({ interval, formula }) { + const data = await this.fetch({ formula }) + return this.constructor.render({ + interval, + downloads: data.analytics.install[periodMap[interval].api_field][formula], + }) + } +} diff --git a/services/homebrew/homebrew-downloads.tester.js b/services/homebrew/homebrew-downloads.tester.js new file mode 100644 index 0000000000000..5f612ace9f6ab --- /dev/null +++ b/services/homebrew/homebrew-downloads.tester.js @@ -0,0 +1,28 @@ +'use strict' + +const t = (module.exports = require('../tester').createServiceTester()) +const { isMetricOverTimePeriod } = require('../test-validators') + +t.create('daily downloads (valid)') + .get('/installs/dm/cake.json') + .expectBadge({ label: 'downloads', message: isMetricOverTimePeriod }) + +t.create('yearly downloads (valid)') + .get('/installs/dq/cake.json') + .expectBadge({ label: 'downloads', message: isMetricOverTimePeriod }) + +t.create('yearly downloads (valid)') + .get('/installs/dy/cake.json') + .expectBadge({ label: 'downloads', message: isMetricOverTimePeriod }) + +t.create('daily downloads (not found)') + .get('/installs/dm/not-a-package.json') + .expectBadge({ label: 'downloads', message: 'formula not found' }) + +t.create('yearly downloads (not found)') + .get('/installs/dq/not-a-package.json') + .expectBadge({ label: 'downloads', message: 'formula not found' }) + +t.create('yearly downloads (not found)') + .get('/installs/dy/not-a-package.json') + .expectBadge({ label: 'downloads', message: 'formula not found' }) diff --git a/services/homebrew/homebrew.service.js b/services/homebrew/homebrew-version.service.js similarity index 89% rename from services/homebrew/homebrew.service.js rename to services/homebrew/homebrew-version.service.js index 2a6a5b4390970..02d0f8f925205 100644 --- a/services/homebrew/homebrew.service.js +++ b/services/homebrew/homebrew-version.service.js @@ -10,14 +10,14 @@ const schema = Joi.object({ }).required(), }).required() -module.exports = class Homebrew extends BaseJsonService { +module.exports = class HomebrewVersion extends BaseJsonService { static category = 'version' static route = { base: 'homebrew/v', pattern: ':formula' } static examples = [ { - title: 'homebrew', + title: 'homebrew version', namedParams: { formula: 'cake' }, staticPreview: renderVersionBadge({ version: 'v0.32.0' }), }, diff --git a/services/homebrew/homebrew.tester.js b/services/homebrew/homebrew-version.tester.js similarity index 100% rename from services/homebrew/homebrew.tester.js rename to services/homebrew/homebrew-version.tester.js diff --git a/services/test-validators.js b/services/test-validators.js index 9a57d79eb5751..c6804831c2c24 100644 --- a/services/test-validators.js +++ b/services/test-validators.js @@ -73,10 +73,12 @@ const isMetricOverMetric = withRegex( ) const isMetricOverTimePeriod = withRegex( - /^([1-9][0-9]*[kMGTPEZY]?|[1-9]\.[1-9][kMGTPEZY])\/(year|month|four weeks|week|day)$/ + /^([1-9][0-9]*[kMGTPEZY]?|[1-9]\.[1-9][kMGTPEZY])\/(year|month|four weeks|quarter|week|day)$/ ) -const isZeroOverTimePeriod = withRegex(/^0\/(year|month|four weeks|week|day)$/) +const isZeroOverTimePeriod = withRegex( + /^0\/(year|month|four weeks|quarter|week|day)$/ +) const isIntegerPercentage = withRegex(/^[1-9][0-9]?%|^100%|^0%$/) const isDecimalPercentage = withRegex(/^[0-9]+\.[0-9]*%$/) From 9028a67c0264d914c4fd310014bdb7a28c77dd2c Mon Sep 17 00:00:00 2001 From: Dheepak Krishnamurthy Date: Mon, 22 Feb 2021 11:50:03 -0700 Subject: [PATCH 2/2] Remove install_on_request --- services/homebrew/homebrew-downloads.service.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/services/homebrew/homebrew-downloads.service.js b/services/homebrew/homebrew-downloads.service.js index 73b6a77d82798..201b5c7bf523e 100644 --- a/services/homebrew/homebrew-downloads.service.js +++ b/services/homebrew/homebrew-downloads.service.js @@ -14,11 +14,6 @@ function getSchema({ formula }) { '90d': Joi.object({ [formula]: nonNegativeInteger }).required(), '365d': Joi.object({ [formula]: nonNegativeInteger }).required(), }).required(), - install_on_request: Joi.object({ - '30d': Joi.object({ [formula]: nonNegativeInteger }).required(), - '90d': Joi.object({ [formula]: nonNegativeInteger }).required(), - '365d': Joi.object({ [formula]: nonNegativeInteger }).required(), - }).required(), }).required(), }).required() }