From 1a98b6bc31c94e3114086062620e08bef778eb24 Mon Sep 17 00:00:00 2001 From: chris48s Date: Mon, 23 Dec 2019 20:47:35 +0000 Subject: [PATCH] Convert vpre routes to include_prereleases param in [bower chocolatey clojars packagist powershellgallery pub resharper] (#4436) * Convert vpre routes to include_prereleases param * add .expectRedirect() helper * test redirects on SVG endpoint --- .../service-test-runner/icedfrisby-shields.js | 4 + services/bower/bower-version.service.js | 49 ++++++++---- services/bower/bower-version.tester.js | 17 +++- services/chocolatey/chocolatey.tester.js | 8 +- services/clojars/clojars-base.js | 29 +------ services/clojars/clojars-release.service.js | 20 ----- services/clojars/clojars-release.tester.js | 14 ---- services/clojars/clojars-snapshot.service.js | 17 ---- services/clojars/clojars-snapshot.tester.js | 14 ---- services/clojars/clojars-version.service.js | 79 +++++++++++++++++++ services/clojars/clojars-version.tester.js | 30 +++++++ services/nuget/nuget-v2-service-family.js | 37 ++++++--- .../packagist/packagist-version.service.js | 39 ++++++--- .../packagist/packagist-version.tester.js | 21 ++++- .../powershellgallery.service.js | 2 + .../powershellgallery.tester.js | 8 +- services/pub/pub.service.js | 39 ++++++--- services/pub/pub.tester.js | 13 ++- services/resharper/resharper.tester.js | 8 +- 19 files changed, 294 insertions(+), 154 deletions(-) delete mode 100644 services/clojars/clojars-release.service.js delete mode 100644 services/clojars/clojars-release.tester.js delete mode 100644 services/clojars/clojars-snapshot.service.js delete mode 100644 services/clojars/clojars-snapshot.tester.js create mode 100644 services/clojars/clojars-version.service.js create mode 100644 services/clojars/clojars-version.tester.js diff --git a/core/service-test-runner/icedfrisby-shields.js b/core/service-test-runner/icedfrisby-shields.js index ec1748dafe..4b1070f90a 100644 --- a/core/service-test-runner/icedfrisby-shields.js +++ b/core/service-test-runner/icedfrisby-shields.js @@ -51,6 +51,10 @@ const factory = superclass => }) } + expectRedirect(location) { + return this.expectStatus(301).expectHeader('Location', location) + } + static _expectField(json, name, expected) { if (typeof expected === 'undefined') return if (typeof expected === 'string' || typeof expected === 'number') { diff --git a/services/bower/bower-version.service.js b/services/bower/bower-version.service.js index 80c46e2c7a..c1f903bf0f 100644 --- a/services/bower/bower-version.service.js +++ b/services/bower/bower-version.service.js @@ -1,33 +1,38 @@ 'use strict' +const Joi = require('@hapi/joi') const { renderVersionBadge } = require('../version') const BaseBowerService = require('./bower-base') -const { InvalidResponse } = require('..') +const { InvalidResponse, redirector } = require('..') -module.exports = class BowerVersion extends BaseBowerService { +const queryParamSchema = Joi.object({ + include_prereleases: Joi.equal(''), +}).required() + +class BowerVersion extends BaseBowerService { static get category() { return 'version' } static get route() { return { - base: 'bower', - pattern: ':vtype(v|vpre)/:packageName', + base: 'bower/v', + pattern: ':packageName', + queryParamSchema, } } static get examples() { return [ { - title: 'Bower', + title: 'Bower Version', namedParams: { packageName: 'bootstrap' }, - pattern: 'v/:packageName', staticPreview: renderVersionBadge({ version: '4.2.1' }), }, { - title: 'Bower Pre Release', + title: 'Bower Version (including pre-releases)', namedParams: { packageName: 'bootstrap' }, - pattern: 'vpre/:packageName', + queryParams: { include_prereleases: null }, staticPreview: renderVersionBadge({ version: '4.2.1' }), }, ] @@ -37,18 +42,34 @@ module.exports = class BowerVersion extends BaseBowerService { return { label: 'bower' } } - async handle({ vtype, packageName }) { + async handle({ packageName }, queryParams) { const data = await this.fetch({ packageName }) + const includePrereleases = queryParams.include_prereleases !== undefined - if (vtype === 'v') { - if (data.latest_stable_release) { - return renderVersionBadge({ version: data.latest_stable_release.name }) - } - } else { + if (includePrereleases) { if (data.latest_release_number) { return renderVersionBadge({ version: data.latest_release_number }) } + } else { + if (data.latest_stable_release) { + return renderVersionBadge({ version: data.latest_stable_release.name }) + } } throw new InvalidResponse({ prettyMessage: 'no releases' }) } } + +const BowerVersionRedirect = redirector({ + category: 'version', + route: { + base: 'bower/vpre', + pattern: ':packageName', + }, + transformPath: ({ packageName }) => `/bower/v/${packageName}`, + transformQueryParams: params => ({ + include_prereleases: null, + }), + dateAdded: new Date('2019-12-15'), +}) + +module.exports = { BowerVersion, BowerVersionRedirect } diff --git a/services/bower/bower-version.tester.js b/services/bower/bower-version.tester.js index 1d2af8795b..3ec6e65fcd 100644 --- a/services/bower/bower-version.tester.js +++ b/services/bower/bower-version.tester.js @@ -2,7 +2,12 @@ const Joi = require('@hapi/joi') const { isVPlusDottedVersionAtLeastOne } = require('../test-validators') -const t = (module.exports = require('../tester').createServiceTester()) +const { ServiceTester } = require('../tester') +const t = (module.exports = new ServiceTester({ + id: 'BowerVersion', + title: 'Bower Version', + pathPrefix: '/bower', +})) const isBowerPrereleaseVersion = Joi.string().regex( /^v\d+(\.\d+)?(\.\d+)?(-?[.\w\d])+?$/ @@ -18,7 +23,7 @@ t.create('version') t.create('pre version') // e.g. bower|v0.2.5-alpha-rc-pre .timeout(10000) - .get('/vpre/bootstrap.json') + .get('/v/bootstrap.json?include_prereleases') .expectBadge({ label: 'bower', message: isBowerPrereleaseVersion, @@ -31,7 +36,7 @@ t.create('Version for Invalid Package') t.create('Pre Version for Invalid Package') .timeout(10000) - .get('/vpre/it-is-a-invalid-package-should-error.json') + .get('/v/it-is-a-invalid-package-should-error.json?include_prereleases') .expectBadge({ label: 'bower', message: 'package not found' }) t.create('Version label should be `no releases` if no stable version') @@ -44,10 +49,14 @@ t.create('Version label should be `no releases` if no stable version') .expectBadge({ label: 'bower', message: 'no releases' }) t.create('Version label should be `no releases` if no pre-release') - .get('/vpre/bootstrap.json') + .get('/v/bootstrap.json?include_prereleases') .intercept(nock => nock('https://libraries.io') .get('/api/bower/bootstrap') .reply(200, { normalized_licenses: [], latest_release_number: null }) ) .expectBadge({ label: 'bower', message: 'no releases' }) + +t.create('Version (legacy redirect: vpre)') + .get('/vpre/bootstrap.svg', { followRedirect: false }) + .expectRedirect('/bower/v/bootstrap.svg?include_prereleases') diff --git a/services/chocolatey/chocolatey.tester.js b/services/chocolatey/chocolatey.tester.js index 7c8ab077e3..fe64bcfbd1 100644 --- a/services/chocolatey/chocolatey.tester.js +++ b/services/chocolatey/chocolatey.tester.js @@ -41,12 +41,16 @@ t.create('version (not found)') // version (pre) t.create('version (pre) (valid)') - .get('/vpre/scriptcs.json') + .get('/v/scriptcs.json?include_prereleases') .expectBadge({ label: 'chocolatey', message: isVPlusDottedVersionNClausesWithOptionalSuffix, }) t.create('version (pre) (not found)') - .get('/vpre/not-a-real-package.json') + .get('/v/not-a-real-package.json?include_prereleases') .expectBadge({ label: 'chocolatey', message: 'not found' }) + +t.create('version (legacy redirect: vpre)') + .get('/vpre/scriptcs.svg', { followRedirect: false }) + .expectRedirect('/chocolatey/v/scriptcs.svg?include_prereleases') diff --git a/services/clojars/clojars-base.js b/services/clojars/clojars-base.js index f9e042499f..75d79b830b 100644 --- a/services/clojars/clojars-base.js +++ b/services/clojars/clojars-base.js @@ -1,7 +1,6 @@ 'use strict' const Joi = require('@hapi/joi') -const { version: versionColor } = require('../color-formatters') const { nonNegativeInteger } = require('../validators') const { BaseJsonService } = require('..') @@ -22,30 +21,4 @@ class BaseClojarsService extends BaseJsonService { } } -class BaseClojarsVersionService extends BaseClojarsService { - static get category() { - return 'version' - } - - static get examples() { - return [ - { - namedParams: { clojar: 'prismic' }, - staticPreview: this.render({ clojar: 'clojar', version: '1.2' }), - }, - ] - } - - static get defaultBadgeData() { - return { label: 'clojars' } - } - - static render({ clojar, version }) { - return { - message: `[${clojar} "${version}"]`, - color: versionColor(version), - } - } -} - -module.exports = { BaseClojarsService, BaseClojarsVersionService } +module.exports = { BaseClojarsService } diff --git a/services/clojars/clojars-release.service.js b/services/clojars/clojars-release.service.js deleted file mode 100644 index c567ffb5de..0000000000 --- a/services/clojars/clojars-release.service.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict' - -const { BaseClojarsVersionService } = require('./clojars-base') - -module.exports = class ClojarsVersionRelease extends BaseClojarsVersionService { - static get route() { - return { - base: 'clojars/v', - pattern: ':clojar+', - } - } - - async handle({ clojar }) { - const json = await this.fetch({ clojar }) - return this.constructor.render({ - clojar, - version: json.latest_release ? json.latest_release : json.latest_version, - }) - } -} diff --git a/services/clojars/clojars-release.tester.js b/services/clojars/clojars-release.tester.js deleted file mode 100644 index 07dc6482a3..0000000000 --- a/services/clojars/clojars-release.tester.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict' - -const t = (module.exports = require('../tester').createServiceTester()) - -t.create('clojars (valid)') - .get('/prismic.json') - .expectBadge({ - label: 'clojars', - message: /^\[prismic "([0-9][.]?)+"\]$/, // note: https://github.com/badges/shields/pull/431 - }) - -t.create('clojars (not found)') - .get('/not-a-package.json') - .expectBadge({ label: 'clojars', message: 'not found' }) diff --git a/services/clojars/clojars-snapshot.service.js b/services/clojars/clojars-snapshot.service.js deleted file mode 100644 index f28a78267e..0000000000 --- a/services/clojars/clojars-snapshot.service.js +++ /dev/null @@ -1,17 +0,0 @@ -'use strict' - -const { BaseClojarsVersionService } = require('./clojars-base') - -module.exports = class ClojarsVersionSnapshot extends BaseClojarsVersionService { - static get route() { - return { - base: 'clojars/vpre', - pattern: ':clojar+', - } - } - - async handle({ clojar }) { - const json = await this.fetch({ clojar }) - return this.constructor.render({ clojar, version: json.latest_version }) - } -} diff --git a/services/clojars/clojars-snapshot.tester.js b/services/clojars/clojars-snapshot.tester.js deleted file mode 100644 index 07dc6482a3..0000000000 --- a/services/clojars/clojars-snapshot.tester.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict' - -const t = (module.exports = require('../tester').createServiceTester()) - -t.create('clojars (valid)') - .get('/prismic.json') - .expectBadge({ - label: 'clojars', - message: /^\[prismic "([0-9][.]?)+"\]$/, // note: https://github.com/badges/shields/pull/431 - }) - -t.create('clojars (not found)') - .get('/not-a-package.json') - .expectBadge({ label: 'clojars', message: 'not found' }) diff --git a/services/clojars/clojars-version.service.js b/services/clojars/clojars-version.service.js new file mode 100644 index 0000000000..ab0404bb71 --- /dev/null +++ b/services/clojars/clojars-version.service.js @@ -0,0 +1,79 @@ +'use strict' + +const Joi = require('@hapi/joi') +const { version: versionColor } = require('../color-formatters') +const { BaseClojarsService } = require('./clojars-base') +const { redirector } = require('..') + +const queryParamSchema = Joi.object({ + include_prereleases: Joi.equal(''), +}).required() + +class ClojarsVersionService extends BaseClojarsService { + static get category() { + return 'version' + } + + static get route() { + return { + base: 'clojars/v', + pattern: ':clojar+', + queryParamSchema, + } + } + + static get examples() { + return [ + { + title: 'Clojars Version', + namedParams: { clojar: 'prismic' }, + staticPreview: this.render({ clojar: 'clojar', version: '1.2' }), + }, + { + title: 'Clojars Version (including pre-releases)', + namedParams: { clojar: 'prismic' }, + queryParams: { include_prereleases: null }, + staticPreview: this.render({ clojar: 'clojar', version: '1.2' }), + }, + ] + } + + static get defaultBadgeData() { + return { label: 'clojars' } + } + + static render({ clojar, version }) { + return { + message: `[${clojar} "${version}"]`, + color: versionColor(version), + } + } + + async handle({ clojar }, queryParams) { + const json = await this.fetch({ clojar }) + const includePrereleases = queryParams.include_prereleases !== undefined + + if (includePrereleases) { + return this.constructor.render({ clojar, version: json.latest_version }) + } + return this.constructor.render({ + clojar, + version: json.latest_release ? json.latest_release : json.latest_version, + }) + } +} + +const ClojarsVersionRedirector = redirector({ + category: 'version', + route: { + base: 'clojars/vpre', + pattern: ':clojar', + }, + transformPath: ({ clojar }) => `/clojars/v/${clojar}`, + transformQueryParams: params => ({ + include_prereleases: null, + }), + dateAdded: new Date('2019-12-15'), +}) + +module.exports = { ClojarsVersionService, ClojarsVersionRedirector } diff --git a/services/clojars/clojars-version.tester.js b/services/clojars/clojars-version.tester.js new file mode 100644 index 0000000000..1078125cca --- /dev/null +++ b/services/clojars/clojars-version.tester.js @@ -0,0 +1,30 @@ +'use strict' + +const { ServiceTester } = require('../tester') +const t = (module.exports = new ServiceTester({ + id: 'ClojarsVersion', + title: 'Clojars Version', + pathPrefix: '/clojars', +})) + +t.create('clojars version (valid)') + .get('/v/prismic.json') + .expectBadge({ + label: 'clojars', + message: /^\[prismic "([0-9][.]?)+"\]$/, // note: https://github.com/badges/shields/pull/431 + }) + +t.create('clojars version (pre) (valid)') + .get('/v/prismic.json?include_prereleases') + .expectBadge({ + label: 'clojars', + message: /^\[prismic "([0-9][.]?)+"\]$/, // note: https://github.com/badges/shields/pull/431 + }) + +t.create('clojars version (not found)') + .get('/v/not-a-package.json') + .expectBadge({ label: 'clojars', message: 'not found' }) + +t.create('version (legacy redirect: vpre)') + .get('/vpre/prismic.svg', { followRedirect: false }) + .expectRedirect('/clojars/v/prismic.svg?include_prereleases') diff --git a/services/nuget/nuget-v2-service-family.js b/services/nuget/nuget-v2-service-family.js index bf4235003c..601c12095f 100644 --- a/services/nuget/nuget-v2-service-family.js +++ b/services/nuget/nuget-v2-service-family.js @@ -7,7 +7,7 @@ const { renderDownloadBadge, odataToObject, } = require('./nuget-helpers') -const { BaseJsonService, BaseXmlService, NotFound } = require('..') +const { BaseJsonService, BaseXmlService, NotFound, redirector } = require('..') function createFilter({ packageName, includePrereleases }) { const releaseTypeFilter = includePrereleases @@ -44,6 +44,10 @@ const xmlSchema = Joi.object({ }).required(), }).required() +const queryParamSchema = Joi.object({ + include_prereleases: Joi.equal(''), +}).required() + async function fetch( serviceInstance, { odataFormat, baseUrl, packageName, includePrereleases = false } @@ -127,8 +131,9 @@ function createServiceFamily({ static get route() { return { - base: serviceBaseUrl, - pattern: ':variant(v|vpre)/:packageName', + base: `${serviceBaseUrl}/v`, + pattern: ':packageName', + queryParamSchema, } } @@ -137,15 +142,14 @@ function createServiceFamily({ return [ { - title, - pattern: 'v/:packageName', + title: `${title} Version`, namedParams: { packageName: examplePackageName }, staticPreview: this.render({ version: exampleVersion }), }, { - title: `${title} (with prereleases)`, - pattern: 'vpre/:packageName', + title: `${title} Version (including pre-releases)`, namedParams: { packageName: examplePackageName }, + queryParams: { include_prereleases: null }, staticPreview: this.render({ version: examplePrereleaseVersion }), }, ] @@ -161,18 +165,31 @@ function createServiceFamily({ return renderVersionBadge(props) } - async handle({ variant, packageName }) { + async handle({ packageName }, queryParams) { const packageData = await fetch(this, { odataFormat, baseUrl: apiBaseUrl, packageName, - includePrereleases: variant === 'vpre', + includePrereleases: queryParams.include_prereleases !== undefined, }) const version = packageData.NormalizedVersion || packageData.Version return this.constructor.render({ version }) } } + const NugetVersionRedirector = redirector({ + category: 'version', + route: { + base: `${serviceBaseUrl}/vpre`, + pattern: ':packageName', + }, + transformPath: ({ packageName }) => `/${serviceBaseUrl}/v/${packageName}`, + transformQueryParams: params => ({ + include_prereleases: null, + }), + dateAdded: new Date('2019-12-15'), + }) + class NugetDownloadService extends Base { static get name() { return `${name}Downloads` @@ -216,7 +233,7 @@ function createServiceFamily({ } } - return { NugetVersionService, NugetDownloadService } + return { NugetVersionService, NugetVersionRedirector, NugetDownloadService } } module.exports = { diff --git a/services/packagist/packagist-version.service.js b/services/packagist/packagist-version.service.js index d3b1dc6eb4..e4c171c0bc 100644 --- a/services/packagist/packagist-version.service.js +++ b/services/packagist/packagist-version.service.js @@ -10,7 +10,7 @@ const { BasePackagistService, customServerDocumentationFragment, } = require('./packagist-base') -const { NotFound } = require('..') +const { NotFound, redirector } = require('..') const packageSchema = Joi.object() .pattern( @@ -32,17 +32,18 @@ const schema = Joi.object({ const queryParamSchema = Joi.object({ server: optionalUrl, + include_prereleases: Joi.equal(''), }).required() -module.exports = class PackagistVersion extends BasePackagistService { +class PackagistVersion extends BasePackagistService { static get category() { return 'version' } static get route() { return { - base: 'packagist', - pattern: ':type(v|vpre)/:user/:repo', + base: 'packagist/v', + pattern: ':user/:repo', queryParamSchema, } } @@ -51,7 +52,6 @@ module.exports = class PackagistVersion extends BasePackagistService { return [ { title: 'Packagist Version', - pattern: 'v/:user/:repo', namedParams: { user: 'symfony', repo: 'symfony', @@ -60,18 +60,17 @@ module.exports = class PackagistVersion extends BasePackagistService { keywords, }, { - title: 'Packagist Pre Release Version', - pattern: 'vpre/:user/:repo', + title: 'Packagist Version (including pre-releases)', namedParams: { user: 'symfony', repo: 'symfony', }, + queryParams: { include_prereleases: null }, staticPreview: renderVersionBadge({ version: '4.3-dev' }), keywords, }, { title: 'Packagist Version (custom server)', - pattern: 'v/:user/:repo', namedParams: { user: 'symfony', repo: 'symfony', @@ -99,7 +98,7 @@ module.exports = class PackagistVersion extends BasePackagistService { return renderVersionBadge({ version }) } - transform({ type, json, user, repo }) { + transform({ includePrereleases, json, user, repo }) { const versionsData = json.packages[this.getPackageName(user, repo)] let versions = Object.keys(versionsData) const aliasesMap = {} @@ -124,7 +123,7 @@ module.exports = class PackagistVersion extends BasePackagistService { versions = versions.filter(version => !/^dev-/.test(version)) - if (type === 'vpre') { + if (includePrereleases) { return { version: latest(versions) } } else { const stableVersion = latest(versions.filter(isStable)) @@ -132,14 +131,28 @@ module.exports = class PackagistVersion extends BasePackagistService { } } - async handle({ type, user, repo }, { server }) { + async handle({ user, repo }, { include_prereleases, server }) { + const includePrereleases = include_prereleases !== undefined const json = await this.fetch({ user, repo, - schema: type === 'v' ? allVersionsSchema : schema, + schema: includePrereleases ? schema : allVersionsSchema, server, }) - const { version } = this.transform({ type, json, user, repo }) + const { version } = this.transform({ includePrereleases, json, user, repo }) return this.constructor.render({ version }) } } + +const PackagistVersionRedirector = redirector({ + category: 'version', + route: { + base: 'packagist/vpre', + pattern: ':user/:repo', + }, + transformPath: ({ user, repo }) => `/packagist/v/${user}/${repo}`, + transformQueryParams: params => ({ include_prereleases: null }), + dateAdded: new Date('2019-12-15'), +}) + +module.exports = { PackagistVersion, PackagistVersionRedirector } diff --git a/services/packagist/packagist-version.tester.js b/services/packagist/packagist-version.tester.js index d84dcf4800..6da4bdeb0d 100644 --- a/services/packagist/packagist-version.tester.js +++ b/services/packagist/packagist-version.tester.js @@ -4,7 +4,12 @@ const Joi = require('@hapi/joi') const { isVPlusDottedVersionNClausesWithOptionalSuffix, } = require('../test-validators') -const t = (module.exports = require('../tester').createServiceTester()) +const { ServiceTester } = require('../tester') +const t = (module.exports = new ServiceTester({ + id: 'packagist', + title: 'Packagist Version', + pathPrefix: '/packagist', +})) /* validator for a packagist version number @@ -35,7 +40,7 @@ t.create('version (invalid package name)') .expectBadge({ label: 'packagist', message: 'not found' }) t.create('pre-release version (valid)') - .get('/vpre/symfony/symfony.json') + .get('/v/symfony/symfony.json?include_prereleases') .expectBadge({ label: 'packagist', message: isVPlusDottedVersionNClausesWithOptionalSuffix, @@ -51,3 +56,15 @@ t.create('version (valid custom server)') t.create('version (invalid custom server)') .get('/v/symfony/symfony.json?server=https%3A%2F%2Fpackagist.com') .expectBadge({ label: 'packagist', message: 'not found' }) + +t.create('version (legacy redirect: vpre)') + .get('/vpre/symfony/symfony.svg', { followRedirect: false }) + .expectRedirect('/packagist/v/symfony/symfony.svg?include_prereleases') + +t.create('version (legacy redirect: vpre) (custom server)') + .get('/vpre/symfony/symfony.svg?server=https%3A%2F%2Fpackagist.org', { + followRedirect: false, + }) + .expectRedirect( + '/packagist/v/symfony/symfony.svg?include_prereleases&server=https%3A%2F%2Fpackagist.org' + ) diff --git a/services/powershellgallery/powershellgallery.service.js b/services/powershellgallery/powershellgallery.service.js index 7cb6158131..9eef674082 100644 --- a/services/powershellgallery/powershellgallery.service.js +++ b/services/powershellgallery/powershellgallery.service.js @@ -14,6 +14,7 @@ const apiBaseUrl = 'https://www.powershellgallery.com/api/v2' const { NugetVersionService: PowershellGalleryVersion, + NugetVersionRedirector: PowershellGalleryVersionRedirector, NugetDownloadService: PowershellGalleryDownloads, } = createServiceFamily({ name: 'PowershellGallery', @@ -106,6 +107,7 @@ class PowershellGalleryPlatformSupport extends BaseXmlService { module.exports = { PowershellGalleryVersion, + PowershellGalleryVersionRedirector, PowershellGalleryDownloads, PowershellGalleryPlatformSupport, } diff --git a/services/powershellgallery/powershellgallery.tester.js b/services/powershellgallery/powershellgallery.tester.js index 776f8febd3..22503f7daf 100644 --- a/services/powershellgallery/powershellgallery.tester.js +++ b/services/powershellgallery/powershellgallery.tester.js @@ -40,16 +40,20 @@ t.create('version (not found)') .expectBadge({ label: 'powershell gallery', message: 'not found' }) t.create('version (pre) (valid)') - .get('/vpre/ACMESharp.json') + .get('/v/ACMESharp.json?include_prereleases') .expectBadge({ label: 'powershell gallery', message: isVPlusDottedVersionNClausesWithOptionalSuffix, }) t.create('version (pre) (not found)') - .get('/vpre/not-a-real-package.json') + .get('/v/not-a-real-package.json?include_prereleases') .expectBadge({ label: 'powershell gallery', message: 'not found' }) +t.create('version (legacy redirect: vpre)') + .get('/vpre/ACMESharp.svg', { followRedirect: false }) + .expectRedirect('/powershellgallery/v/ACMESharp.svg?include_prereleases') + t.create('platform (valid') .get('/p/DNS.1.1.1.1.json') .expectBadge({ diff --git a/services/pub/pub.service.js b/services/pub/pub.service.js index 1127ca03f4..f68e4a9760 100644 --- a/services/pub/pub.service.js +++ b/services/pub/pub.service.js @@ -2,7 +2,7 @@ const Joi = require('@hapi/joi') const { latest, renderVersionBadge } = require('../version') -const { BaseJsonService } = require('..') +const { BaseJsonService, redirector } = require('..') const schema = Joi.object({ versions: Joi.array() @@ -10,31 +10,35 @@ const schema = Joi.object({ .required(), }).required() -module.exports = class PubVersion extends BaseJsonService { +const queryParamSchema = Joi.object({ + include_prereleases: Joi.equal(''), +}).required() + +class PubVersion extends BaseJsonService { static get category() { return 'version' } static get route() { return { - base: 'pub', - pattern: ':variant(v|vpre)/:packageName', + base: 'pub/v', + pattern: ':packageName', + queryParamSchema, } } static get examples() { return [ { - title: 'Pub', - pattern: 'v/:packageName', + title: 'Pub Version', namedParams: { packageName: 'box2d' }, staticPreview: renderVersionBadge({ version: 'v0.4.0' }), keywords: ['dart', 'dartlang'], }, { - title: 'Pub', - pattern: 'vpre/:packageName', + title: 'Pub Version (including pre-releases)', namedParams: { packageName: 'box2d' }, + queryParams: { include_prereleases: null }, staticPreview: renderVersionBadge({ version: 'v0.4.0' }), keywords: ['dart', 'dartlang'], }, @@ -52,11 +56,26 @@ module.exports = class PubVersion extends BaseJsonService { }) } - async handle({ variant, packageName }) { + async handle({ packageName }, queryParams) { const data = await this.fetch({ packageName }) - const includePre = variant === 'vpre' + const includePre = queryParams.include_prereleases !== undefined const versions = data.versions const version = latest(versions, { pre: includePre }) return renderVersionBadge({ version }) } } + +const PubVersionRedirector = redirector({ + category: 'version', + route: { + base: 'pub/vpre', + pattern: ':packageName', + }, + transformPath: ({ packageName }) => `/pub/v/${packageName}`, + transformQueryParams: params => ({ + include_prereleases: null, + }), + dateAdded: new Date('2019-12-15'), +}) + +module.exports = { PubVersion, PubVersionRedirector } diff --git a/services/pub/pub.tester.js b/services/pub/pub.tester.js index 96bda4b97e..8f1f3aea85 100644 --- a/services/pub/pub.tester.js +++ b/services/pub/pub.tester.js @@ -1,7 +1,12 @@ 'use strict' const { isVPlusTripleDottedVersion } = require('../test-validators') -const t = (module.exports = require('../tester').createServiceTester()) +const { ServiceTester } = require('../tester') +const t = (module.exports = new ServiceTester({ + id: 'PubVersion', + title: 'Pub Version', + pathPrefix: '/pub', +})) t.create('package version') .get('/v/box2d.json') @@ -11,7 +16,7 @@ t.create('package version') }) t.create('package pre-release version') - .get('/vpre/box2d.json') + .get('/v/box2d.json?include_prereleases') .expectBadge({ label: 'pub', message: isVPlusTripleDottedVersion, @@ -23,3 +28,7 @@ t.create('package not found') label: 'pub', message: 'not found', }) + +t.create('package version (legacy redirect: vpre)') + .get('/vpre/box2d.svg', { followRedirect: false }) + .expectRedirect('/pub/v/box2d.svg?include_prereleases') diff --git a/services/resharper/resharper.tester.js b/services/resharper/resharper.tester.js index 63eec00eba..33ed3fd4e4 100644 --- a/services/resharper/resharper.tester.js +++ b/services/resharper/resharper.tester.js @@ -41,12 +41,16 @@ t.create('version (not found)') // version (pre) t.create('version (pre) (valid)') - .get('/vpre/ReSharper.Nuke.json') + .get('/v/ReSharper.Nuke.json?include_prereleases') .expectBadge({ label: 'resharper', message: isVPlusDottedVersionNClausesWithOptionalSuffix, }) t.create('version (pre) (not found)') - .get('/vpre/not-a-real-package.json') + .get('/v/not-a-real-package.json?include_prereleases') .expectBadge({ label: 'resharper', message: 'not found' }) + +t.create('version (legacy redirect: vpre)') + .get('/vpre/ReSharper.Nuke.svg', { followRedirect: false }) + .expectRedirect('/resharper/v/ReSharper.Nuke.svg?include_prereleases')