diff --git a/services/bundlephobia/bundlephobia.service.js b/services/bundlephobia/bundlephobia.service.js index 1bd56c0418..b47c453f04 100644 --- a/services/bundlephobia/bundlephobia.service.js +++ b/services/bundlephobia/bundlephobia.service.js @@ -1,24 +1,41 @@ 'use strict' +const Joi = require('joi') const prettyBytes = require('pretty-bytes') -const { makeBadgeData: getBadgeData } = require('../../lib/badge-data') -const LegacyService = require('../legacy-service') +const { BaseJsonService } = require('..') +const { nonNegativeInteger } = require('../validators') -// This legacy service should be rewritten to use e.g. BaseJsonService. -// -// Tips for rewriting: -// https://github.com/badges/shields/blob/master/doc/rewriting-services.md -// -// Do not base new services on this code. -module.exports = class Bundlephobia extends LegacyService { +const schema = Joi.object({ + size: nonNegativeInteger, + gzip: nonNegativeInteger, +}).required() + +const keywords = ['node', 'bundlephobia'] + +module.exports = class Bundlephobia extends BaseJsonService { static get category() { return 'size' } + static get defaultBadgeData() { + return { + label: 'bundlephobia', + color: 'informational', + } + } + static get route() { return { base: 'bundlephobia', - pattern: '', + pattern: ':format(min|minzip)/:scope(@[^/]+)?/:packageName/:version?', + } + } + + static render({ format, size }) { + const label = format === 'min' ? 'minified size' : 'minzipped size' + return { + label, + message: prettyBytes(size), } } @@ -27,78 +44,68 @@ module.exports = class Bundlephobia extends LegacyService { { title: 'npm bundle size', pattern: ':format(min|minzip)/:packageName', - namedParams: { format: 'minzip', packageName: 'react' }, - staticPreview: { - label: 'minified size', - message: '2.57 kB', - color: 'blue', + namedParams: { + format: 'min', + packageName: 'react', }, - keywords: ['node'], + staticPreview: this.render({ format: 'min', size: 6652 }), + keywords, + }, + { + title: 'npm bundle size (scoped)', + pattern: ':format(min|minzip)/:scope/:packageName', + namedParams: { + format: 'min', + scope: '@cycle', + packageName: 'core', + }, + staticPreview: this.render({ format: 'min', size: 3562 }), + keywords, + }, + { + title: 'npm bundle size (version)', + pattern: ':format(min|minzip)/:packageName/:version', + namedParams: { + format: 'min', + packageName: 'react', + version: '15.0.0', + }, + staticPreview: this.render({ format: 'min', size: 20535 }), + keywords, + }, + { + title: 'npm bundle size (scoped version)', + pattern: ':format(min|minzip)/:scope/:packageName/:version', + namedParams: { + format: 'min', + scope: '@cycle', + packageName: 'core', + version: '7.0.0', + }, + staticPreview: this.render({ format: 'min', size: 3562 }), + keywords, }, ] } - static registerLegacyRouteHandler({ camp, cache }) { - camp.route( - /^\/bundlephobia\/(min|minzip)\/(?:@([^/]+)?\/)?([^/]+)?(?:\/([^/]+)?)?\.(svg|png|gif|jpg|json)?$/, - cache((data, match, sendBadge, request) => { - // A: /bundlephobia/(min|minzip)/:package.:format - // B: /bundlephobia/(min|minzip)/:package/:version.:format - // C: /bundlephobia/(min|minzip)/@:scope/:package.:format - // D: /bundlephobia/(min|minzip)/@:scope/:package/:version.:format - const resultType = match[1] - const scope = match[2] - const packageName = match[3] - const packageVersion = match[4] - const format = match[5] - const showMin = resultType === 'min' + async fetch({ scope, packageName, version }) { + const packageQuery = `${scope ? `${scope}/` : ''}${packageName}${ + version ? `@${version}` : '' + }` + const options = { qs: { package: packageQuery } } + return this._requestJson({ + schema, + url: 'https://bundlephobia.com/api/size', + options, + errorMessages: { + 404: 'package or version not found', + }, + }) + } - const badgeData = getBadgeData( - showMin ? 'minified size' : 'minzipped size', - data - ) - - let packageString = - typeof scope === 'string' ? `@${scope}/${packageName}` : packageName - - if (packageVersion) { - packageString += `@${packageVersion}` - } - - const requestOptions = { - url: 'https://bundlephobia.com/api/size', - qs: { - package: packageString, - }, - json: true, - } - - /** - * `ErrorCode` => `error code` - * @param {string} code - * @returns {string} - */ - const formatErrorCode = code => - code - .replace(/([A-Z])/g, ' $1') - .trim() - .toLowerCase() - - request(requestOptions, (error, response, body) => { - if (typeof body !== 'object' || body === null) { - badgeData.text[1] = 'error' - badgeData.colorscheme = 'red' - } else if (error !== null || body.error) { - badgeData.text[1] = - 'code' in body.error ? formatErrorCode(body.error.code) : 'error' - badgeData.colorscheme = 'red' - } else { - badgeData.text[1] = prettyBytes(showMin ? body.size : body.gzip) - badgeData.colorscheme = 'blue' - } - sendBadge(format, badgeData) - }) - }) - ) + async handle({ format, scope, packageName, version }) { + const json = await this.fetch({ scope, packageName, version }) + const size = format === 'min' ? json.size : json.gzip + return this.constructor.render({ format, size }) } } diff --git a/services/bundlephobia/bundlephobia.tester.js b/services/bundlephobia/bundlephobia.tester.js index 549ed30433..a4ec4d6f29 100644 --- a/services/bundlephobia/bundlephobia.tester.js +++ b/services/bundlephobia/bundlephobia.tester.js @@ -1,12 +1,7 @@ 'use strict' const { isFileSize } = require('../test-validators') -const { ServiceTester } = require('../tester') - -const t = (module.exports = new ServiceTester({ - id: 'bundlephobia', - title: 'NPM package bundle size', -})) +const t = (module.exports = require('../tester').createServiceTester()) const formats = { A: '/bundlephobia/:type/:package.:format', @@ -59,12 +54,12 @@ const data = [ { format: formats.A, get: '/min/some-no-exist.json', - expect: { label: 'minified size', message: 'package not found error' }, + expect: { label: 'bundlephobia', message: 'package or version not found' }, }, { format: formats.C, get: '/min/@some-no-exist/some-no-exist.json', - expect: { label: 'minified size', message: 'package not found error' }, + expect: { label: 'bundlephobia', message: 'package or version not found' }, }, ]