-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add [npm] badges for collaborator count and dependency version (#2461)
This adds a badge for collaborator count. When evaluating a library, it can be useful to know that there's not a single-contributor bottleneck for publishing. Having more than one collaborator is a sign of library maturity. It adds another badge for dependency version of published dependencies, which solves a similar problem as the node-version badge. I will find this useful for making sure dependencies are up to date in a library.
- Loading branch information
1 parent
38ca6fc
commit a3a5252
Showing
8 changed files
with
303 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
'use strict' | ||
|
||
const NpmBase = require('./npm-base') | ||
|
||
const keywords = ['node'] | ||
|
||
module.exports = class NpmCollaborators extends NpmBase { | ||
static get category() { | ||
return 'activity' | ||
} | ||
|
||
static get route() { | ||
return this.buildRoute('npm/collaborators', { withTag: false }) | ||
} | ||
|
||
static get examples() { | ||
return [ | ||
{ | ||
title: 'npm collaborators', | ||
pattern: ':packageName', | ||
namedParams: { packageName: 'prettier' }, | ||
staticPreview: this.render({ collaborators: 6 }), | ||
keywords, | ||
}, | ||
{ | ||
title: 'npm collaborators', | ||
pattern: ':packageName', | ||
namedParams: { packageName: 'prettier' }, | ||
queryParams: { registry_uri: 'https://registry.npmjs.com' }, | ||
staticPreview: this.render({ collaborators: 6 }), | ||
keywords, | ||
}, | ||
] | ||
} | ||
|
||
static get defaultBadgeData() { | ||
return { | ||
label: 'npm collaborators', | ||
} | ||
} | ||
|
||
static render({ collaborators }) { | ||
let color | ||
if (collaborators > 2) { | ||
color = 'blue' | ||
} else if (collaborators === 2) { | ||
color = 'yellow' | ||
} else { | ||
color = 'red' | ||
} | ||
|
||
return { | ||
message: collaborators, | ||
color, | ||
} | ||
} | ||
|
||
async handle(namedParams, queryParams) { | ||
const { scope, packageName, registryUrl } = this.constructor.unpackParams( | ||
namedParams, | ||
queryParams | ||
) | ||
const { maintainers } = await this.fetchPackageData({ | ||
scope, | ||
packageName, | ||
registryUrl, | ||
}) | ||
const collaborators = maintainers.length | ||
return this.constructor.render({ collaborators }) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
'use strict' | ||
|
||
const Joi = require('joi') | ||
const { nonNegativeInteger } = require('../validators') | ||
const t = (module.exports = require('../create-service-tester')()) | ||
|
||
t.create('gets the contributor count') | ||
.get('/prettier.json') | ||
.expectJSONTypes( | ||
Joi.object({ name: 'npm collaborators', value: nonNegativeInteger }) | ||
) | ||
|
||
t.create('gets the contributor count from a custom registry') | ||
.get('/prettier.json?registry_uri=https://registry.npmjs.com') | ||
.expectJSONTypes( | ||
Joi.object({ name: 'npm collaborators', value: nonNegativeInteger }) | ||
) | ||
|
||
t.create('contributor count for unknown package') | ||
.get('/npm-registry-does-not-have-this-package.json') | ||
.expectJSON({ | ||
name: 'npm collaborators', | ||
value: 'package not found', | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
'use strict' | ||
|
||
const { InvalidParameter } = require('../errors') | ||
const NpmBase = require('./npm-base') | ||
|
||
const keywords = ['node'] | ||
|
||
module.exports = class NpmDependencyVersion extends NpmBase { | ||
static get category() { | ||
return 'platform-support' | ||
} | ||
|
||
static get route() { | ||
const { queryParams } = this.buildRoute('') | ||
return { | ||
base: 'npm/dependency-version', | ||
pattern: ':scope(@[^/]+)?/:packageName/:kind(dev|peer)?/:dependency', | ||
queryParams, | ||
} | ||
} | ||
|
||
static get examples() { | ||
return [ | ||
{ | ||
title: 'npm peer dependency version', | ||
pattern: ':packageName/peer/:dependency', | ||
namedParams: { | ||
packageName: 'react-boxplot', | ||
dependency: 'prop-types', | ||
}, | ||
staticPreview: this.render({ | ||
dependency: 'prop-types', | ||
range: '^15.5.4', | ||
}), | ||
keywords, | ||
}, | ||
{ | ||
title: 'npm dev dependency version', | ||
pattern: ':packageName/dev/:dependency', | ||
namedParams: { | ||
packageName: 'react-boxplot', | ||
kind: 'dev', | ||
dependency: 'eslint-config-standard', | ||
}, | ||
staticPreview: this.render({ | ||
dependency: 'eslint-config-standard', | ||
range: '^12.0.0', | ||
}), | ||
keywords, | ||
}, | ||
{ | ||
title: 'npm (prod) dependency version', | ||
pattern: ':packageName/:dependency', | ||
namedParams: { | ||
packageName: 'react-boxplot', | ||
dependency: 'simple-statistics', | ||
}, | ||
staticPreview: this.render({ | ||
dependency: 'simple-statistics', | ||
range: '^6.1.1', | ||
}), | ||
keywords, | ||
}, | ||
] | ||
} | ||
|
||
static get defaultBadgeData() { | ||
return { | ||
label: 'dependency', | ||
} | ||
} | ||
|
||
static render({ dependency, range }) { | ||
return { | ||
label: dependency, | ||
message: range, | ||
color: 'blue', | ||
} | ||
} | ||
|
||
transform({ | ||
kind, | ||
wantedDependency, | ||
dependencies, | ||
devDependencies, | ||
peerDependencies, | ||
}) { | ||
let dependenciesOfKind | ||
if (kind === 'peer') { | ||
dependenciesOfKind = peerDependencies | ||
} else if (kind === 'dev') { | ||
dependenciesOfKind = devDependencies | ||
} else { | ||
dependenciesOfKind = dependencies | ||
} | ||
|
||
const range = dependenciesOfKind[wantedDependency] | ||
if (range === undefined) { | ||
throw new InvalidParameter({ prettyMessage: 'not found' }) | ||
} | ||
|
||
return { range } | ||
} | ||
|
||
async handle(namedParams, queryParams) { | ||
const { scope, packageName, registryUrl } = this.constructor.unpackParams( | ||
namedParams, | ||
queryParams | ||
) | ||
const { kind, dependency: wantedDependency } = namedParams | ||
|
||
const { | ||
dependencies, | ||
devDependencies, | ||
peerDependencies, | ||
} = await this.fetchPackageData({ | ||
scope, | ||
packageName, | ||
registryUrl, | ||
}) | ||
|
||
const { range } = this.transform({ | ||
kind, | ||
wantedDependency, | ||
dependencies, | ||
devDependencies, | ||
peerDependencies, | ||
}) | ||
|
||
return this.constructor.render({ | ||
dependency: wantedDependency, | ||
range, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
'use strict' | ||
|
||
const Joi = require('joi') | ||
const { semverRange } = require('../validators') | ||
const t = (module.exports = require('../create-service-tester')()) | ||
|
||
t.create('gets the peer dependency version') | ||
.get('/react-boxplot/peer/react.json') | ||
.expectJSONTypes( | ||
Joi.object({ | ||
name: 'react', | ||
value: semverRange, | ||
}) | ||
) | ||
|
||
t.create('gets the dev dependency version') | ||
.get('/react-boxplot/dev/react.json?label=react%20tested') | ||
.expectJSONTypes( | ||
Joi.object({ | ||
name: 'react tested', | ||
value: semverRange, | ||
}) | ||
) | ||
|
||
t.create('gets the dev dependency version (scoped)') | ||
.get('/@metabolize/react-flexbox-svg/dev/eslint.json?') | ||
.expectJSONTypes( | ||
Joi.object({ | ||
name: 'eslint', | ||
value: semverRange, | ||
}) | ||
) | ||
|
||
t.create('gets the prod dependency version') | ||
.get('/react-boxplot/simple-statistics.json') | ||
.expectJSONTypes( | ||
Joi.object({ | ||
name: 'simple-statistics', | ||
value: semverRange, | ||
}) | ||
) | ||
|
||
t.create('unknown dependency') | ||
.get('/react-boxplot/dev/i-made-this-up.json') | ||
.expectJSON({ | ||
name: 'dependency', | ||
value: 'not found', | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters