Unify remaining service order and enforce (#3359)

Ref #3353
This commit is contained in:
Paul Melnikow
2019-04-24 16:53:33 -04:00
committed by GitHub
parent f8aeb56129
commit 0088a9d0da
38 changed files with 665 additions and 665 deletions

View File

@@ -22,7 +22,7 @@ overrides:
rules:
sort-class-members/sort-class-members:
[
'warn',
'error',
{
order:
[

View File

@@ -111,16 +111,6 @@ module.exports = class BaseService {
throw new Error(`Route not defined for ${this.name}`)
}
static get _cacheLength() {
const cacheLengths = {
build: 30,
license: 3600,
version: 300,
debug: 60,
}
return cacheLengths[this.category]
}
/**
* Example URLs for this service. These should use the format
* specified in `route`, and can be used to demonstrate how to use badges for
@@ -153,6 +143,16 @@ module.exports = class BaseService {
return []
}
static get _cacheLength() {
const cacheLengths = {
build: 30,
license: 3600,
version: 300,
debug: 60,
}
return cacheLengths[this.category]
}
/**
* Default data for the badge. Can include label, logo, and color. These
* defaults are used if the value is neither included in the service data
@@ -162,6 +162,10 @@ module.exports = class BaseService {
return {}
}
static render(props) {
throw new Error(`render() function not implemented for ${this.name}`)
}
static validateDefinition() {
assertValidCategory(this.category, `Category for ${this.name}`)
@@ -209,10 +213,6 @@ module.exports = class BaseService {
return result
}
static render(props) {
throw new Error(`render() function not implemented for ${this.name}`)
}
constructor({ sendAndCacheRequest }, { handleInternalErrors }) {
this._requestFetcher = sendAndCacheRequest
this._handleInternalErrors = handleInternalErrors

View File

@@ -21,29 +21,6 @@ class AnsibleGalaxyContent extends BaseJsonService {
}
module.exports = class AnsibleGalaxyContentQualityScore extends AnsibleGalaxyContent {
static render({ qualityScore }) {
return {
message: qualityScore,
color: floorCount(qualityScore, 2, 3, 4),
}
}
async handle({ projectId }) {
const { quality_score: qualityScore } = await this.fetch({ projectId })
if (qualityScore === null) {
throw new InvalidResponse({
prettyMessage: 'no score available',
})
}
return this.constructor.render({ qualityScore })
}
static get defaultBadgeData() {
return { label: 'quality' }
}
static get category() {
return 'analysis'
}
@@ -66,4 +43,27 @@ module.exports = class AnsibleGalaxyContentQualityScore extends AnsibleGalaxyCon
},
]
}
static get defaultBadgeData() {
return { label: 'quality' }
}
static render({ qualityScore }) {
return {
message: qualityScore,
color: floorCount(qualityScore, 2, 3, 4),
}
}
async handle({ projectId }) {
const { quality_score: qualityScore } = await this.fetch({ projectId })
if (qualityScore === null) {
throw new InvalidResponse({
prettyMessage: 'no score available',
})
}
return this.constructor.render({ qualityScore })
}
}

View File

@@ -27,22 +27,6 @@ class AnsibleGalaxyRole extends BaseJsonService {
}
class AnsibleGalaxyRoleDownloads extends AnsibleGalaxyRole {
static render({ downloads }) {
return {
message: metric(downloads),
color: downloadCount(downloads),
}
}
async handle({ roleId }) {
const json = await this.fetch({ roleId })
return this.constructor.render({ downloads: json.download_count })
}
static get defaultBadgeData() {
return { label: 'role downloads' }
}
static get category() {
return 'downloads'
}
@@ -63,23 +47,25 @@ class AnsibleGalaxyRoleDownloads extends AnsibleGalaxyRole {
},
]
}
}
class AnsibleGalaxyRoleName extends AnsibleGalaxyRole {
static render({ name }) {
return { message: name, color: 'blue' }
static get defaultBadgeData() {
return { label: 'role downloads' }
}
static render({ downloads }) {
return {
message: metric(downloads),
color: downloadCount(downloads),
}
}
async handle({ roleId }) {
const json = await this.fetch({ roleId })
const name = `${json.summary_fields.namespace.name}.${json.name}`
return this.constructor.render({ name })
}
static get defaultBadgeData() {
return { label: 'role' }
return this.constructor.render({ downloads: json.download_count })
}
}
class AnsibleGalaxyRoleName extends AnsibleGalaxyRole {
static get category() {
return 'other'
}
@@ -102,6 +88,20 @@ class AnsibleGalaxyRoleName extends AnsibleGalaxyRole {
},
]
}
static get defaultBadgeData() {
return { label: 'role' }
}
static render({ name }) {
return { message: name, color: 'blue' }
}
async handle({ roleId }) {
const json = await this.fetch({ roleId })
const name = `${json.summary_fields.namespace.name}.${json.name}`
return this.constructor.render({ name })
}
}
module.exports = {

View File

@@ -20,6 +20,10 @@ const schema = Joi.object({
})
class BaseAPMService extends BaseJsonService {
static get defaultBadgeData() {
return { label: 'apm' }
}
async fetch({ packageName }) {
return this._requestJson({
schema,
@@ -27,30 +31,13 @@ class BaseAPMService extends BaseJsonService {
errorMessages: { 404: 'package not found' },
})
}
static get defaultBadgeData() {
return { label: 'apm' }
}
}
class APMDownloads extends BaseAPMService {
static render({ downloads }) {
return { message: metric(downloads), color: 'green' }
}
async handle({ packageName }) {
const json = await this.fetch({ packageName })
return this.constructor.render({ downloads: json.downloads })
}
static get category() {
return 'downloads'
}
static get defaultBadgeData() {
return { label: 'downloads' }
}
static get route() {
return {
base: 'apm/dm',
@@ -68,24 +55,22 @@ class APMDownloads extends BaseAPMService {
},
]
}
}
class APMVersion extends BaseAPMService {
static render({ version }) {
return renderVersionBadge({ version })
static get defaultBadgeData() {
return { label: 'downloads' }
}
static render({ downloads }) {
return { message: metric(downloads), color: 'green' }
}
async handle({ packageName }) {
const json = await this.fetch({ packageName })
const version = json.releases.latest
if (!version)
throw new InvalidResponse({
underlyingError: new Error('version is invalid'),
})
return this.constructor.render({ version })
return this.constructor.render({ downloads: json.downloads })
}
}
class APMVersion extends BaseAPMService {
static get category() {
return 'version'
}
@@ -107,28 +92,24 @@ class APMVersion extends BaseAPMService {
},
]
}
}
class APMLicense extends BaseAPMService {
static render({ license }) {
return renderLicenseBadge({ license })
static render({ version }) {
return renderVersionBadge({ version })
}
async handle({ packageName }) {
const json = await this.fetch({ packageName })
const license = json.metadata.license
if (!license)
const version = json.releases.latest
if (!version)
throw new InvalidResponse({
underlyingError: new Error('licence is invalid'),
underlyingError: new Error('version is invalid'),
})
return this.constructor.render({ license })
}
static get defaultBadgeData() {
return { label: 'license' }
return this.constructor.render({ version })
}
}
class APMLicense extends BaseAPMService {
static get category() {
return 'license'
}
@@ -150,6 +131,25 @@ class APMLicense extends BaseAPMService {
},
]
}
static get defaultBadgeData() {
return { label: 'license' }
}
static render({ license }) {
return renderLicenseBadge({ license })
}
async handle({ packageName }) {
const json = await this.fetch({ packageName })
const license = json.metadata.license
if (!license)
throw new InvalidResponse({
underlyingError: new Error('licence is invalid'),
})
return this.constructor.render({ license })
}
}
module.exports = {

View File

@@ -44,12 +44,6 @@ module.exports = class AppVeyorTests extends AppVeyorBase {
}
}
static get defaultBadgeData() {
return {
label: 'tests',
}
}
static get examples() {
return [
{
@@ -110,6 +104,12 @@ module.exports = class AppVeyorTests extends AppVeyorBase {
]
}
static get defaultBadgeData() {
return {
label: 'tests',
}
}
static render({
passed,
failed,

View File

@@ -22,14 +22,6 @@ const aurSchema = Joi.object({
}).required()
class BaseAurService extends BaseJsonService {
async fetch({ packageName }) {
return this._requestJson({
schema: aurSchema,
url: 'https://aur.archlinux.org/rpc.php',
options: { qs: { type: 'info', arg: packageName } },
})
}
static get defaultBadgeData() {
return { label: 'aur' }
}
@@ -43,22 +35,17 @@ class BaseAurService extends BaseJsonService {
}
return super._validate(data, schema)
}
async fetch({ packageName }) {
return this._requestJson({
schema: aurSchema,
url: 'https://aur.archlinux.org/rpc.php',
options: { qs: { type: 'info', arg: packageName } },
})
}
}
class AurLicense extends BaseAurService {
static render({ license }) {
return { message: license, color: 'blue' }
}
async handle({ packageName }) {
const json = await this.fetch({ packageName })
return this.constructor.render({ license: json.results.License })
}
static get defaultBadgeData() {
return { label: 'license' }
}
static get category() {
return 'license'
}
@@ -79,29 +66,25 @@ class AurLicense extends BaseAurService {
},
]
}
}
class AurVotes extends BaseAurService {
static render({ votes }) {
return {
message: metric(votes),
color: floorCountColor(votes, 2, 20, 60),
}
static get defaultBadgeData() {
return { label: 'license' }
}
static render({ license }) {
return { message: license, color: 'blue' }
}
async handle({ packageName }) {
const json = await this.fetch({ packageName })
return this.constructor.render({ votes: json.results.NumVotes })
}
static get defaultBadgeData() {
return { label: 'votes' }
return this.constructor.render({ license: json.results.License })
}
}
class AurVotes extends BaseAurService {
static get category() {
return 'rating'
}
static get route() {
return {
base: 'aur/votes',
@@ -118,22 +101,25 @@ class AurVotes extends BaseAurService {
},
]
}
}
class AurVersion extends BaseAurService {
static render({ version, outOfDate }) {
const color = outOfDate === null ? 'blue' : 'orange'
return { message: addv(version), color }
static get defaultBadgeData() {
return { label: 'votes' }
}
static render({ votes }) {
return {
message: metric(votes),
color: floorCountColor(votes, 2, 20, 60),
}
}
async handle({ packageName }) {
const json = await this.fetch({ packageName })
return this.constructor.render({
version: json.results.Version,
outOfDate: json.results.OutOfDate,
})
return this.constructor.render({ votes: json.results.NumVotes })
}
}
class AurVersion extends BaseAurService {
static get category() {
return 'version'
}
@@ -154,6 +140,19 @@ class AurVersion extends BaseAurService {
},
]
}
static render({ version, outOfDate }) {
const color = outOfDate === null ? 'blue' : 'orange'
return { message: addv(version), color }
}
async handle({ packageName }) {
const json = await this.fetch({ packageName })
return this.constructor.render({
version: json.results.Version,
outOfDate: json.results.OutOfDate,
})
}
}
module.exports = {

View File

@@ -47,21 +47,17 @@ const buildCodeCoverageSchema = Joi.object({
}).required()
module.exports = class AzureDevOpsCoverage extends AzureDevOpsBase {
static render({ coverage }) {
return {
message: `${coverage.toFixed(0)}%`,
color: coveragePercentageColor(coverage),
}
}
static get defaultBadgeData() {
return { label: 'coverage' }
}
static get category() {
return 'coverage'
}
static get route() {
return {
base: 'azure-devops/coverage',
pattern: ':organization/:project/:definitionId/:branch*',
}
}
static get examples() {
return [
{
@@ -92,10 +88,14 @@ module.exports = class AzureDevOpsCoverage extends AzureDevOpsBase {
]
}
static get route() {
static get defaultBadgeData() {
return { label: 'coverage' }
}
static render({ coverage }) {
return {
base: 'azure-devops/coverage',
pattern: ':organization/:project/:definitionId/:branch*',
message: `${coverage.toFixed(0)}%`,
color: coveragePercentageColor(coverage),
}
}

View File

@@ -63,36 +63,18 @@ const buildTestResultSummarySchema = Joi.object({
}).required()
module.exports = class AzureDevOpsTests extends AzureDevOpsBase {
static render({
passed,
failed,
skipped,
total,
passedLabel,
failedLabel,
skippedLabel,
isCompact,
}) {
return renderTestResultBadge({
passed,
failed,
skipped,
total,
passedLabel,
failedLabel,
skippedLabel,
isCompact,
})
}
static get defaultBadgeData() {
return { label: 'tests' }
}
static get category() {
return 'build'
}
static get route() {
return {
base: 'azure-devops/tests',
pattern: ':organization/:project/:definitionId/:branch*',
queryParamSchema: testResultQueryParamSchema,
}
}
static get examples() {
return [
{
@@ -175,12 +157,30 @@ module.exports = class AzureDevOpsTests extends AzureDevOpsBase {
]
}
static get route() {
return {
base: 'azure-devops/tests',
pattern: ':organization/:project/:definitionId/:branch*',
queryParamSchema: testResultQueryParamSchema,
}
static get defaultBadgeData() {
return { label: 'tests' }
}
static render({
passed,
failed,
skipped,
total,
passedLabel,
failedLabel,
skippedLabel,
isCompact,
}) {
return renderTestResultBadge({
passed,
failed,
skipped,
total,
passedLabel,
failedLabel,
skippedLabel,
isCompact,
})
}
async handle(

View File

@@ -12,7 +12,37 @@ const collectionSchema = Joi.object({
}).required(),
}).required()
module.exports = class bitComponents extends BaseJsonService {
module.exports = class BitComponents extends BaseJsonService {
static get category() {
return 'other'
}
static get route() {
return {
base: 'bit/collection/total-components',
pattern: ':owner/:collection',
}
}
static get examples() {
return [
{
title: 'bit',
namedParams: { owner: 'ramda', collection: 'ramda' },
staticPreview: this.render({ count: 330 }),
keywords: ['components'],
},
]
}
static get defaultBadgeData() {
return { label: 'components' }
}
static render({ count }) {
return { message: metric(count), color: downloadCount(count) }
}
async fetch({ owner, collection }) {
const url = `https://api.bit.dev/scope/${owner}/${collection}/`
return this._requestJson({
@@ -24,37 +54,8 @@ module.exports = class bitComponents extends BaseJsonService {
})
}
static render({ count }) {
return { message: metric(count), color: downloadCount(count) }
}
async handle({ owner, collection }) {
const json = await this.fetch({ owner, collection })
return this.constructor.render({ count: json.payload.totalComponents })
}
static get defaultBadgeData() {
return { label: 'components' }
}
static get category() {
return 'other'
}
static get route() {
return {
base: 'bit/collection/total-components',
pattern: ':owner/:collection',
}
}
static get examples() {
return [
{
title: 'bit',
namedParams: { owner: 'ramda', collection: 'ramda' },
staticPreview: this.render({ count: 330 }),
keywords: ['components'],
},
]
}
}

View File

@@ -18,39 +18,10 @@ function issueClassGenerator(raw) {
return `BitbucketIssues${raw ? 'Raw' : ''}`
}
async fetch({ user, repo }) {
const url = `https://bitbucket.org/api/1.0/repositories/${user}/${repo}/issues/`
return this._requestJson({
url,
schema: bitbucketIssuesSchema,
options: {
qs: { limit: 0, status: ['new', 'open'] },
useQuerystring: true,
},
errorMessages: { 403: 'private repo' },
})
}
static render({ issues }) {
return {
message: `${metric(issues)}${badgeSuffix}`,
color: issues ? 'yellow' : 'brightgreen',
}
}
async handle({ user, repo }) {
const data = await this.fetch({ user, repo })
return this.constructor.render({ issues: data.count })
}
static get category() {
return 'issue-tracking'
}
static get defaultBadgeData() {
return { label: 'issues' }
}
static get route() {
return {
base: `bitbucket/${routePrefix}`,
@@ -70,6 +41,35 @@ function issueClassGenerator(raw) {
},
]
}
static get defaultBadgeData() {
return { label: 'issues' }
}
static render({ issues }) {
return {
message: `${metric(issues)}${badgeSuffix}`,
color: issues ? 'yellow' : 'brightgreen',
}
}
async fetch({ user, repo }) {
const url = `https://bitbucket.org/api/1.0/repositories/${user}/${repo}/issues/`
return this._requestJson({
url,
schema: bitbucketIssuesSchema,
options: {
qs: { limit: 0, status: ['new', 'open'] },
useQuerystring: true,
},
errorMessages: { 403: 'private repo' },
})
}
async handle({ user, repo }) {
const data = await this.fetch({ user, repo })
return this.constructor.render({ issues: data.count })
}
}
}

View File

@@ -26,52 +26,10 @@ const bitbucketPipelinesSchema = Joi.object({
}).required()
module.exports = class BitbucketPipelines extends BaseJsonService {
async fetch({ user, repo, branch }) {
const url = `https://api.bitbucket.org/2.0/repositories/${user}/${repo}/pipelines/`
return this._requestJson({
url,
schema: bitbucketPipelinesSchema,
options: {
qs: {
fields: 'values.state',
page: 1,
pagelen: 2,
sort: '-created_on',
'target.ref_type': 'BRANCH',
'target.ref_name': branch,
},
},
errorMessages: { 403: 'private repo' },
})
}
static render({ status }) {
return renderBuildStatusBadge({ status: status.toLowerCase() })
}
static transform(data) {
const values = data.values.filter(
value => value.state && value.state.name === 'COMPLETED'
)
if (values.length > 0) {
return values[0].state.result.name
}
return 'never built'
}
async handle({ user, repo, branch }) {
const data = await this.fetch({ user, repo, branch: branch || 'master' })
return this.constructor.render({ status: this.constructor.transform(data) })
}
static get category() {
return 'build'
}
static get defaultBadgeData() {
return { label: 'build' }
}
static get route() {
return {
base: 'bitbucket/pipelines',
@@ -102,4 +60,46 @@ module.exports = class BitbucketPipelines extends BaseJsonService {
},
]
}
static get defaultBadgeData() {
return { label: 'build' }
}
static render({ status }) {
return renderBuildStatusBadge({ status: status.toLowerCase() })
}
async fetch({ user, repo, branch }) {
const url = `https://api.bitbucket.org/2.0/repositories/${user}/${repo}/pipelines/`
return this._requestJson({
url,
schema: bitbucketPipelinesSchema,
options: {
qs: {
fields: 'values.state',
page: 1,
pagelen: 2,
sort: '-created_on',
'target.ref_type': 'BRANCH',
'target.ref_name': branch,
},
},
errorMessages: { 403: 'private repo' },
})
}
static transform(data) {
const values = data.values.filter(
value => value.state && value.state.name === 'COMPLETED'
)
if (values.length > 0) {
return values[0].state.result.name
}
return 'never built'
}
async handle({ user, repo, branch }) {
const data = await this.fetch({ user, repo, branch: branch || 'master' })
return this.constructor.render({ status: this.constructor.transform(data) })
}
}

View File

@@ -23,6 +23,51 @@ function pullRequestClassGenerator(raw) {
return `BitbucketPullRequest${raw ? 'Raw' : ''}`
}
static get category() {
return 'issue-tracking'
}
static get route() {
return {
base: `bitbucket/${routePrefix}`,
pattern: `:user/:repo`,
queryParamSchema,
}
}
static get examples() {
return [
{
title: 'Bitbucket open pull requests',
namedParams: {
user: 'atlassian',
repo: 'python-bitbucket',
},
staticPreview: this.render({ prs: 22 }),
},
{
title: 'Bitbucket Server open pull requests',
namedParams: {
user: 'foo',
repo: 'bar',
},
queryParams: { server: 'https://bitbucket.mydomain.net' },
staticPreview: this.render({ prs: 42 }),
},
]
}
static get defaultBadgeData() {
return { label: 'pull requests' }
}
static render({ prs }) {
return {
message: `${metric(prs)}${badgeSuffix}`,
color: prs ? 'yellow' : 'brightgreen',
}
}
async fetchCloud({ args, user, repo }) {
args.url = `https://bitbucket.org/api/2.0/repositories/${user}/${repo}/pullrequests/`
args.options = { qs: { state: 'OPEN', limit: 0 } }
@@ -82,55 +127,10 @@ function pullRequestClassGenerator(raw) {
}
}
static render({ prs }) {
return {
message: `${metric(prs)}${badgeSuffix}`,
color: prs ? 'yellow' : 'brightgreen',
}
}
async handle({ user, repo }, { server }) {
const data = await this.fetch({ server, user, repo })
return this.constructor.render({ prs: data.size })
}
static get category() {
return 'issue-tracking'
}
static get defaultBadgeData() {
return { label: 'pull requests' }
}
static get route() {
return {
base: `bitbucket/${routePrefix}`,
pattern: `:user/:repo`,
queryParamSchema,
}
}
static get examples() {
return [
{
title: 'Bitbucket open pull requests',
namedParams: {
user: 'atlassian',
repo: 'python-bitbucket',
},
staticPreview: this.render({ prs: 22 }),
},
{
title: 'Bitbucket Server open pull requests',
namedParams: {
user: 'foo',
repo: 'bar',
},
queryParams: { server: 'https://bitbucket.mydomain.net' },
staticPreview: this.render({ prs: 42 }),
},
]
}
}
}

View File

@@ -42,19 +42,6 @@ module.exports = class Bitrise extends BaseJsonService {
}
}
async fetch({ appId, branch, token }) {
return this._requestJson({
url: `https://app.bitrise.io/app/${encodeURIComponent(
appId
)}/status.json`,
options: { qs: { token, branch } },
schema,
errorMessages: {
403: 'app not found or invalid token',
},
})
}
static render({ status }) {
const color = {
success: 'brightgreen',
@@ -74,6 +61,19 @@ module.exports = class Bitrise extends BaseJsonService {
return { message, color }
}
async fetch({ appId, branch, token }) {
return this._requestJson({
url: `https://app.bitrise.io/app/${encodeURIComponent(
appId
)}/status.json`,
options: { qs: { token, branch } },
schema,
errorMessages: {
403: 'app not found or invalid token',
},
})
}
async handle({ appId, branch }, { token }) {
const { status } = await this.fetch({ appId, branch, token })
return this.constructor.render({ status })

View File

@@ -8,25 +8,10 @@ const { metric } = require('../text-formatters')
const schema = Joi.object({ activity_total: nonNegativeInteger })
module.exports = class Bountysource extends BaseJsonService {
async fetch({ team }) {
const url = `https://api.bountysource.com/teams/${team}`
return this._requestJson({
schema,
url,
options: {
headers: { Accept: 'application/vnd.bountysource+json; version=2' },
},
})
}
static get category() {
return 'funding'
}
static get defaultBadgeData() {
return { label: 'bounties' }
}
static get route() {
return {
base: 'bountysource/team',
@@ -44,6 +29,10 @@ module.exports = class Bountysource extends BaseJsonService {
]
}
static get defaultBadgeData() {
return { label: 'bounties' }
}
static render({ total }) {
return {
message: metric(total),
@@ -51,6 +40,17 @@ module.exports = class Bountysource extends BaseJsonService {
}
}
async fetch({ team }) {
const url = `https://api.bountysource.com/teams/${team}`
return this._requestJson({
schema,
url,
options: {
headers: { Accept: 'application/vnd.bountysource+json; version=2' },
},
})
}
async handle({ team }) {
const json = await this.fetch({ team })
return this.constructor.render({ total: json.activity_total })

View File

@@ -9,6 +9,10 @@ const schema = Joi.array()
.required()
module.exports = class BStatsPlayers extends BaseJsonService {
static get category() {
return 'other'
}
static get route() {
return {
base: 'bstats/players',
@@ -16,6 +20,18 @@ module.exports = class BStatsPlayers extends BaseJsonService {
}
}
static get examples() {
return [
{
title: 'bStats Players',
namedParams: {
pluginid: '1',
},
staticPreview: this.render({ players: 74299 }),
},
]
}
static get defaultBadgeData() {
return {
label: 'players',
@@ -23,15 +39,10 @@ module.exports = class BStatsPlayers extends BaseJsonService {
}
}
async handle({ pluginid }) {
const json = await this.fetch({ pluginid })
const { players } = this.transform({ json })
return this.constructor.render({ players })
}
transform({ json }) {
const players = json[0][1]
return { players }
static render({ players }) {
return {
message: metric(players),
}
}
async fetch({ pluginid }) {
@@ -48,24 +59,14 @@ module.exports = class BStatsPlayers extends BaseJsonService {
})
}
static render({ players }) {
return {
message: metric(players),
}
transform({ json }) {
const players = json[0][1]
return { players }
}
static get category() {
return 'other'
}
static get examples() {
return [
{
title: 'bStats Players',
namedParams: {
pluginid: '1',
},
staticPreview: this.render({ players: 74299 }),
},
]
async handle({ pluginid }) {
const json = await this.fetch({ pluginid })
const { players } = this.transform({ json })
return this.constructor.render({ players })
}
}

View File

@@ -9,6 +9,10 @@ const schema = Joi.array()
.required()
module.exports = class BStatsServers extends BaseJsonService {
static get category() {
return 'other'
}
static get route() {
return {
base: 'bstats/servers',
@@ -16,6 +20,18 @@ module.exports = class BStatsServers extends BaseJsonService {
}
}
static get examples() {
return [
{
title: 'bStats Servers',
namedParams: {
pluginid: '1',
},
staticPreview: this.render({ servers: 57479 }),
},
]
}
static get defaultBadgeData() {
return {
label: 'servers',
@@ -23,15 +39,10 @@ module.exports = class BStatsServers extends BaseJsonService {
}
}
async handle({ pluginid }) {
const json = await this.fetch({ pluginid })
const { servers } = this.transform({ json })
return this.constructor.render({ servers })
}
transform({ json }) {
const servers = json[0][1]
return { servers }
static render({ servers }) {
return {
message: metric(servers),
}
}
async fetch({ pluginid }) {
@@ -48,24 +59,14 @@ module.exports = class BStatsServers extends BaseJsonService {
})
}
static render({ servers }) {
return {
message: metric(servers),
}
transform({ json }) {
const servers = json[0][1]
return { servers }
}
static get category() {
return 'other'
}
static get examples() {
return [
{
title: 'bStats Servers',
namedParams: {
pluginid: '1',
},
staticPreview: this.render({ servers: 57479 }),
},
]
async handle({ pluginid }) {
const json = await this.fetch({ pluginid })
const { servers } = this.transform({ json })
return this.constructor.render({ servers })
}
}

View File

@@ -52,13 +52,6 @@ module.exports = class Bugzilla extends BaseJsonService {
return { label: 'bugzilla' }
}
async fetch({ bugNumber }) {
return this._requestJson({
schema,
url: `https://bugzilla.mozilla.org/rest/bug/${bugNumber}`,
})
}
static getDisplayStatus({ status, resolution }) {
let displayStatus =
status === 'RESOLVED' ? resolution.toLowerCase() : status.toLowerCase()
@@ -99,6 +92,13 @@ module.exports = class Bugzilla extends BaseJsonService {
}
}
async fetch({ bugNumber }) {
return this._requestJson({
schema,
url: `https://bugzilla.mozilla.org/rest/bug/${bugNumber}`,
})
}
async handle({ bugNumber }) {
const data = await this.fetch({ bugNumber })
return this.constructor.render({

View File

@@ -21,10 +21,6 @@ module.exports = class Buildkite extends BaseJsonService {
}
}
static get defaultBadgeData() {
return { label: 'build' }
}
static get examples() {
return [
{
@@ -47,6 +43,10 @@ module.exports = class Buildkite extends BaseJsonService {
]
}
static get defaultBadgeData() {
return { label: 'build' }
}
async fetch({ identifier, branch }) {
const url = `https://badge.buildkite.com/${identifier}.json`
const options = { qs: { branch } }

View File

@@ -17,13 +17,6 @@ module.exports = class Bundlephobia extends BaseJsonService {
return 'size'
}
static get defaultBadgeData() {
return {
label: 'bundlephobia',
color: 'informational',
}
}
static get route() {
return {
base: 'bundlephobia',
@@ -31,14 +24,6 @@ module.exports = class Bundlephobia extends BaseJsonService {
}
}
static render({ format, size }) {
const label = format === 'min' ? 'minified size' : 'minzipped size'
return {
label,
message: prettyBytes(size),
}
}
static get examples() {
return [
{
@@ -88,6 +73,21 @@ module.exports = class Bundlephobia extends BaseJsonService {
]
}
static get defaultBadgeData() {
return {
label: 'bundlephobia',
color: 'informational',
}
}
static render({ format, size }) {
const label = format === 'min' ? 'minified size' : 'minzipped size'
return {
label,
message: prettyBytes(size),
}
}
async fetch({ scope, packageName, version }) {
const packageQuery = `${scope ? `${scope}/` : ''}${packageName}${
version ? `@${version}` : ''

View File

@@ -10,35 +10,6 @@ const cdnjsSchema = Joi.object({
}).required()
module.exports = class Cdnjs extends BaseJsonService {
async fetch({ library }) {
const url = `https://api.cdnjs.com/libraries/${library}?fields=version`
return this._requestJson({
url,
schema: cdnjsSchema,
})
}
static render({ version }) {
return renderVersionBadge({ version })
}
async handle({ library }) {
const json = await this.fetch({ library })
if (Object.keys(json).length === 0) {
/* Note the 'not found' response from cdnjs is:
status code = 200, body = {} */
throw new NotFound()
}
return this.constructor.render({ version: json.version })
}
// Metadata
static get defaultBadgeData() {
return { label: 'cdnjs' }
}
static get category() {
return 'version'
}
@@ -58,4 +29,32 @@ module.exports = class Cdnjs extends BaseJsonService {
},
]
}
static get defaultBadgeData() {
return { label: 'cdnjs' }
}
static render({ version }) {
return renderVersionBadge({ version })
}
async fetch({ library }) {
const url = `https://api.cdnjs.com/libraries/${library}?fields=version`
return this._requestJson({
url,
schema: cdnjsSchema,
})
}
async handle({ library }) {
const json = await this.fetch({ library })
if (Object.keys(json).length === 0) {
/* Note the 'not found' response from cdnjs is:
status code = 200, body = {} */
throw new NotFound()
}
return this.constructor.render({ version: json.version })
}
}

