Files
shields/services/nuget/nuget-helpers.js
Jakub Fijałkowski 878f4fbcbc Add support for NuGet badges from [nuget feedz] hosting (#5753)
* Add support for Feedz NuGet feeds

* Fix tests & error messages that are used

* Cleanup service and change route according to the conventions

* Change route nomenclature

* Extract `searchServiceUrl`, `stripBuildMetadata` and `selectVersion` to NuGet helpers

* Fix Feedz examples

* Fixup the pattern in Feedz examples

Missed save...

* Use MongoDB.Driver.Core in Feedz examples

* Use standard route pattern instead of `RouteBuilder`

* Extract `transform` function in feedz service

* Add simple test for the `apiUrl` function

* Distinguish repository/package errors

Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2020-11-03 00:52:13 +00:00

114 lines
3.1 KiB
JavaScript

'use strict'
const { promisify } = require('util')
const semver = require('semver')
const { metric, addv } = require('../text-formatters')
const { downloadCount: downloadCountColor } = require('../color-formatters')
const { regularUpdate } = require('../../core/legacy/regular-update')
function renderVersionBadge({ version, feed }) {
let color
if (version.includes('-')) {
color = 'yellow'
} else if (version.startsWith('0')) {
color = 'orange'
} else {
color = 'blue'
}
return {
message: addv(version),
color,
label: feed,
}
}
function renderDownloadBadge({ downloads }) {
return {
message: metric(downloads),
color: downloadCountColor(downloads),
}
}
function odataToObject(odata) {
if (odata === undefined) {
return undefined
}
const result = {}
Object.entries(odata['m:properties']).forEach(([key, value]) => {
const newKey = key.replace(/^d:/, '')
result[newKey] = value
})
return result
}
function randomElementFrom(items) {
const index = Math.floor(Math.random() * items.length)
return items[index]
}
/*
* Hit the service index endpoint and return a {serviceType} URL, chosen
* at random. Cache the responses, but return a different random URL each time.
*/
async function searchServiceUrl(baseUrl, serviceType = 'SearchQueryService') {
// Should we really be caching all these NuGet feeds in memory?
const searchQueryServices = await promisify(regularUpdate)({
url: `${baseUrl}/index.json`,
// The endpoint changes once per year (ie, a period of n = 1 year).
// We minimize the users' waiting time for information.
// With l = latency to fetch the endpoint and x = endpoint update period
// both in years, the yearly number of queries for the endpoint are 1/x,
// and when the endpoint changes, we wait for up to x years to get the
// right endpoint.
// So the waiting time within n years is n*l/x + x years, for which a
// derivation yields an optimum at x = sqrt(n*l), roughly 42 minutes.
intervalMillis: 42 * 60 * 1000,
json: true,
scraper: json =>
json.resources.filter(resource => resource['@type'] === serviceType),
})
return randomElementFrom(searchQueryServices)['@id']
}
/*
* Strip Build MetaData
* Nuget versions may include an optional "build metadata" clause,
* separated from the version by a + character.
*/
function stripBuildMetadata(version) {
return version.split('+')[0]
}
/*
* Select latest version from NuGet feed, filtering-out prerelease versions if needed
*/
function selectVersion(versions, includePrereleases) {
if (includePrereleases) {
return versions.slice(-1).pop()
} else {
const filtered = versions.filter(i => {
if (semver.valid(i)) {
return !semver.prerelease(i)
} else {
return !i.includes('-')
}
})
if (filtered.length > 0) {
return filtered.slice(-1).pop()
} else {
return versions.slice(-1).pop()
}
}
}
module.exports = {
renderVersionBadge,
renderDownloadBadge,
odataToObject,
searchServiceUrl,
stripBuildMetadata,
selectVersion,
}