import Joi from 'joi' import { matcher } from 'matcher' import { nonNegativeInteger } from '../validators.js' import { latest } from '../version.js' import { NotFound, queryParams } from '../index.js' import { httpErrorsFor } from './github-helpers.js' const releaseInfoSchema = Joi.object({ assets: Joi.array() .items({ name: Joi.string().required(), download_count: nonNegativeInteger, }) .required(), tag_name: Joi.string().required(), name: Joi.string().allow(null).allow(''), prerelease: Joi.boolean().required(), }).required() // Fetch the 'latest' release as defined by the GitHub API async function fetchLatestGitHubRelease(serviceInstance, { user, repo }) { const commonAttrs = { httpErrors: httpErrorsFor('no releases or repo not found'), } const releaseInfo = await serviceInstance._requestJson({ schema: releaseInfoSchema, url: `/repos/${user}/${repo}/releases/latest`, ...commonAttrs, }) return releaseInfo } const releaseInfoArraySchema = Joi.alternatives().try( Joi.array().items(releaseInfoSchema), Joi.array().length(0), ) async function fetchReleases(serviceInstance, { user, repo }) { const commonAttrs = { httpErrors: httpErrorsFor('repo not found'), } const releases = await serviceInstance._requestJson({ url: `/repos/${user}/${repo}/releases`, schema: releaseInfoArraySchema, ...commonAttrs, options: { searchParams: { per_page: 100 } }, }) return releases } function getLatestRelease({ releases, sort, includePrereleases }) { if (sort === 'semver') { const latestTagName = latest( releases.map(release => release.tag_name), { pre: includePrereleases }, ) return releases.find(({ tag_name: tagName }) => tagName === latestTagName) } if (!includePrereleases) { const stableReleases = releases.filter(release => !release.prerelease) if (stableReleases.length > 0) { return stableReleases[0] } } return releases[0] } const sortEnum = ['date', 'semver'] const queryParamSchema = Joi.object({ include_prereleases: Joi.equal(''), sort: Joi.string() .valid(...sortEnum) .default('date'), filter: Joi.string(), }).required() const filterDocs = `
The filter param can be used to apply a filter to the
project's tag or release names before selecting the latest from the list.
Two constructs are available: * is a wildcard matching zero
or more characters, and if the pattern starts with a !,
the whole pattern is negated.