View File

@@ -25,6 +25,10 @@ module.exports = class ChromeWebStorePrice extends BaseChromeWebStoreService {
]
}
static get defaultBadgeData() {
return { label: 'price' }
}
static render({ priceCurrency, price }) {
return {
message: `${currencyFromCode(priceCurrency) + price}`,
@@ -36,8 +40,4 @@ module.exports = class ChromeWebStorePrice extends BaseChromeWebStoreService {
const { priceCurrency, price } = await this.fetch({ storeId })
return this.constructor.render({ priceCurrency, price })
}
static get defaultBadgeData() {
return { label: 'price' }
}
}

View File

@@ -25,12 +25,12 @@ module.exports = class ChromeWebStoreVersion extends BaseChromeWebStoreService {
]
}
static get defaultBadgeData() {
return { label: 'chrome web store' }
}
async handle({ storeId }) {
const data = await this.fetch({ storeId })
return renderVersionBadge({ version: data.version })
}
static get defaultBadgeData() {
return { label: 'chrome web store' }
}
}

View File

@@ -21,42 +21,6 @@ const documentation = `
`
module.exports = class CircleCi extends BaseJsonService {
async fetch({ token, vcsType, userRepo, branch }) {
let url = `https://circleci.com/api/v1.1/project/${vcsType}/${userRepo}`
if (branch != null) {
url += `/tree/${branch}`
}
const query = { filter: 'completed', limit: 1 }
if (token) {
query['circle-token'] = token
}
return this._requestJson({
url,
schema: circleSchema,
options: { qs: query },
errorMessages: { 404: 'project not found' },
})
}
static render({ status }) {
return renderBuildStatusBadge({ status: status.replace('_', ' ') })
}
async handle({ token, vcsType, userRepo, branch }) {
const json = await this.fetch({
token,
vcsType: vcsType || 'github',
userRepo,
branch,
})
return this.constructor.render({ status: json[0].status })
}
// Metadata
static get defaultBadgeData() {
return { label: 'build' }
}
static get category() {
return 'build'
}
@@ -108,4 +72,39 @@ module.exports = class CircleCi extends BaseJsonService {
},
]
}
static get defaultBadgeData() {
return { label: 'build' }
}
static render({ status }) {
return renderBuildStatusBadge({ status: status.replace('_', ' ') })
}
async fetch({ token, vcsType, userRepo, branch }) {
let url = `https://circleci.com/api/v1.1/project/${vcsType}/${userRepo}`
if (branch != null) {
url += `/tree/${branch}`
}
const query = { filter: 'completed', limit: 1 }
if (token) {
query['circle-token'] = token
}
return this._requestJson({
url,
schema: circleSchema,
options: { qs: query },
errorMessages: { 404: 'project not found' },
})
}
async handle({ token, vcsType, userRepo, branch }) {
const json = await this.fetch({
token,
vcsType: vcsType || 'github',
userRepo,
branch,
})
return this.constructor.render({ status: json[0].status })
}
}

