Skip to content

Commit

Permalink
Add Crates.io recent downloads badge (fixes #4186), run [Crates] (#4187)
Browse files Browse the repository at this point in the history
* Add Crates.io recent downloads badge (fixes #4186)

* Rename extractDownloads to transform

* Fix up the error handling a bit

* Simplify imports
  • Loading branch information
17cupsofcoffee authored and calebcartwright committed Oct 17, 2019
1 parent 7b30731 commit 62bee16
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 25 deletions.
1 change: 1 addition & 0 deletions services/crates/crates-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const keywords = ['Rust']
const crateSchema = Joi.object({
crate: Joi.object({
downloads: nonNegativeInteger,
recent_downloads: nonNegativeInteger,
max_version: Joi.string().required(),
}).required(),
versions: Joi.array()
Expand Down
87 changes: 62 additions & 25 deletions services/crates/crates-downloads.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const { downloadCount: downloadCountColor } = require('../color-formatters')
const { metric } = require('../text-formatters')
const { BaseCratesService, keywords } = require('./crates-base')
const { InvalidParameter, NotFound } = require('..')

module.exports = class CratesDownloads extends BaseCratesService {
static get category() {
Expand All @@ -12,42 +13,64 @@ module.exports = class CratesDownloads extends BaseCratesService {
static get route() {
return {
base: 'crates',
pattern: ':variant(d|dv)/:crate/:version?',
pattern: ':variant(d|dv|dr)/:crate/:version?',
}
}

static get examples() {
return [
{
title: 'Crates.io',
pattern: ':variant(d|dv)/:crate',
namedParams: { variant: 'd', crate: 'rustc-serialize' },
staticPreview: this.render({ downloads: 5000000 }),
pattern: 'd/:crate',
namedParams: {
crate: 'rustc-serialize',
},
staticPreview: this.render({ variant: 'd', downloads: 5000000 }),
keywords,
},
{
title: 'Crates.io',
pattern: ':variant(d|dv)/:crate/:version',
title: 'Crates.io (latest)',
pattern: 'dv/:crate',
namedParams: {
crate: 'rustc-serialize',
},
staticPreview: this.render({ variant: 'dv', downloads: 2000000 }),
keywords,
},
{
title: 'Crates.io (version)',
pattern: 'dv/:crate/:version',
namedParams: {
variant: 'd',
crate: 'rustc-serialize',
version: '0.3.24',
},
staticPreview: this.render({ downloads: 2000000, version: '0.3.24' }),
staticPreview: this.render({
variant: 'dv',
downloads: 2000000,
version: '0.3.24',
}),
keywords,
},
{
title: 'Crates.io (recent)',
pattern: 'dr/:crate',
namedParams: {
crate: 'rustc-serialize',
},
staticPreview: this.render({ variant: 'dr', downloads: 2000000 }),
keywords,
},
]
}

static _getLabel(version, variant) {
if (version) {
return `downloads@${version}`
} else {
if (variant === 'dv') {
return 'downloads@latest'
} else {
return 'downloads'
}
switch (variant) {
case 'dv':
return version ? `downloads@${version}` : 'downloads@latest'
case 'dr':
return 'recent downloads'
default:
return version ? `downloads@${version}` : 'downloads'
}
}

Expand All @@ -59,7 +82,27 @@ module.exports = class CratesDownloads extends BaseCratesService {
}
}

transform({ variant, json }) {
switch (variant) {
case 'dv':
return json.crate ? json.versions[0].downloads : json.version.downloads
case 'dr':
return json.crate.recent_downloads
default:
return json.crate ? json.crate.downloads : json.version.downloads
}
}

async handle({ variant, crate, version }) {
if (variant === 'dr' && version) {
/* crates.io doesn't currently expose
recent download counts for individual
versions */
throw new InvalidParameter({
prettyMessage: 'recent downloads not supported for specific versions',
})
}

const json = await this.fetch({ crate, version })

if (json.errors) {
Expand All @@ -68,17 +111,11 @@ module.exports = class CratesDownloads extends BaseCratesService {
or
https://crates.io/api/v1/crates/libc/0.1.76
returns a 200 OK with an errors object */
return { message: json.errors[0].detail }
throw new NotFound({ prettyMessage: json.errors[0].detail })
}

let downloads
if (variant === 'dv') {
downloads = json.version
? json.version.downloads
: json.versions[0].downloads
} else {
downloads = json.crate ? json.crate.downloads : json.version.downloads
}
const downloads = this.transform({ variant, json })

return this.constructor.render({ variant, downloads, version })
}
}
14 changes: 14 additions & 0 deletions services/crates/crates-downloads.tester.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@ t.create('downloads for version (with version)')
message: isMetric,
})

t.create('recent downloads')
.get('/dr/libc.json')
.expectBadge({
label: 'recent downloads',
message: isMetric,
})

t.create('recent downloads (with version)')
.get('/dr/libc/0.2.31.json')
.expectBadge({
label: 'crates.io',
message: 'recent downloads not supported for specific versions',
})

t.create('downloads (invalid version)')
.get('/d/libc/7.json')
.expectBadge({ label: 'crates.io', message: 'invalid semver: 7' })
Expand Down

0 comments on commit 62bee16

Please sign in to comment.