Files
shields/services/github/github-tag.service.js
chris48s e8a148eed3 migrate examples to openApi part 34; affects [github] (#9865)
* fix github service tests

* migrate some services from examples to openApi

* document latest variant with separate examples

making seperate routes for the /{version} and /latest variants
allows us to only show the docs for
- include_prereleases
- sort and
- filter
in the situation where they are relevant
2024-01-04 20:02:03 +00:00

173 lines
4.3 KiB
JavaScript

import gql from 'graphql-tag'
import Joi from 'joi'
import { matcher } from 'matcher'
import { addv } from '../text-formatters.js'
import { version as versionColor } from '../color-formatters.js'
import { latest } from '../version.js'
import { NotFound, redirector, pathParam } from '../index.js'
import { GithubAuthV4Service } from './github-auth-service.js'
import {
queryParamSchema,
openApiQueryParams,
} from './github-common-release.js'
import { documentation, transformErrors } from './github-helpers.js'
const schema = Joi.object({
data: Joi.object({
repository: Joi.object({
refs: Joi.object({
edges: Joi.array()
.items({
node: Joi.object({
name: Joi.string().required(),
}).required(),
})
.required(),
}).required(),
}).required(),
}).required(),
}).required()
class GithubTag extends GithubAuthV4Service {
static category = 'version'
static route = {
base: 'github/v/tag',
pattern: ':user/:repo',
queryParamSchema,
}
static openApi = {
'/github/v/tag/{user}/{repo}': {
get: {
summary: 'GitHub Tag',
description: documentation,
parameters: [
pathParam({ name: 'user', example: 'expressjs' }),
pathParam({ name: 'repo', example: 'express' }),
...openApiQueryParams,
],
},
},
}
static defaultBadgeData = {
label: 'tag',
}
static render({ version, sort }) {
return {
message: addv(version),
color: sort === 'semver' ? versionColor(version) : 'blue',
}
}
static getLimit({ sort, filter }) {
if (!filter && sort === 'date') {
return 1
}
return 100
}
static applyFilter({ tags, filter }) {
if (!filter) {
return tags
}
return matcher(tags, filter)
}
async fetch({ user, repo, limit }) {
return this._requestGraphql({
query: gql`
query ($user: String!, $repo: String!, $limit: Int!) {
repository(owner: $user, name: $repo) {
refs(
refPrefix: "refs/tags/"
first: $limit
orderBy: { field: TAG_COMMIT_DATE, direction: DESC }
) {
edges {
node {
name
}
}
}
}
}
`,
variables: { user, repo, limit },
schema,
transformErrors,
})
}
static getLatestTag({ tags, sort, includePrereleases }) {
if (sort === 'semver') {
return latest(tags, { pre: includePrereleases })
}
return tags[0]
}
async handle({ user, repo }, queryParams) {
const sort = queryParams.sort
const includePrereleases = queryParams.include_prereleases !== undefined
const filter = queryParams.filter
const limit = this.constructor.getLimit({ sort, filter })
const json = await this.fetch({ user, repo, limit })
const tags = this.constructor.applyFilter({
tags: json.data.repository.refs.edges.map(edge => edge.node.name),
filter,
})
if (tags.length === 0) {
const prettyMessage = filter ? 'no matching tags found' : 'no tags found'
throw new NotFound({ prettyMessage })
}
return this.constructor.render({
version: this.constructor.getLatestTag({
tags,
sort,
includePrereleases,
}),
sort,
})
}
}
const redirects = {
GithubTagRedirect: redirector({
category: 'version',
route: {
base: 'github/tag',
pattern: ':user/:repo',
},
transformPath: ({ user, repo }) => `/github/v/tag/${user}/${repo}`,
transformQueryParams: params => ({ sort: 'semver' }),
dateAdded: new Date('2019-08-17'),
}),
GithubTagPreRedirect: redirector({
category: 'version',
route: {
base: 'github/tag-pre',
pattern: ':user/:repo',
},
transformPath: ({ user, repo }) => `/github/v/tag/${user}/${repo}`,
transformQueryParams: params => ({
sort: 'semver',
include_prereleases: null,
}),
dateAdded: new Date('2019-08-17'),
}),
GithubTagDateRedirect: redirector({
category: 'version',
route: {
base: 'github/tag-date',
pattern: ':user/:repo',
},
transformPath: ({ user, repo }) => `/github/v/tag/${user}/${repo}`,
dateAdded: new Date('2019-08-17'),
}),
}
export { GithubTag, redirects }