diff --git a/services/cran/cran.service.js b/services/cran/cran.service.js index 589ae4a562..c7325af9be 100644 --- a/services/cran/cran.service.js +++ b/services/cran/cran.service.js @@ -1,14 +1,26 @@ 'use strict' -const LegacyService = require('../legacy-service') -const { - makeBadgeData: getBadgeData, - makeLabel: getLabel, -} = require('../../lib/badge-data') -const { addv: versionText } = require('../../lib/text-formatters') -const { version: versionColor } = require('../../lib/color-formatters') +const Joi = require('joi') +const BaseJsonService = require('../base-json') +const { renderVersionBadge } = require('../../lib/version') -class CranLicense extends LegacyService { +const schema = Joi.object({ + License: Joi.string().required(), + Version: Joi.string().required(), +}).required() + +class BaseCranService extends BaseJsonService { + async fetch({ packageName }) { + const url = `http://crandb.r-pkg.org/${packageName}` + return this._requestJson({ schema, url }) + } + + static get defaultBadgeData() { + return { label: 'cran' } + } +} + +class CranLicense extends BaseCranService { static get category() { return 'license' } @@ -25,20 +37,27 @@ class CranLicense extends LegacyService { { title: 'CRAN/METACRAN', namedParams: { packageName: 'devtools' }, - staticPreview: { - label: 'license', - message: 'GPL (>= 2)', - color: 'blue', - }, + staticPreview: this.render({ license: 'GPL (>= 2)' }), keywords: ['R'], }, ] } - static registerLegacyRouteHandler() {} + static render({ license }) { + return { + label: 'license', + message: license, + color: 'blue', + } + } + + async handle({ packageName }) { + const data = await this.fetch({ packageName }) + return this.constructor.render({ license: data['License'] }) + } } -class CranVersion extends LegacyService { +class CranVersion extends BaseCranService { static get category() { return 'version' } @@ -46,6 +65,7 @@ class CranVersion extends LegacyService { static get route() { return { base: 'cran/v', + pattern: ':packageName', } } @@ -53,69 +73,21 @@ class CranVersion extends LegacyService { return [ { title: 'CRAN/METACRAN', - previewUrl: 'devtools', + namedParams: { packageName: 'devtools' }, + staticPreview: this.render({ version: '2.0.1' }), keywords: ['R'], }, ] } - static registerLegacyRouteHandler() {} -} + static render({ version }) { + return renderVersionBadge({ version }) + } -class Cran extends LegacyService { - static registerLegacyRouteHandler({ camp, cache }) { - camp.route( - /^\/cran\/([vl])\/([^/]+)\.(svg|png|gif|jpg|json)$/, - cache((queryParams, match, sendBadge, request) => { - const info = match[1] // either `v` or `l` - const pkg = match[2] // eg, devtools - const format = match[3] - const url = `http://crandb.r-pkg.org/${pkg}` - const badgeData = getBadgeData('cran', queryParams) - request(url, (err, res, buffer) => { - if (err != null) { - badgeData.text[1] = 'inaccessible' - sendBadge(format, badgeData) - return - } - if (res.statusCode === 404) { - badgeData.text[1] = 'not found' - sendBadge(format, badgeData) - return - } - try { - const data = JSON.parse(buffer) - - if (info === 'v') { - const version = data.Version - badgeData.text[1] = versionText(version) - badgeData.colorscheme = versionColor(version) - sendBadge(format, badgeData) - } else if (info === 'l') { - badgeData.text[0] = getLabel('license', queryParams) - const license = data.License - if (license) { - badgeData.text[1] = license - badgeData.colorscheme = 'blue' - } else { - badgeData.text[1] = 'unknown' - } - sendBadge(format, badgeData) - } else { - throw Error('Unreachable due to regex') - } - } catch (e) { - badgeData.text[1] = 'invalid' - sendBadge(format, badgeData) - } - }) - }) - ) + async handle({ packageName }) { + const data = await this.fetch({ packageName }) + return this.constructor.render({ version: data['Version'] }) } } -module.exports = { - CranLicense, - CranVersion, - Cran, -} +module.exports = { CranLicense, CranVersion } diff --git a/services/cran/cran.tester.js b/services/cran/cran.tester.js index 57d3979fde..e33b770e85 100644 --- a/services/cran/cran.tester.js +++ b/services/cran/cran.tester.js @@ -9,7 +9,7 @@ const t = (module.exports = new ServiceTester({ title: 'CRAN/METACRAN', })) -t.create('version') +t.create('version (valid)') .get('/v/devtools.json') .expectJSONTypes( Joi.object().keys({ @@ -18,38 +18,14 @@ t.create('version') }) ) -t.create('specified license') +t.create('version (not found)') + .get('/v/some-bogus-package.json') + .expectJSON({ name: 'cran', value: 'not found' }) + +t.create('license (valid)') .get('/l/devtools.json') .expectJSON({ name: 'license', value: 'GPL (>= 2)' }) -t.create('unknown package') +t.create('license (not found)') .get('/l/some-bogus-package.json') .expectJSON({ name: 'cran', value: 'not found' }) - -t.create('unknown info') - .get('/z/devtools.json') - .expectStatus(404) - .expectJSON({ name: '404', value: 'badge not found' }) - -t.create('malformed response') - .get('/v/foobar.json') - .intercept(nock => - nock('http://crandb.r-pkg.org') - .get('/foobar') - .reply(200) - ) // JSON without Version. - .expectJSON({ name: 'cran', value: 'invalid' }) - -t.create('connection error') - .get('/v/foobar.json') - .networkOff() - .expectJSON({ name: 'cran', value: 'inaccessible' }) - -t.create('unspecified license') - .get('/l/foobar.json') - .intercept(nock => - nock('http://crandb.r-pkg.org') - .get('/foobar') - .reply(200, {}) - ) // JSON without License. - .expectJSON({ name: 'license', value: 'unknown' })