Support custom [Packagist] server (#3986)

* feat(packagist): add custom server query param

* chore(docs): packagist docs tweak

* feat(packagist): custom server downloads badge

* test(packagist): fix custom server tests
This commit is contained in:
Honza Hommer
2019-09-13 21:38:45 +02:00
committed by Caleb Cartwright
parent 4d03e6a028
commit 22d713c29b
9 changed files with 213 additions and 12 deletions

View File

@@ -22,8 +22,8 @@ const allVersionsSchema = Joi.object({
const keywords = ['PHP']
class BasePackagistService extends BaseJsonService {
async fetch({ user, repo, schema }) {
const url = `https://packagist.org/packages/${user}/${repo}.json`
async fetch({ user, repo, schema, server = 'https://packagist.org' }) {
const url = `${server}/packages/${user}/${repo}.json`
return this._requestJson({
schema,
@@ -32,4 +32,12 @@ class BasePackagistService extends BaseJsonService {
}
}
module.exports = { allVersionsSchema, keywords, BasePackagistService }
const documentation =
'Note that only network-accessible packagist.org and other self-hosted Packagist instances are supported.'
module.exports = {
allVersionsSchema,
keywords,
BasePackagistService,
documentation,
}

View File

@@ -3,7 +3,12 @@
const Joi = require('@hapi/joi')
const { metric } = require('../text-formatters')
const { downloadCount } = require('../color-formatters')
const { keywords, BasePackagistService } = require('./packagist-base')
const { optionalUrl } = require('../validators')
const {
keywords,
BasePackagistService,
documentation,
} = require('./packagist-base')
const periodMap = {
dm: {
@@ -30,6 +35,10 @@ const schema = Joi.object({
}).required(),
}).required()
const queryParamSchema = Joi.object({
server: optionalUrl,
}).required()
module.exports = class PackagistDownloads extends BasePackagistService {
static get category() {
return 'downloads'
@@ -39,6 +48,7 @@ module.exports = class PackagistDownloads extends BasePackagistService {
return {
base: 'packagist',
pattern: ':interval(dm|dd|dt)/:user/:repo',
queryParamSchema,
}
}
@@ -57,6 +67,21 @@ module.exports = class PackagistDownloads extends BasePackagistService {
}),
keywords,
},
{
title: 'Packagist (custom server)',
namedParams: {
interval: 'dm',
user: 'doctrine',
repo: 'orm',
},
staticPreview: this.render({
downloads: 1000000,
interval: 'dm',
}),
queryParams: { server: 'https://packagist.org' },
keywords,
documentation,
},
]
}
@@ -73,10 +98,10 @@ module.exports = class PackagistDownloads extends BasePackagistService {
}
}
async handle({ interval, user, repo }) {
async handle({ interval, user, repo }, { server }) {
const {
package: { downloads },
} = await this.fetch({ user, repo, schema })
} = await this.fetch({ user, repo, schema, server })
return this.constructor.render({
downloads: downloads[periodMap[interval].field],

View File

@@ -10,6 +10,22 @@ t.create('daily downloads (valid, no package version specified)')
message: isMetricOverTimePeriod,
})
t.create('daily downloads (valid, no package version specified, custom server)')
.get('/dd/doctrine/orm.json?server=https%3A%2F%2Fpackagist.org')
.expectBadge({
label: 'downloads',
message: isMetricOverTimePeriod,
})
t.create(
'daily downloads (invalid, no package version specified, invalid custom server)'
)
.get('/dd/doctrine/orm.json?server=https%3A%2F%2Fpackagist.com')
.expectBadge({
label: 'downloads',
message: 'not found',
})
t.create('monthly downloads (valid, no package version specified)')
.get('/dm/doctrine/orm.json')
.expectBadge({
@@ -17,6 +33,24 @@ t.create('monthly downloads (valid, no package version specified)')
message: isMetricOverTimePeriod,
})
t.create(
'monthly downloads (valid, no package version specified, custom server)'
)
.get('/dm/doctrine/orm.json?server=https%3A%2F%2Fpackagist.org')
.expectBadge({
label: 'downloads',
message: isMetricOverTimePeriod,
})
t.create(
'monthly downloads (valid, no package version specified, invalid custom server)'
)
.get('/dm/doctrine/orm.json?server=https%3A%2F%2Fpackagist.com')
.expectBadge({
label: 'downloads',
message: 'not found',
})
t.create('total downloads (valid, no package version specified)')
.get('/dt/doctrine/orm.json')
.expectBadge({
@@ -24,27 +58,69 @@ t.create('total downloads (valid, no package version specified)')
message: isMetric,
})
t.create('total downloads (valid, no package version specified, custom server)')
.get('/dt/doctrine/orm.json?server=https%3A%2F%2Fpackagist.org')
.expectBadge({
label: 'downloads',
message: isMetric,
})
t.create(
'total downloads (valid, no package version specified, invalid custom server)'
)
.get('/dt/doctrine/orm.json?server=https%3A%2F%2Fpackagist.com')
.expectBadge({
label: 'downloads',
message: 'not found',
})
// note: packagist can't give us download stats for a specific version
t.create('daily downloads (invalid, package version specified)')
.get('/dd/symfony/symfony/v2.8.0.json')
.expectBadge({ label: '404', message: 'badge not found' })
t.create('daily downloads (invalid, package version specified, custom server)')
.get('/dd/symfony/symfony/v2.8.0.json?server=https%3A%2F%2Fpackagist.org')
.expectBadge({ label: '404', message: 'badge not found' })
t.create('monthly downloads (invalid, package version in request)')
.get('/dm/symfony/symfony/v2.8.0.json')
.expectBadge({ label: '404', message: 'badge not found' })
t.create(
'monthly downloads (invalid, package version in request, custom server)'
)
.get('/dm/symfony/symfony/v2.8.0.json?server=https%3A%2F%2Fpackagist.org')
.expectBadge({ label: '404', message: 'badge not found' })
t.create('total downloads (invalid, package version in request)')
.get('/dt/symfony/symfony/v2.8.0.json')
.expectBadge({ label: '404', message: 'badge not found' })
t.create('total downloads (invalid, package version in request, custom server)')
.get('/dt/symfony/symfony/v2.8.0.json?server=https%3A%2F%2Fpackagist.org')
.expectBadge({ label: '404', message: 'badge not found' })
t.create('daily downloads (invalid package name)')
.get('/dd/frodo/is-not-a-package.json')
.expectBadge({ label: 'downloads', message: 'not found' })
t.create('daily downloads (invalid package name, custom server)')
.get('/dd/frodo/is-not-a-package.json?server=https%3A%2F%2Fpackagist.org')
.expectBadge({ label: 'downloads', message: 'not found' })
t.create('monthly downloads (invalid package name)')
.get('/dm/frodo/is-not-a-package.json')
.expectBadge({ label: 'downloads', message: 'not found' })
t.create('monthly downloads (invalid package name, custom server)')
.get('/dm/frodo/is-not-a-package.json?server=https%3A%2F%2Fpackagist.org')
.expectBadge({ label: 'downloads', message: 'not found' })
t.create('total downloads (invalid package name)')
.get('/dt/frodo/is-not-a-package.json')
.expectBadge({ label: 'downloads', message: 'not found' })
t.create('total downloads (invalid package name, custom server)')
.get('/dt/frodo/is-not-a-package.json?server=https%3A%2F%2Fpackagist.org')
.expectBadge({ label: 'downloads', message: 'not found' })

View File

@@ -2,7 +2,12 @@
const Joi = require('@hapi/joi')
const { renderLicenseBadge } = require('../licenses')
const { keywords, BasePackagistService } = require('./packagist-base')
const { optionalUrl } = require('../validators')
const {
keywords,
BasePackagistService,
documentation,
} = require('./packagist-base')
const schema = Joi.object({
package: Joi.object({
@@ -14,6 +19,10 @@ const schema = Joi.object({
}).required(),
}).required()
const queryParamSchema = Joi.object({
server: optionalUrl,
}).required()
module.exports = class PackagistLicense extends BasePackagistService {
static get category() {
return 'license'
@@ -23,6 +32,7 @@ module.exports = class PackagistLicense extends BasePackagistService {
return {
base: 'packagist/l',
pattern: ':user/:repo',
queryParamSchema,
}
}
@@ -34,6 +44,14 @@ module.exports = class PackagistLicense extends BasePackagistService {
staticPreview: renderLicenseBadge({ license: 'MIT' }),
keywords,
},
{
title: 'Packagist (custom server)',
namedParams: { user: 'doctrine', repo: 'orm' },
queryParams: { server: 'https://packagist.org' },
staticPreview: renderLicenseBadge({ license: 'MIT' }),
keywords,
documentation,
},
]
}
@@ -47,8 +65,8 @@ module.exports = class PackagistLicense extends BasePackagistService {
return { license: json.package.versions['dev-master'].license }
}
async handle({ user, repo }) {
const json = await this.fetch({ user, repo, schema })
async handle({ user, repo }, { server }) {
const json = await this.fetch({ user, repo, schema, server })
const { license } = this.transform({ json })
return renderLicenseBadge({ license })
}

View File

@@ -15,3 +15,11 @@ t.create('license (invalid, package version in request)')
t.create('license (invalid)')
.get('/frodo/is-not-a-package.json')
.expectBadge({ label: 'license', message: 'not found' })
t.create('license (valid custom server)')
.get('/symfony/symfony.json?server=https%3A%2F%2Fpackagist.org')
.expectBadge({ label: 'license', message: 'MIT' })
t.create('license (invalid custom server)')
.get('/symfony/symfony.json?server=https%3A%2F%2Fpackagist.com')
.expectBadge({ label: 'license', message: 'not found' })

View File

@@ -1,8 +1,18 @@
'use strict'
const { allVersionsSchema, BasePackagistService } = require('./packagist-base')
const Joi = require('@hapi/joi')
const { optionalUrl } = require('../validators')
const {
allVersionsSchema,
BasePackagistService,
documentation,
} = require('./packagist-base')
const { NotFound } = require('..')
const queryParamSchema = Joi.object({
server: optionalUrl,
}).required()
module.exports = class PackagistPhpVersion extends BasePackagistService {
static get category() {
return 'platform-support'
@@ -12,6 +22,7 @@ module.exports = class PackagistPhpVersion extends BasePackagistService {
return {
base: 'packagist/php-v',
pattern: ':user/:repo/:version?',
queryParamSchema,
}
}
@@ -36,6 +47,19 @@ module.exports = class PackagistPhpVersion extends BasePackagistService {
},
staticPreview: this.render({ php: '>=5.3.9' }),
},
{
title: 'PHP from Packagist (custom server)',
pattern: ':user/:repo',
namedParams: {
user: 'symfony',
repo: 'symfony',
},
queryParams: {
server: 'https://packagist.org',
},
staticPreview: this.render({ php: '^7.1.3' }),
documentation,
},
]
}
@@ -52,11 +76,12 @@ module.exports = class PackagistPhpVersion extends BasePackagistService {
}
}
async handle({ user, repo, version = 'dev-master' }) {
async handle({ user, repo, version = 'dev-master' }, { server }) {
const allData = await this.fetch({
user,
repo,
schema: allVersionsSchema,
server,
})
if (!allData.package.versions.hasOwnProperty(version)) {

View File

@@ -26,3 +26,11 @@ t.create('invalid package name')
t.create('invalid version')
.get('/symfony/symfony/invalid.json')
.expectBadge({ label: 'php', message: 'invalid version' })
t.create('custom server')
.get('/symfony/symfony.json?server=https%3A%2F%2Fpackagist.org')
.expectBadge({ label: 'php', message: isComposerVersion })
t.create('invalid custom server')
.get('/symfony/symfony.json?server=https%3A%2F%2Fpackagist.com')
.expectBadge({ label: 'php', message: 'not found' })

View File

@@ -3,10 +3,12 @@
const Joi = require('@hapi/joi')
const { renderVersionBadge } = require('../version')
const { compare, isStable, latest } = require('../php-version')
const { optionalUrl } = require('../validators')
const {
allVersionsSchema,
keywords,
BasePackagistService,
documentation,
} = require('./packagist-base')
const { NotFound } = require('..')
@@ -26,6 +28,10 @@ const schema = Joi.object({
}).required(),
}).required()
const queryParamSchema = Joi.object({
server: optionalUrl,
}).required()
module.exports = class PackagistVersion extends BasePackagistService {
static get category() {
return 'version'
@@ -35,6 +41,7 @@ module.exports = class PackagistVersion extends BasePackagistService {
return {
base: 'packagist',
pattern: ':type(v|vpre)/:user/:repo',
queryParamSchema,
}
}
@@ -60,6 +67,20 @@ module.exports = class PackagistVersion extends BasePackagistService {
staticPreview: renderVersionBadge({ version: '4.3-dev' }),
keywords,
},
{
title: 'Packagist Version (custom server)',
pattern: 'v/:user/:repo',
namedParams: {
user: 'symfony',
repo: 'symfony',
},
queryParams: {
server: 'https://packagist.org',
},
staticPreview: renderVersionBadge({ version: '4.2.2' }),
keywords,
documentation,
},
]
}
@@ -109,11 +130,12 @@ module.exports = class PackagistVersion extends BasePackagistService {
}
}
async handle({ type, user, repo }) {
async handle({ type, user, repo }, { server }) {
const json = await this.fetch({
user,
repo,
schema: type === 'v' ? allVersionsSchema : schema,
server,
})
const { version } = this.transform({ type, json })
return this.constructor.render({ version })

View File

@@ -40,3 +40,14 @@ t.create('pre-release version (valid)')
label: 'packagist',
message: isVPlusDottedVersionNClausesWithOptionalSuffix,
})
t.create('version (valid custom server)')
.get('/v/symfony/symfony.json?server=https%3A%2F%2Fpackagist.org')
.expectBadge({
label: 'packagist',
message: isPackagistVersion,
})
t.create('version (invalid custom server)')
.get('/v/symfony/symfony.json?server=https%3A%2F%2Fpackagist.com')
.expectBadge({ label: 'packagist', message: 'not found' })