View File

@@ -23,17 +23,6 @@ class BaseClojarsService extends BaseJsonService {
}
class BaseClojarsVersionService extends BaseClojarsService {
static render({ clojar, version }) {
return {
message: `[${clojar} "${version}"]`,
color: versionColor(version),
}
}
static get defaultBadgeData() {
return { label: 'clojars' }
}
static get category() {
return 'version'
}
@@ -46,6 +35,17 @@ class BaseClojarsVersionService extends BaseClojarsService {
},
]
}
static get defaultBadgeData() {
return { label: 'clojars' }
}
static render({ clojar, version }) {
return {
message: `[${clojar} "${version}"]`,
color: versionColor(version),
}
}
}
module.exports = { BaseClojarsService, BaseClojarsVersionService }

View File

@@ -5,23 +5,6 @@ const { downloadCount: downloadsColor } = require('../color-formatters')
const { BaseClojarsService } = require('./clojars-base')
module.exports = class ClojarsDownloads extends BaseClojarsService {
static render({ downloads }) {
return {
label: 'downloads',
message: metric(downloads),
color: downloadsColor(downloads),
}
}
async handle({ clojar }) {
const json = await this.fetch({ clojar })
return this.constructor.render({ downloads: json.downloads })
}
static get defaultBadgeData() {
return { label: 'downloads' }
}
static get category() {
return 'downloads'
}
@@ -41,4 +24,21 @@ module.exports = class ClojarsDownloads extends BaseClojarsService {
},
]
}
static get defaultBadgeData() {
return { label: 'downloads' }
}
static render({ downloads }) {
return {
label: 'downloads',
message: metric(downloads),
color: downloadsColor(downloads),
}
}
async handle({ clojar }) {
const json = await this.fetch({ clojar })
return this.constructor.render({ downloads: json.downloads })
}
}

