Add [pkgreview].dev service (#4660)
* Add pkgreview.dev services * 🐛 FIX: Fix badges for pkgnames containing @ symbol * 🐛 FIX: parseFloat the rating * 🐛 FIX: Fix LGTM alerts Alert: 2 for Incomplete string escaping or encoding * Update services/pkgreview/package-rating.service.js Co-Authored-By: Caleb Cartwright <calebcartwright@users.noreply.github.com> * 🐛 FIX: Rollback to Joi.number() temporarily * 👌 IMPROVE: Follow guidelines properly. Not completely done, yet. * 🐛 FIX: Handle response timed out error * 👌 IMPROVE: Merge star and rating badge logic * 🐛 FIX: Fix according to the maintainer's review * ✅ TEST: Write a test * ✅ TEST: Write one more dummy test * 👌 IMPROVE: Improve message color scheme. Add logic to it. use color-formatters. * ✅ TEST: Complete Test Suitew * 👌 IMPROVE: Make fixes according to the review * ✅ TEST: Write nice tests * ✅ TEST: Fix test regex * 👌 IMPROVE: Do according to the review * ✅ TEST: Fix test regex and don't test Bad Requested Badge * ✅ TEST: Fix tests :) Co-authored-by: Caleb Cartwright <calebcartwright@users.noreply.github.com>
This commit is contained in:
94
services/pkgreview/package-rating.service.js
Normal file
94
services/pkgreview/package-rating.service.js
Normal file
@@ -0,0 +1,94 @@
|
||||
'use strict'
|
||||
|
||||
const Joi = require('@hapi/joi')
|
||||
const { starRating, metric } = require('../text-formatters')
|
||||
const { colorScale } = require('../color-formatters')
|
||||
const { nonNegativeInteger } = require('../validators')
|
||||
const { BaseJsonService } = require('..')
|
||||
|
||||
const pkgReviewColor = colorScale([2, 3, 4])
|
||||
|
||||
const schema = Joi.object({
|
||||
rating: Joi.number()
|
||||
.min(0)
|
||||
.max(1)
|
||||
.precision(1)
|
||||
.required()
|
||||
.allow(null),
|
||||
reviewsCount: nonNegativeInteger,
|
||||
}).required()
|
||||
|
||||
module.exports = class PkgreviewRating extends BaseJsonService {
|
||||
static get category() {
|
||||
return 'rating'
|
||||
}
|
||||
|
||||
static get route() {
|
||||
return {
|
||||
base: 'pkgreview',
|
||||
pattern: ':format(rating|stars)/:pkgManager(npm)/:pkgSlug+',
|
||||
}
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
return [
|
||||
{
|
||||
title: 'pkgreview.dev Package Ratings',
|
||||
pattern: 'rating/:pkgManager/:pkgSlug+',
|
||||
namedParams: { pkgManager: 'npm', pkgSlug: 'react' },
|
||||
staticPreview: this.render({
|
||||
format: 'rating',
|
||||
rating: 3.5,
|
||||
reviewsCount: 237,
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: 'pkgreview.dev Star Ratings',
|
||||
pattern: 'stars/:pkgManager/:pkgSlug+',
|
||||
namedParams: { pkgManager: 'npm', pkgSlug: 'react' },
|
||||
staticPreview: this.render({
|
||||
format: 'stars',
|
||||
rating: 1.5,
|
||||
reviewsCount: 200,
|
||||
}),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static render({ rating, reviewsCount, format }) {
|
||||
const message =
|
||||
format === 'rating'
|
||||
? `${+parseFloat(rating).toFixed(1)}/5 (${metric(reviewsCount)})`
|
||||
: starRating(rating)
|
||||
|
||||
return {
|
||||
message,
|
||||
label: format,
|
||||
color: pkgReviewColor(rating),
|
||||
}
|
||||
}
|
||||
|
||||
async fetch({ pkgManager, pkgSlug }) {
|
||||
return this._requestJson({
|
||||
schema,
|
||||
url: `https://pkgreview.dev/api/v1/${pkgManager}/${encodeURIComponent(
|
||||
pkgSlug
|
||||
)}`,
|
||||
errorMessages: {
|
||||
404: 'package not found',
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
async handle({ format, pkgManager, pkgSlug }) {
|
||||
const { reviewsCount, rating } = await this.fetch({
|
||||
pkgManager,
|
||||
pkgSlug,
|
||||
})
|
||||
return this.constructor.render({
|
||||
reviewsCount,
|
||||
format,
|
||||
rating: rating * 5,
|
||||
})
|
||||
}
|
||||
}
|
||||
24
services/pkgreview/package-rating.tester.js
Normal file
24
services/pkgreview/package-rating.tester.js
Normal file
@@ -0,0 +1,24 @@
|
||||
'use strict'
|
||||
|
||||
const { withRegex, isStarRating } = require('../test-validators')
|
||||
const t = (module.exports = require('../tester').createServiceTester())
|
||||
|
||||
const isRatingWithReviews = withRegex(
|
||||
/^(([0-4](.?([0-9]))?)|5)\/5?\s*\([0-9]*\)$/
|
||||
)
|
||||
|
||||
t.create('Stars Badge renders')
|
||||
.get('/stars/npm/react.json')
|
||||
.expectBadge({ label: 'stars', message: isStarRating })
|
||||
|
||||
t.create('Rating Badge renders')
|
||||
.get('/rating/npm/react.json')
|
||||
.expectBadge({ label: 'rating', message: isRatingWithReviews })
|
||||
|
||||
t.create('nonexistent package')
|
||||
.get('/rating/npm/ohlolweallknowthispackagewontexist.json')
|
||||
.expectBadge({
|
||||
label: 'rating',
|
||||
message: 'package not found',
|
||||
color: 'red',
|
||||
})
|
||||
Reference in New Issue
Block a user