View File

@@ -3,6 +3,13 @@
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({
@@ -10,11 +17,4 @@ module.exports = class ClojarsVersionRelease extends BaseClojarsVersionService {
version: json.latest_release ? json.latest_release : json.latest_version,
})
}
static get route() {
return {
base: 'clojars/v',
pattern: ':clojar+',
}
}
}

View File

@@ -3,15 +3,15 @@
const { BaseClojarsVersionService } = require('./clojars-base')
module.exports = class ClojarsVersionSnapshot extends BaseClojarsVersionService {
async handle({ clojar }) {
const json = await this.fetch({ clojar })
return this.constructor.render({ clojar, version: json.latest_version })
}
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 })
}
}

View File

@@ -36,11 +36,8 @@ module.exports = class CocoapodsDocs extends BaseJsonService {
]
}
async fetch({ spec }) {
return this._requestJson({
schema,
url: `https://metrics.cocoapods.org/api/v1/pods/${spec}`,
})
static get defaultBadgeData() {
return { label: 'docs' }
}
static render({ percentage }) {
@@ -50,13 +47,16 @@ module.exports = class CocoapodsDocs extends BaseJsonService {
}
}
async fetch({ spec }) {
return this._requestJson({
schema,
url: `https://metrics.cocoapods.org/api/v1/pods/${spec}`,
})
}
async handle({ spec }) {
const data = await this.fetch({ spec })
const percentage = data.cocoadocs.doc_percent || 0
return this.constructor.render({ percentage })
}
static get defaultBadgeData() {
return { label: 'docs' }
}
}

View File

@@ -24,6 +24,10 @@ module.exports = class CocoapodsLicense extends BaseCocoaPodsService {
]
}
static get defaultBadgeData() {
return { label: 'license' }
}
static render({ license }) {
return {
message: license,
@@ -38,8 +42,4 @@ module.exports = class CocoapodsLicense extends BaseCocoaPodsService {
typeof data.license === 'string' ? data.license : data.license.type
return this.constructor.render({ license })
}
static get defaultBadgeData() {
return { label: 'license' }
}
}

View File

@@ -26,6 +26,10 @@ module.exports = class CocoapodsPlatform extends BaseCocoaPodsService {
]
}
static get defaultBadgeData() {
return { label: 'platform' }
}
static render({ platforms }) {
return {
message: platforms.join(' | '),
@@ -38,8 +42,4 @@ module.exports = class CocoapodsPlatform extends BaseCocoaPodsService {
const { platforms } = await this.fetch({ spec })
return this.constructor.render({ platforms: Object.keys(platforms) })
}
static get defaultBadgeData() {
return { label: 'platform' }
}
}

View File

@@ -25,12 +25,12 @@ module.exports = class CocoapodsVersion extends BaseCocoaPodsService {
]
}
static get defaultBadgeData() {
return { label: 'pod' }
}
async handle({ spec }) {
const { version } = await this.fetch({ spec })
return renderVersionBadge({ version })
}
static get defaultBadgeData() {
return { label: 'pod' }
}
}

View File

@@ -88,6 +88,10 @@ const whichMap = {
}
module.exports = class CodeclimateAnalysis extends BaseJsonService {
static get category() {
return 'analysis'
}
static get route() {
return {
base: 'codeclimate',
@@ -96,10 +100,6 @@ module.exports = class CodeclimateAnalysis extends BaseJsonService {
}
}
static get category() {
return 'analysis'
}
static get examples() {
return [
{
@@ -140,6 +140,12 @@ module.exports = class CodeclimateAnalysis extends BaseJsonService {
]
}
static render({ which, ...props }) {
const { render } = whichMap[which]
return render(props)
}
async fetch({ user, repo }) {
const {
id: repoId,
@@ -159,12 +165,6 @@ module.exports = class CodeclimateAnalysis extends BaseJsonService {
return data
}
static render({ which, ...props }) {
const { render } = whichMap[which]
return render(props)
}
async handle({ which, user, repo }) {
const { transform } = whichMap[which]

View File

@@ -17,6 +17,10 @@ const schema = Joi.object({
}).required()
module.exports = class CodeclimateCoverage extends BaseJsonService {
static get category() {
return 'coverage'
}
static get route() {
return {
base: 'codeclimate',
@@ -24,10 +28,6 @@ module.exports = class CodeclimateCoverage extends BaseJsonService {
}
}
static get category() {
return 'coverage'
}
static get examples() {
return [
{
@@ -43,6 +43,20 @@ module.exports = class CodeclimateCoverage extends BaseJsonService {
]
}
static render({ wantLetter, percentage, letter }) {
if (wantLetter) {
return {
message: letter,
color: letterScore(letter),
}
} else {
return {
message: `${percentage.toFixed(0)}%`,
color: coveragePercentage(percentage),
}
}
}
async fetch({ user, repo }) {
const {
id: repoId,
@@ -62,20 +76,6 @@ module.exports = class CodeclimateCoverage extends BaseJsonService {
return data
}
static render({ wantLetter, percentage, letter }) {
if (wantLetter) {
return {
message: letter,
color: letterScore(letter),
}
} else {
return {
message: `${percentage.toFixed(0)}%`,
color: coveragePercentage(percentage),
}
}
}
async handle({ which, user, repo }) {
const {
attributes: {

View File

@@ -37,23 +37,6 @@ module.exports = class Codecov extends BaseJsonService {
return 'coverage'
}
static get defaultBadgeData() {
return { label: 'coverage' }
}
static render({ coverage }) {
if (coverage === 'unknown') {
return {
message: coverage,
color: 'lightgrey',
}
}
return {
message: `${coverage.toFixed(0)}%`,
color: coveragePercentage(coverage),
}
}
static get route() {
return {
base: 'codecov/c',
@@ -100,6 +83,23 @@ module.exports = class Codecov extends BaseJsonService {
]
}
static get defaultBadgeData() {
return { label: 'coverage' }
}
static render({ coverage }) {
if (coverage === 'unknown') {
return {
message: coverage,
color: 'lightgrey',
}
}
return {
message: `${coverage.toFixed(0)}%`,
color: coveragePercentage(coverage),
}
}
async fetch({ vcsName, user, repo, branch, token }) {
// Codecov Docs: https://docs.codecov.io/reference#section-get-a-single-repository
let url = `https://codecov.io/api/${vcsName}/${user}/${repo}`

View File

@@ -31,15 +31,6 @@ module.exports = class Codeship extends BaseSvgScrapingService {
return 'build'
}
static get defaultBadgeData() {
return { label: 'build' }
}
static render({ status }) {
status = statusMap[status] || status
return renderBuildStatusBadge({ status })
}
static get route() {
return {
base: 'codeship',
@@ -69,6 +60,15 @@ module.exports = class Codeship extends BaseSvgScrapingService {
]
}
static get defaultBadgeData() {
return { label: 'build' }
}
static render({ status }) {
status = statusMap[status] || status
return renderBuildStatusBadge({ status })
}
async fetch({ projectId, branch }) {
const url = `https://app.codeship.com/projects/${projectId}/status`
return this._requestSvg({

View File

@@ -13,23 +13,10 @@ const schema = Joi.object({
}).required()
module.exports = class Codetally extends BaseJsonService {
static render({ currency, amount, multiplier }) {
return {
message: `${currency}${amount.toFixed(2)} ${multiplier}`,
}
}
static get category() {
return 'funding'
}
static get defaultBadgeData() {
return {
label: 'codetally',
color: '#2E8B57',
}
}
static get route() {
return {
base: 'codetally',
@@ -54,6 +41,19 @@ module.exports = class Codetally extends BaseJsonService {
]
}
static get defaultBadgeData() {
return {
label: 'codetally',
color: '#2E8B57',
}
}
static render({ currency, amount, multiplier }) {
return {
message: `${currency}${amount.toFixed(2)} ${multiplier}`,
}
}
async handle({ owner, repo }) {
const url = `http://www.codetally.com/formattedshield/${owner}/${repo}`
const json = await this._requestJson({

View File

@@ -18,19 +18,6 @@ module.exports = class ContinuousPhp extends BaseJsonService {
return 'build'
}
static get defaultBadgeData() {
return { label: 'continuousphp' }
}
static render({ status }) {
const badge = renderBuildStatusBadge({ label: 'build', status })
const customColor = statusMap[status]
if (customColor) {
badge.color = customColor
}
return badge
}
static get route() {
return {
base: 'continuousphp',
@@ -64,6 +51,19 @@ module.exports = class ContinuousPhp extends BaseJsonService {
]
}
static get defaultBadgeData() {
return { label: 'continuousphp' }
}
static render({ status }) {
const badge = renderBuildStatusBadge({ label: 'build', status })
const customColor = statusMap[status]
if (customColor) {
badge.color = customColor
}
return badge
}
async fetch({ provider, user, repo, branch }) {
const url = `https://status.continuousphp.com/${provider}/${user}/${repo}/status-info`
return this._requestJson({