Compare commits
54 Commits
server-202
...
server-202
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b02a30ac89 | ||
|
|
2588797365 | ||
|
|
4319367c40 | ||
|
|
af19335c5a | ||
|
|
90d2a230ba | ||
|
|
5861f9a4dc | ||
|
|
74c96387b9 | ||
|
|
271dd9c81e | ||
|
|
6041859fae | ||
|
|
1b91ef57c1 | ||
|
|
bc41c409ff | ||
|
|
609775ee25 | ||
|
|
e032f3d4b7 | ||
|
|
560f79df59 | ||
|
|
9c3927ea33 | ||
|
|
5ad1e670b2 | ||
|
|
5dd6014cbc | ||
|
|
085a9baa80 | ||
|
|
2129fe5915 | ||
|
|
c53f15ba9a | ||
|
|
3d115ead27 | ||
|
|
5e35dd1e43 | ||
|
|
c5943c0f2d | ||
|
|
0c18daa278 | ||
|
|
179466ccba | ||
|
|
bd92f99532 | ||
|
|
c1671ec1ae | ||
|
|
632067fc9e | ||
|
|
f739cf66d5 | ||
|
|
ed814132cd | ||
|
|
5fb78c50ef | ||
|
|
5fa3435841 | ||
|
|
7e8b85ecd0 | ||
|
|
dc84d09732 | ||
|
|
4a55c3eaa4 | ||
|
|
bfcbaea116 | ||
|
|
79dd749608 | ||
|
|
57aaaad7fe | ||
|
|
16d0ebbe7b | ||
|
|
086dbe0d16 | ||
|
|
9493d00483 | ||
|
|
a388c6e698 | ||
|
|
95e98d405f | ||
|
|
95cc63bafa | ||
|
|
4e01b1f399 | ||
|
|
2ba3c70c86 | ||
|
|
6966a13144 | ||
|
|
34ef876be5 | ||
|
|
26ae5a0cf4 | ||
|
|
e8a148eed3 | ||
|
|
b1f5aecf36 | ||
|
|
89f5acfc9d | ||
|
|
a7f2396202 | ||
|
|
09c83d9d46 |
@@ -10,4 +10,4 @@ jobs:
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@v4
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@v3
|
||||
uses: actions/dependency-review-action@v4
|
||||
|
||||
2
.github/workflows/test-e2e.yml
vendored
2
.github/workflows/test-e2e.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
|
||||
- name: Cache Cypress binary
|
||||
id: cache-cypress
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
env:
|
||||
cache-name: cache-cypress
|
||||
with:
|
||||
|
||||
13
CHANGELOG.md
13
CHANGELOG.md
@@ -4,6 +4,19 @@ Note: this changelog is for the shields.io server. The changelog for the badge-m
|
||||
|
||||
---
|
||||
|
||||
## server-2024-02-01
|
||||
|
||||
- feat: added up_message and down_message to [uptimerobotstatus] [#9662](https://github.com/badges/shields/issues/9662)
|
||||
- Add [Hangar] Badges [#9800](https://github.com/badges/shields/issues/9800)
|
||||
- sort categories by title (except core) [#9888](https://github.com/badges/shields/issues/9888)
|
||||
- Add Support for [Nostr] Followers [#9870](https://github.com/badges/shields/issues/9870)
|
||||
- [thunderstore] replace experimental API usage with newly available v1 API [#9886](https://github.com/badges/shields/issues/9886)
|
||||
- Update [Gitea] defaults to gitea.com [#9872](https://github.com/badges/shields/issues/9872)
|
||||
- [crates] MSRV Badge [#9871](https://github.com/badges/shields/issues/9871)
|
||||
- Add [galaxytoolshed] Version [#8249](https://github.com/badges/shields/issues/8249)
|
||||
- fix default style docs for social badges [#9869](https://github.com/badges/shields/issues/9869)
|
||||
- Dependency updates
|
||||
|
||||
## server-2024-01-01
|
||||
|
||||
The most important changes in this release for users hosting their own instance are:
|
||||
|
||||
@@ -109,7 +109,7 @@ When server source files change, the badge server should automatically restart
|
||||
itself (using [nodemon][]). When the frontend files change, the frontend dev
|
||||
server (`docusaurus start`) should also automatically reload. However the badge
|
||||
definitions are built only before the server first starts. To regenerate those,
|
||||
either run `npm run defs` or manually restart the server.
|
||||
either run `npm run prestart` or manually restart the server.
|
||||
|
||||
To debug a badge from the command line, run `npm run badge -- /npm/v/nock`.
|
||||
It also works with full URLs like
|
||||
|
||||
@@ -198,7 +198,13 @@ function addGlobalProperties(endpoints) {
|
||||
return paths
|
||||
}
|
||||
|
||||
function services2openapi(services) {
|
||||
function sortPaths(obj) {
|
||||
const entries = Object.entries(obj)
|
||||
entries.sort((a, b) => a[1].get.summary.localeCompare(b[1].get.summary))
|
||||
return Object.fromEntries(entries)
|
||||
}
|
||||
|
||||
function services2openapi(services, sort) {
|
||||
const paths = {}
|
||||
for (const service of services) {
|
||||
if (service.openApi) {
|
||||
@@ -221,10 +227,10 @@ function services2openapi(services) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return paths
|
||||
return sort ? sortPaths(paths) : paths
|
||||
}
|
||||
|
||||
function category2openapi(category, services) {
|
||||
function category2openapi({ category, services, sort = false }) {
|
||||
const spec = {
|
||||
openapi: '3.0.0',
|
||||
info: {
|
||||
@@ -241,7 +247,9 @@ function category2openapi(category, services) {
|
||||
name: 'style',
|
||||
in: 'query',
|
||||
required: false,
|
||||
description: 'If not specified, the defautl style is "flat".',
|
||||
description: `If not specified, the default style for this badge is "${
|
||||
category.name.toLowerCase() === 'social' ? 'social' : 'flat'
|
||||
}".`,
|
||||
schema: {
|
||||
type: 'string',
|
||||
enum: ['flat', 'flat-square', 'plastic', 'for-the-badge', 'social'],
|
||||
@@ -332,7 +340,7 @@ function category2openapi(category, services) {
|
||||
},
|
||||
},
|
||||
},
|
||||
paths: services2openapi(services),
|
||||
paths: services2openapi(services, sort),
|
||||
}
|
||||
|
||||
return spec
|
||||
|
||||
@@ -88,7 +88,8 @@ const expected = {
|
||||
name: 'style',
|
||||
in: 'query',
|
||||
required: false,
|
||||
description: 'If not specified, the defautl style is "flat".',
|
||||
description:
|
||||
'If not specified, the default style for this badge is "flat".',
|
||||
schema: {
|
||||
enum: ['flat', 'flat-square', 'plastic', 'for-the-badge', 'social'],
|
||||
type: 'string',
|
||||
@@ -376,10 +377,13 @@ describe('category2openapi', function () {
|
||||
it('generates an Open API spec', function () {
|
||||
expect(
|
||||
clean(
|
||||
category2openapi({ name: 'build' }, [
|
||||
OpenApiService.getDefinition(),
|
||||
LegacyService.getDefinition(),
|
||||
]),
|
||||
category2openapi({
|
||||
category: { name: 'build' },
|
||||
services: [
|
||||
OpenApiService.getDefinition(),
|
||||
LegacyService.getDefinition(),
|
||||
],
|
||||
}),
|
||||
),
|
||||
).to.deep.equal(expected)
|
||||
})
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
import { isValidCategory } from './categories.js'
|
||||
import { MetricHelper } from './metric-helper.js'
|
||||
import { isValidRoute, prepareRoute, namedParamsForMatch } from './route.js'
|
||||
import { openApiSchema } from './service-definitions.js'
|
||||
import trace from './trace.js'
|
||||
|
||||
const attrSchema = Joi.object({
|
||||
@@ -18,6 +19,7 @@ const attrSchema = Joi.object({
|
||||
isDeprecated: Joi.boolean().default(true),
|
||||
route: isValidRoute,
|
||||
examples: Joi.array().has(Joi.object()).default([]),
|
||||
openApi: openApiSchema,
|
||||
transformPath: Joi.func()
|
||||
.maxArity(1)
|
||||
.required()
|
||||
@@ -37,6 +39,7 @@ export default function redirector(attrs) {
|
||||
isDeprecated,
|
||||
route,
|
||||
examples,
|
||||
openApi,
|
||||
transformPath,
|
||||
transformQueryParams,
|
||||
overrideTransformedQueryParams,
|
||||
@@ -53,6 +56,7 @@ export default function redirector(attrs) {
|
||||
static isDeprecated = isDeprecated
|
||||
static route = route
|
||||
static examples = examples
|
||||
static openApi = openApi
|
||||
|
||||
static register({ camp, metricInstance }, { rasterUrl }) {
|
||||
const { regex, captureNames } = prepareRoute({
|
||||
|
||||
@@ -6,6 +6,33 @@ const objectOfKeyValues = Joi.object()
|
||||
.pattern(/./, Joi.string().allow(null))
|
||||
.required()
|
||||
|
||||
const openApiSchema = Joi.object().pattern(
|
||||
/./,
|
||||
Joi.object({
|
||||
get: Joi.object({
|
||||
summary: Joi.string().required(),
|
||||
description: Joi.string(),
|
||||
parameters: Joi.array()
|
||||
.items(
|
||||
Joi.object({
|
||||
name: Joi.string().required(),
|
||||
description: Joi.string(),
|
||||
in: Joi.string().valid('query', 'path').required(),
|
||||
required: Joi.boolean().required(),
|
||||
schema: Joi.object({
|
||||
type: Joi.string().required(),
|
||||
enum: Joi.array(),
|
||||
}).required(),
|
||||
allowEmptyValue: Joi.boolean(),
|
||||
example: Joi.string().allow(null),
|
||||
}),
|
||||
)
|
||||
.min(1)
|
||||
.required(),
|
||||
}).required(),
|
||||
}).required(),
|
||||
)
|
||||
|
||||
const serviceDefinition = Joi.object({
|
||||
category: Joi.string().required(),
|
||||
name: Joi.string().required(),
|
||||
@@ -43,32 +70,7 @@ const serviceDefinition = Joi.object({
|
||||
}),
|
||||
)
|
||||
.default([]),
|
||||
openApi: Joi.object().pattern(
|
||||
/./,
|
||||
Joi.object({
|
||||
get: Joi.object({
|
||||
summary: Joi.string().required(),
|
||||
description: Joi.string(),
|
||||
parameters: Joi.array()
|
||||
.items(
|
||||
Joi.object({
|
||||
name: Joi.string().required(),
|
||||
description: Joi.string(),
|
||||
in: Joi.string().valid('query', 'path').required(),
|
||||
required: Joi.boolean().required(),
|
||||
schema: Joi.object({
|
||||
type: Joi.string().required(),
|
||||
enum: Joi.array(),
|
||||
}).required(),
|
||||
allowEmptyValue: Joi.boolean(),
|
||||
example: Joi.string().allow(null),
|
||||
}),
|
||||
)
|
||||
.min(1)
|
||||
.required(),
|
||||
}).required(),
|
||||
}).required(),
|
||||
),
|
||||
openApi: openApiSchema,
|
||||
}).required()
|
||||
|
||||
function assertValidServiceDefinition(service, message = undefined) {
|
||||
@@ -93,4 +95,8 @@ function assertValidServiceDefinitionExport(examples, message = undefined) {
|
||||
Joi.assert(examples, serviceDefinitionExport, message)
|
||||
}
|
||||
|
||||
export { assertValidServiceDefinition, assertValidServiceDefinitionExport }
|
||||
export {
|
||||
assertValidServiceDefinition,
|
||||
assertValidServiceDefinitionExport,
|
||||
openApiSchema,
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ describe('Frontend', function () {
|
||||
cy.contains('Build')
|
||||
cy.contains('Chat').click()
|
||||
|
||||
cy.contains('Discourse status')
|
||||
cy.contains('Discourse Status')
|
||||
cy.contains('Stack Exchange questions')
|
||||
})
|
||||
|
||||
|
||||
21
frontend/blog/2024-01-13-simpleicons11.md
Normal file
21
frontend/blog/2024-01-13-simpleicons11.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
slug: simple-icons-11
|
||||
title: Simple Icons 11
|
||||
authors:
|
||||
name: chris48s
|
||||
title: Shields.io Core Team
|
||||
url: https://github.com/chris48s
|
||||
image_url: https://avatars.githubusercontent.com/u/6025893
|
||||
tags: []
|
||||
---
|
||||
|
||||
Logos on Shields.io are provided by SimpleIcons. We've recently upgraded to SimpleIcons 11. This release removes the following 4 icons:
|
||||
|
||||
- Babylon.js
|
||||
- Hulu
|
||||
- Pepsi
|
||||
- Uno
|
||||
|
||||
More details can be found in the [release notes](https://github.com/simple-icons/simple-icons/releases/tag/11.0.0).
|
||||
|
||||
Please remember that we are just consumers of SimpleIcons. Decisions about changes and removals are made by the [SimpleIcons](https://github.com/simple-icons/simple-icons) project.
|
||||
393
package-lock.json
generated
393
package-lock.json
generated
@@ -11,7 +11,7 @@
|
||||
"dependencies": {
|
||||
"@renovatebot/pep440": "^3.0.17",
|
||||
"@renovatebot/ruby-semver": "^3.0.22",
|
||||
"@sentry/node": "^7.91.0",
|
||||
"@sentry/node": "^7.98.0",
|
||||
"@shields_io/camp": "^18.1.2",
|
||||
"@xmldom/xmldom": "0.8.10",
|
||||
"badge-maker": "file:badge-maker",
|
||||
@@ -20,19 +20,19 @@
|
||||
"chalk": "^5.3.0",
|
||||
"check-node-version": "^4.2.1",
|
||||
"cloudflare-middleware": "^1.0.4",
|
||||
"config": "^3.3.9",
|
||||
"config": "^3.3.10",
|
||||
"cross-env": "^7.0.3",
|
||||
"dayjs": "^1.11.10",
|
||||
"decamelize": "^3.2.0",
|
||||
"emojic": "^1.1.17",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"fast-xml-parser": "^4.3.2",
|
||||
"fast-xml-parser": "^4.3.3",
|
||||
"glob": "^10.3.10",
|
||||
"global-agent": "^3.0.0",
|
||||
"got": "^14.0.0",
|
||||
"graphql": "16.8.1",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"joi": "17.11.0",
|
||||
"joi": "17.12.0",
|
||||
"joi-extension-semver": "5.0.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsonpath": "~1.1.1",
|
||||
@@ -51,8 +51,8 @@
|
||||
"qs": "^6.11.2",
|
||||
"query-string": "^8.1.0",
|
||||
"semver": "~7.5.4",
|
||||
"simple-icons": "10.4.0",
|
||||
"smol-toml": "1.1.3",
|
||||
"simple-icons": "11.2.0",
|
||||
"smol-toml": "1.1.4",
|
||||
"webextension-store-meta": "^1.0.5",
|
||||
"xpath": "~0.0.34"
|
||||
},
|
||||
@@ -60,17 +60,17 @@
|
||||
"@docusaurus/core": "^2.4.3",
|
||||
"@easyops-cn/docusaurus-search-local": "^0.40.1",
|
||||
"@mdx-js/react": "^1.6.21",
|
||||
"@typescript-eslint/parser": "^6.16.0",
|
||||
"c8": "^8.0.1",
|
||||
"@typescript-eslint/parser": "^6.19.1",
|
||||
"c8": "^9.1.0",
|
||||
"caller": "^1.1.0",
|
||||
"chai": "^4.3.10",
|
||||
"chai": "^4.4.1",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"chai-datetime": "^1.8.0",
|
||||
"chai-string": "^1.4.0",
|
||||
"child-process-promise": "^2.2.1",
|
||||
"clsx": "^2.0.0",
|
||||
"clsx": "^2.1.0",
|
||||
"concurrently": "^8.2.2",
|
||||
"cypress": "^13.6.2",
|
||||
"cypress": "^13.6.3",
|
||||
"cypress-wait-for-stable-dom": "^0.1.0",
|
||||
"danger": "^11.3.1",
|
||||
"deepmerge": "^4.3.1",
|
||||
@@ -80,11 +80,11 @@
|
||||
"eslint-config-standard": "17.1.0",
|
||||
"eslint-config-standard-jsx": "11.0.0",
|
||||
"eslint-config-standard-react": "13.0.0",
|
||||
"eslint-plugin-chai-friendly": "^0.7.2",
|
||||
"eslint-plugin-chai-friendly": "^0.7.4",
|
||||
"eslint-plugin-cypress": "^2.15.1",
|
||||
"eslint-plugin-icedfrisby": "^0.1.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jsdoc": "^46.9.1",
|
||||
"eslint-plugin-jsdoc": "^48.0.4",
|
||||
"eslint-plugin-mocha": "^10.2.0",
|
||||
"eslint-plugin-no-extension-in-require": "^0.2.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
@@ -104,13 +104,13 @@
|
||||
"mocha-env-reporter": "^4.0.0",
|
||||
"mocha-junit-reporter": "^2.2.1",
|
||||
"mocha-yaml-loader": "^1.0.3",
|
||||
"nock": "13.4.0",
|
||||
"node-mocks-http": "^1.14.0",
|
||||
"nodemon": "^3.0.2",
|
||||
"nock": "13.5.0",
|
||||
"node-mocks-http": "^1.14.1",
|
||||
"nodemon": "^3.0.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"open-cli": "^8.0.0",
|
||||
"portfinder": "^1.0.32",
|
||||
"prettier": "3.1.1",
|
||||
"prettier": "3.2.4",
|
||||
"prism-react-renderer": "^2.3.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
@@ -122,7 +122,7 @@
|
||||
"sinon-chai": "^3.7.0",
|
||||
"snap-shot-it": "^7.9.10",
|
||||
"start-server-and-test": "2.0.3",
|
||||
"tsd": "^0.30.1",
|
||||
"tsd": "^0.30.4",
|
||||
"url": "^0.11.3"
|
||||
},
|
||||
"engines": {
|
||||
@@ -4678,59 +4678,58 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/tracing": {
|
||||
"version": "7.91.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.91.0.tgz",
|
||||
"integrity": "sha512-JH5y6gs6BS0its7WF2DhySu7nkhPDfZcdpAXldxzIlJpqFkuwQKLU5nkYJpiIyZz1NHYYtW5aum2bV2oCOdDRA==",
|
||||
"version": "7.98.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.98.0.tgz",
|
||||
"integrity": "sha512-FnhD2uMLIAJvv4XsYPv3qsTTtxrImyLxiZacudJyaWFhxoeVQ8bKKbWJ/Ar68FAwqTtjXMeY5evnEBbRMcQlaA==",
|
||||
"dependencies": {
|
||||
"@sentry/core": "7.91.0",
|
||||
"@sentry/types": "7.91.0",
|
||||
"@sentry/utils": "7.91.0"
|
||||
"@sentry/core": "7.98.0",
|
||||
"@sentry/types": "7.98.0",
|
||||
"@sentry/utils": "7.98.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "7.91.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.91.0.tgz",
|
||||
"integrity": "sha512-tu+gYq4JrTdrR+YSh5IVHF0fJi/Pi9y0HZ5H9HnYy+UMcXIotxf6hIEaC6ZKGeLWkGXffz2gKpQLe/g6vy/lPA==",
|
||||
"version": "7.98.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.98.0.tgz",
|
||||
"integrity": "sha512-baRUcpCNGyk7cApQHMfqEZJkXdvAKK+z/dVWiMqWc5T5uhzMnPE8/gjP1JZsMtJSQ8g5nHimBdI5TwOyZtxPaA==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "7.91.0",
|
||||
"@sentry/utils": "7.91.0"
|
||||
"@sentry/types": "7.98.0",
|
||||
"@sentry/utils": "7.98.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/node": {
|
||||
"version": "7.91.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.91.0.tgz",
|
||||
"integrity": "sha512-hTIfSQxD7L+AKIqyjoq8CWBRkEQrrMZmA3GSZgPI5JFWBHgO0HBo5TH/8TU81oEJh6kqqHAl2ObMhmcnaFqlzg==",
|
||||
"version": "7.98.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.98.0.tgz",
|
||||
"integrity": "sha512-9cHW217DnU9wC4iR+QxmY3q59N1Touh23hPMDtpMRmbRHSgrmLMoHTVPhK9zHsXRs0mUeidmMqY1ubAWauQByw==",
|
||||
"dependencies": {
|
||||
"@sentry-internal/tracing": "7.91.0",
|
||||
"@sentry/core": "7.91.0",
|
||||
"@sentry/types": "7.91.0",
|
||||
"@sentry/utils": "7.91.0",
|
||||
"https-proxy-agent": "^5.0.0"
|
||||
"@sentry-internal/tracing": "7.98.0",
|
||||
"@sentry/core": "7.98.0",
|
||||
"@sentry/types": "7.98.0",
|
||||
"@sentry/utils": "7.98.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/types": {
|
||||
"version": "7.91.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.91.0.tgz",
|
||||
"integrity": "sha512-bcQnb7J3P3equbCUc+sPuHog2Y47yGD2sCkzmnZBjvBT0Z1B4f36fI/5WjyZhTjLSiOdg3F2otwvikbMjmBDew==",
|
||||
"version": "7.98.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.98.0.tgz",
|
||||
"integrity": "sha512-pc034ziM0VTETue4bfBcBqTWGy4w0okidtoZJjGVrYAfE95ObZnUGVj/XYIQ3FeCYWIa7NFN2MvdsCS0buwivQ==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/utils": {
|
||||
"version": "7.91.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.91.0.tgz",
|
||||
"integrity": "sha512-fvxjrEbk6T6Otu++Ax9ntlQ0sGRiwSC179w68aC3u26Wr30FAIRKqHTCCdc2jyWk7Gd9uWRT/cq+g8NG/8BfSg==",
|
||||
"version": "7.98.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.98.0.tgz",
|
||||
"integrity": "sha512-0/LY+kpHxItVRY0xPDXPXVsKRb95cXsGSQf8sVMtfSjz++0bLL1U4k7PFz1c5s2/Vk0B8hS6duRrgMv6dMIZDw==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "7.91.0"
|
||||
"@sentry/types": "7.98.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -5237,9 +5236,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/express": {
|
||||
"version": "4.17.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz",
|
||||
"integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==",
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
|
||||
"integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/body-parser": "*",
|
||||
@@ -5626,15 +5625,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "6.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.16.0.tgz",
|
||||
"integrity": "sha512-H2GM3eUo12HpKZU9njig3DF5zJ58ja6ahj1GoHEHOgQvYxzoFJJEvC1MQ7T2l9Ha+69ZSOn7RTxOdpC/y3ikMw==",
|
||||
"version": "6.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.1.tgz",
|
||||
"integrity": "sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "6.16.0",
|
||||
"@typescript-eslint/types": "6.16.0",
|
||||
"@typescript-eslint/typescript-estree": "6.16.0",
|
||||
"@typescript-eslint/visitor-keys": "6.16.0",
|
||||
"@typescript-eslint/scope-manager": "6.19.1",
|
||||
"@typescript-eslint/types": "6.19.1",
|
||||
"@typescript-eslint/typescript-estree": "6.19.1",
|
||||
"@typescript-eslint/visitor-keys": "6.19.1",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -5654,13 +5653,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "6.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz",
|
||||
"integrity": "sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw==",
|
||||
"version": "6.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz",
|
||||
"integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.16.0",
|
||||
"@typescript-eslint/visitor-keys": "6.16.0"
|
||||
"@typescript-eslint/types": "6.19.1",
|
||||
"@typescript-eslint/visitor-keys": "6.19.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
@@ -5671,9 +5670,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "6.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.16.0.tgz",
|
||||
"integrity": "sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ==",
|
||||
"version": "6.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz",
|
||||
"integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^16.0.0 || >=18.0.0"
|
||||
@@ -5684,13 +5683,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "6.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz",
|
||||
"integrity": "sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA==",
|
||||
"version": "6.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz",
|
||||
"integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.16.0",
|
||||
"@typescript-eslint/visitor-keys": "6.16.0",
|
||||
"@typescript-eslint/types": "6.19.1",
|
||||
"@typescript-eslint/visitor-keys": "6.19.1",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
@@ -5736,12 +5735,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "6.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz",
|
||||
"integrity": "sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A==",
|
||||
"version": "6.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz",
|
||||
"integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "6.16.0",
|
||||
"@typescript-eslint/types": "6.19.1",
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -5990,6 +5989,7 @@
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
@@ -7193,19 +7193,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/c8": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/c8/-/c8-8.0.1.tgz",
|
||||
"integrity": "sha512-EINpopxZNH1mETuI0DzRA4MZpAUH+IFiRhnmFD3vFr3vdrgxqi3VfE3KL0AIL+zDq8rC9bZqwM/VDmmoe04y7w==",
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/c8/-/c8-9.1.0.tgz",
|
||||
"integrity": "sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@bcoe/v8-coverage": "^0.2.3",
|
||||
"@istanbuljs/schema": "^0.1.3",
|
||||
"find-up": "^5.0.0",
|
||||
"foreground-child": "^2.0.0",
|
||||
"foreground-child": "^3.1.1",
|
||||
"istanbul-lib-coverage": "^3.2.0",
|
||||
"istanbul-lib-report": "^3.0.1",
|
||||
"istanbul-reports": "^3.1.6",
|
||||
"rimraf": "^3.0.2",
|
||||
"test-exclude": "^6.0.0",
|
||||
"v8-to-istanbul": "^9.0.0",
|
||||
"yargs": "^17.7.2",
|
||||
@@ -7215,7 +7214,7 @@
|
||||
"c8": "bin/c8.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
"node": ">=14.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/c8/node_modules/ansi-styles": {
|
||||
@@ -7271,26 +7270,6 @@
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/c8/node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/c8/node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
@@ -7300,21 +7279,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/c8/node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/c8/node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
@@ -7545,9 +7509,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chai": {
|
||||
"version": "4.3.10",
|
||||
"resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz",
|
||||
"integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==",
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz",
|
||||
"integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==",
|
||||
"dependencies": {
|
||||
"assertion-error": "^1.1.0",
|
||||
"check-error": "^1.0.3",
|
||||
@@ -8172,9 +8136,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz",
|
||||
"integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz",
|
||||
"integrity": "sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
@@ -8547,9 +8511,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/config": {
|
||||
"version": "3.3.9",
|
||||
"resolved": "https://registry.npmjs.org/config/-/config-3.3.9.tgz",
|
||||
"integrity": "sha512-G17nfe+cY7kR0wVpc49NCYvNtelm/pPy8czHoFkAgtV1lkmcp7DHtWCdDu+C9Z7gb2WVqa9Tm3uF9aKaPbCfhg==",
|
||||
"version": "3.3.10",
|
||||
"resolved": "https://registry.npmjs.org/config/-/config-3.3.10.tgz",
|
||||
"integrity": "sha512-9Kl3LpQ6zj93KaqgfIMTcpwTpgozFOqNl/Dk7mjras1BgGIOlqxWkyIGeU1my+sRuskRYwrCATgCk1RjAnRPGA==",
|
||||
"dependencies": {
|
||||
"json5": "^2.2.3"
|
||||
},
|
||||
@@ -9305,15 +9269,14 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cypress": {
|
||||
"version": "13.6.2",
|
||||
"resolved": "https://registry.npmjs.org/cypress/-/cypress-13.6.2.tgz",
|
||||
"integrity": "sha512-TW3bGdPU4BrfvMQYv1z3oMqj71YI4AlgJgnrycicmPZAXtvywVFZW9DAToshO65D97rCWfG/kqMFsYB6Kp91gQ==",
|
||||
"version": "13.6.3",
|
||||
"resolved": "https://registry.npmjs.org/cypress/-/cypress-13.6.3.tgz",
|
||||
"integrity": "sha512-d/pZvgwjAyZsoyJ3FOsJT5lDsqnxQ/clMqnNc++rkHjbkkiF2h9s0JsZSyyH4QXhVFW3zPFg82jD25roFLOdZA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@cypress/request": "^3.0.0",
|
||||
"@cypress/xvfb": "^1.2.4",
|
||||
"@types/node": "^18.17.5",
|
||||
"@types/sinonjs__fake-timers": "8.1.1",
|
||||
"@types/sizzle": "^2.3.2",
|
||||
"arch": "^2.2.0",
|
||||
@@ -11335,9 +11298,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-chai-friendly": {
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-chai-friendly/-/eslint-plugin-chai-friendly-0.7.2.tgz",
|
||||
"integrity": "sha512-LOIfGx5sZZ5FwM1shr2GlYAWV9Omdi+1/3byuVagvQNoGUuU0iHhp7AfjA1uR+4dJ4Isfb4+FwBJgQajIw9iAg==",
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-chai-friendly/-/eslint-plugin-chai-friendly-0.7.4.tgz",
|
||||
"integrity": "sha512-PGPjJ8diYgX1mjLxGJqRop2rrGwZRKImoEOwUOgoIhg0p80MkTaqvmFLe5TF7/iagZHggasvIfQlUyHIhK/PYg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@@ -11501,9 +11464,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-jsdoc": {
|
||||
"version": "46.9.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.9.1.tgz",
|
||||
"integrity": "sha512-11Ox5LCl2wY7gGkp9UOyew70o9qvii1daAH+h/MFobRVRNcy7sVlH+jm0HQdgcvcru6285GvpjpUyoa051j03Q==",
|
||||
"version": "48.0.4",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.0.4.tgz",
|
||||
"integrity": "sha512-A0cH+5svWPXzGZszBjXA1t0aAqVGS+/x3i02KFmb73rU0iMLnadEcVWcD/dGBZHIfAMKr3YpWh58f6wn4N909w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@es-joy/jsdoccomment": "~0.41.0",
|
||||
@@ -11517,10 +11480,10 @@
|
||||
"spdx-expression-parse": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^7.0.0 || ^8.0.0"
|
||||
"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-jsdoc/node_modules/spdx-expression-parse": {
|
||||
@@ -12385,9 +12348,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fast-xml-parser": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.2.tgz",
|
||||
"integrity": "sha512-rmrXUXwbJedoXkStenj1kkljNF7ugn5ZjR9FJcwmCfcCbtOMDghPajbc+Tck6vE6F5XsDmx+Pr2le9fw8+pXBg==",
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.3.tgz",
|
||||
"integrity": "sha512-coV/D1MhrShMvU6D0I+VAK3umz6hUaxxhL0yp/9RjfiYUfAv14rDhGQL+PLForhMdr0wq3PiV07WtkkNjJjNHg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -12758,9 +12721,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
||||
"version": "1.15.4",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
|
||||
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -12787,23 +12750,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/foreground-child": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
|
||||
"integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==",
|
||||
"dev": true,
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
|
||||
"integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.0",
|
||||
"signal-exit": "^3.0.2"
|
||||
"signal-exit": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/foreground-child/node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
@@ -12813,11 +12777,21 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/foreground-child/node_modules/signal-exit": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
||||
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/foreground-child/node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
@@ -13349,34 +13323,6 @@
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
"which": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/foreground-child": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
|
||||
"integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.0",
|
||||
"signal-exit": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/minimatch": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz",
|
||||
@@ -13391,31 +13337,6 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/signal-exit": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz",
|
||||
"integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"node-which": "bin/node-which"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/global-agent": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz",
|
||||
@@ -14329,6 +14250,7 @@
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
@@ -15651,13 +15573,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/joi": {
|
||||
"version": "17.11.0",
|
||||
"resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz",
|
||||
"integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==",
|
||||
"version": "17.12.0",
|
||||
"resolved": "https://registry.npmjs.org/joi/-/joi-17.12.0.tgz",
|
||||
"integrity": "sha512-HSLsmSmXz+PV9PYoi3p7cgIbj06WnEBNT28n+bbBNcPZXZFqCzzvGqpTBPujx/Z0nh1+KNQPDrNgdmQ8dq0qYw==",
|
||||
"dependencies": {
|
||||
"@hapi/hoek": "^9.0.0",
|
||||
"@hapi/topo": "^5.0.0",
|
||||
"@sideway/address": "^4.1.3",
|
||||
"@hapi/hoek": "^9.3.0",
|
||||
"@hapi/topo": "^5.1.0",
|
||||
"@sideway/address": "^4.1.4",
|
||||
"@sideway/formula": "^3.0.1",
|
||||
"@sideway/pinpoint": "^2.0.0"
|
||||
}
|
||||
@@ -18199,9 +18121,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/nock": {
|
||||
"version": "13.4.0",
|
||||
"resolved": "https://registry.npmjs.org/nock/-/nock-13.4.0.tgz",
|
||||
"integrity": "sha512-W8NVHjO/LCTNA64yxAPHV/K47LpGYcVzgKd3Q0n6owhwvD0Dgoterc25R4rnZbckJEb6Loxz1f5QMuJpJnbSyQ==",
|
||||
"version": "13.5.0",
|
||||
"resolved": "https://registry.npmjs.org/nock/-/nock-13.5.0.tgz",
|
||||
"integrity": "sha512-9hc1eCS2HtOz+sE9W7JQw/tXJktg0zoPSu48s/pYe73e25JW9ywiowbqnUSd7iZPeVawLcVpPZeZS312fwSY+g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"debug": "^4.1.0",
|
||||
@@ -18279,11 +18201,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/node-mocks-http": {
|
||||
"version": "1.14.0",
|
||||
"resolved": "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.14.0.tgz",
|
||||
"integrity": "sha512-yOb3zNr9/5N27TAWxxMlrvWp4nNfRcrC0dAiqyj5NLyk6Jm80T95AhNj/YjThelkTkmTutS6RAB8pkmpkMofdA==",
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/node-mocks-http/-/node-mocks-http-1.14.1.tgz",
|
||||
"integrity": "sha512-mfXuCGonz0A7uG1FEjnypjm34xegeN5+HI6xeGhYKecfgaZhjsmYoLE9LEFmT+53G1n8IuagPZmVnEL/xNsFaA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/node": "^20.10.6",
|
||||
"accepts": "^1.3.7",
|
||||
"content-disposition": "^0.5.3",
|
||||
"depd": "^1.1.0",
|
||||
@@ -18299,6 +18223,15 @@
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/node-mocks-http/node_modules/@types/node": {
|
||||
"version": "20.10.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.6.tgz",
|
||||
"integrity": "sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/node-pg-migrate": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/node-pg-migrate/-/node-pg-migrate-6.2.2.tgz",
|
||||
@@ -18397,9 +18330,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/nodemon": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.2.tgz",
|
||||
"integrity": "sha512-9qIN2LNTrEzpOPBaWHTm4Asy1LxXLSickZStAQ4IZe7zsoIpD/A7LWxhZV3t4Zu352uBcqVnRsDXSMR2Sc3lTA==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.3.tgz",
|
||||
"integrity": "sha512-7jH/NXbFPxVaMwmBCC2B9F/V6X1VkEdNgx3iu9jji8WxWcvhMWkmhNWhI5077zknOnZnBzba9hZP6bCPJLSReQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chokidar": "^3.5.2",
|
||||
@@ -21270,9 +21203,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz",
|
||||
"integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==",
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz",
|
||||
"integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
@@ -24029,9 +23962,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/simple-icons": {
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/simple-icons/-/simple-icons-10.4.0.tgz",
|
||||
"integrity": "sha512-XBoU1ljCsWjw59IVkaQ1nKc0PiaDAAKNFVx59ueC0tBy4WY/I4Q040sGj6ok2cZRLT8zBzL1HaTubi8MRqmojQ==",
|
||||
"version": "11.2.0",
|
||||
"resolved": "https://registry.npmjs.org/simple-icons/-/simple-icons-11.2.0.tgz",
|
||||
"integrity": "sha512-ZT/+2+pSg7kGaWBorPxaktwb3pK18R945XnPU895qPzGDN1LxkHfDbejbBnAvIElYYPgUPstqUIjyPSvZPSfTg==",
|
||||
"engines": {
|
||||
"node": ">=0.12.18"
|
||||
},
|
||||
@@ -24184,9 +24117,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/smol-toml": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.1.3.tgz",
|
||||
"integrity": "sha512-qTyy6Owjho1ISBmxj4HdrFWB2kMQ5RczU6J04OqslSfdSH656OIHuomHS4ZDvhwm37nig/uXyiTMJxlC9zIVfw==",
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.1.4.tgz",
|
||||
"integrity": "sha512-Y0OT8HezWsTNeEOSVxDnKOW/AyNXHQ4BwJNbAXlLTF5wWsBvrcHhIkE5Rf8kQMLmgf7nDX3PVOlgC6/Aiggu3Q==",
|
||||
"engines": {
|
||||
"node": ">= 18",
|
||||
"pnpm": ">= 8"
|
||||
@@ -25785,9 +25718,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tsd": {
|
||||
"version": "0.30.1",
|
||||
"resolved": "https://registry.npmjs.org/tsd/-/tsd-0.30.1.tgz",
|
||||
"integrity": "sha512-OKyeWzTGuaidnYPcSCk/Jz6GY+3A4cNe0tLvJXT7V0vyQ8gy4ISNAetex6YodOkJw7b641B5vokmOZFeW/mpmQ==",
|
||||
"version": "0.30.4",
|
||||
"resolved": "https://registry.npmjs.org/tsd/-/tsd-0.30.4.tgz",
|
||||
"integrity": "sha512-ncC4SwAeUk0OTcXt5h8l0/gOLHJSp9ogosvOADT6QYzrl0ITm398B3wkz8YESqefIsEEwvYAU8bvo7/rcN/M0Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@tsd/typescript": "~5.3.3",
|
||||
@@ -26305,6 +26238,12 @@
|
||||
"integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/unherit": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz",
|
||||
|
||||
36
package.json
36
package.json
@@ -23,7 +23,7 @@
|
||||
"dependencies": {
|
||||
"@renovatebot/pep440": "^3.0.17",
|
||||
"@renovatebot/ruby-semver": "^3.0.22",
|
||||
"@sentry/node": "^7.91.0",
|
||||
"@sentry/node": "^7.98.0",
|
||||
"@shields_io/camp": "^18.1.2",
|
||||
"@xmldom/xmldom": "0.8.10",
|
||||
"badge-maker": "file:badge-maker",
|
||||
@@ -32,19 +32,19 @@
|
||||
"chalk": "^5.3.0",
|
||||
"check-node-version": "^4.2.1",
|
||||
"cloudflare-middleware": "^1.0.4",
|
||||
"config": "^3.3.9",
|
||||
"config": "^3.3.10",
|
||||
"cross-env": "^7.0.3",
|
||||
"dayjs": "^1.11.10",
|
||||
"decamelize": "^3.2.0",
|
||||
"emojic": "^1.1.17",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"fast-xml-parser": "^4.3.2",
|
||||
"fast-xml-parser": "^4.3.3",
|
||||
"glob": "^10.3.10",
|
||||
"global-agent": "^3.0.0",
|
||||
"got": "^14.0.0",
|
||||
"graphql": "16.8.1",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"joi": "17.11.0",
|
||||
"joi": "17.12.0",
|
||||
"joi-extension-semver": "5.0.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsonpath": "~1.1.1",
|
||||
@@ -63,8 +63,8 @@
|
||||
"qs": "^6.11.2",
|
||||
"query-string": "^8.1.0",
|
||||
"semver": "~7.5.4",
|
||||
"simple-icons": "10.4.0",
|
||||
"smol-toml": "1.1.3",
|
||||
"simple-icons": "11.2.0",
|
||||
"smol-toml": "1.1.4",
|
||||
"webextension-store-meta": "^1.0.5",
|
||||
"xpath": "~0.0.34"
|
||||
},
|
||||
@@ -147,17 +147,17 @@
|
||||
"@docusaurus/core": "^2.4.3",
|
||||
"@easyops-cn/docusaurus-search-local": "^0.40.1",
|
||||
"@mdx-js/react": "^1.6.21",
|
||||
"@typescript-eslint/parser": "^6.16.0",
|
||||
"c8": "^8.0.1",
|
||||
"@typescript-eslint/parser": "^6.19.1",
|
||||
"c8": "^9.1.0",
|
||||
"caller": "^1.1.0",
|
||||
"chai": "^4.3.10",
|
||||
"chai": "^4.4.1",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"chai-datetime": "^1.8.0",
|
||||
"chai-string": "^1.4.0",
|
||||
"child-process-promise": "^2.2.1",
|
||||
"clsx": "^2.0.0",
|
||||
"clsx": "^2.1.0",
|
||||
"concurrently": "^8.2.2",
|
||||
"cypress": "^13.6.2",
|
||||
"cypress": "^13.6.3",
|
||||
"cypress-wait-for-stable-dom": "^0.1.0",
|
||||
"danger": "^11.3.1",
|
||||
"deepmerge": "^4.3.1",
|
||||
@@ -167,11 +167,11 @@
|
||||
"eslint-config-standard": "17.1.0",
|
||||
"eslint-config-standard-jsx": "11.0.0",
|
||||
"eslint-config-standard-react": "13.0.0",
|
||||
"eslint-plugin-chai-friendly": "^0.7.2",
|
||||
"eslint-plugin-chai-friendly": "^0.7.4",
|
||||
"eslint-plugin-cypress": "^2.15.1",
|
||||
"eslint-plugin-icedfrisby": "^0.1.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jsdoc": "^46.9.1",
|
||||
"eslint-plugin-jsdoc": "^48.0.4",
|
||||
"eslint-plugin-mocha": "^10.2.0",
|
||||
"eslint-plugin-no-extension-in-require": "^0.2.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
@@ -191,13 +191,13 @@
|
||||
"mocha-env-reporter": "^4.0.0",
|
||||
"mocha-junit-reporter": "^2.2.1",
|
||||
"mocha-yaml-loader": "^1.0.3",
|
||||
"nock": "13.4.0",
|
||||
"node-mocks-http": "^1.14.0",
|
||||
"nodemon": "^3.0.2",
|
||||
"nock": "13.5.0",
|
||||
"node-mocks-http": "^1.14.1",
|
||||
"nodemon": "^3.0.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"open-cli": "^8.0.0",
|
||||
"portfinder": "^1.0.32",
|
||||
"prettier": "3.1.1",
|
||||
"prettier": "3.2.4",
|
||||
"prism-react-renderer": "^2.3.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
@@ -209,7 +209,7 @@
|
||||
"sinon-chai": "^3.7.0",
|
||||
"snap-shot-it": "^7.9.10",
|
||||
"start-server-and-test": "2.0.3",
|
||||
"tsd": "^0.30.1",
|
||||
"tsd": "^0.30.4",
|
||||
"url": "^0.11.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -27,7 +27,7 @@ function writeSpec(filename, spec) {
|
||||
|
||||
writeSpec(
|
||||
path.join(specsPath, `${category.id}.yaml`),
|
||||
category2openapi(category, services),
|
||||
category2openapi({ category, services, sort: true }),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -44,6 +44,10 @@ function writeSpec(filename, spec) {
|
||||
)
|
||||
writeSpec(
|
||||
path.join(specsPath, '1core.yaml'),
|
||||
category2openapi({ name: 'Core' }, coreServices),
|
||||
category2openapi({
|
||||
category: { name: 'Core' },
|
||||
services: coreServices,
|
||||
sort: false,
|
||||
}),
|
||||
)
|
||||
})()
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
import { renderVersionBadge } from '../version.js'
|
||||
import { InvalidResponse } from '../index.js'
|
||||
import { InvalidResponse, pathParams } from '../index.js'
|
||||
import BaseBowerService from './bower-base.js'
|
||||
|
||||
export default class BowerVersion extends BaseBowerService {
|
||||
static category = 'version'
|
||||
static route = { base: 'bower/v', pattern: ':packageName' }
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'Bower Version',
|
||||
namedParams: { packageName: 'bootstrap' },
|
||||
staticPreview: renderVersionBadge({ version: '4.2.1' }),
|
||||
static openApi = {
|
||||
'/bower/v/{packageName}': {
|
||||
get: {
|
||||
summary: 'Bower Version',
|
||||
parameters: pathParams({
|
||||
name: 'packageName',
|
||||
example: 'bootstrap',
|
||||
}),
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'bower' }
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Joi from 'joi'
|
||||
import { coveragePercentage } from '../color-formatters.js'
|
||||
import { BaseSvgScrapingService } from '../index.js'
|
||||
import { BaseSvgScrapingService, pathParam, queryParam } from '../index.js'
|
||||
import { parseJson } from '../../core/base-service/json.js'
|
||||
|
||||
// https://docs.codecov.io/reference#totals
|
||||
@@ -35,12 +35,12 @@ const svgValueMatcher = />(\d{1,3}%|unknown)<\/text><\/g>/
|
||||
|
||||
const badgeTokenPattern = /^\w{10}$/
|
||||
|
||||
const documentation = `
|
||||
const description = `
|
||||
<p>
|
||||
You may specify a Codecov badge token to get coverage for a private repository.
|
||||
</p>
|
||||
<p>
|
||||
You can find the token under the badge section of your project settings page, in this url: <code>https://codecov.io/{vcsName}/{user}/{repo}/settings/badge</code>.
|
||||
You can find the token under the badge section of your project settings page, in this url: <code>https://codecov.io/<vcsName>/<user>/<repo>/settings/badge</code>.
|
||||
</p>
|
||||
`
|
||||
|
||||
@@ -54,39 +54,43 @@ export default class Codecov extends BaseSvgScrapingService {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'Codecov',
|
||||
pattern: ':vcsName(github|gh|bitbucket|bb|gl|gitlab)/:user/:repo',
|
||||
namedParams: {
|
||||
vcsName: 'github',
|
||||
user: 'codecov',
|
||||
repo: 'example-node',
|
||||
static openApi = {
|
||||
'/codecov/c/{vcsName}/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'Codecov',
|
||||
description,
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'vcsName',
|
||||
example: 'github',
|
||||
schema: { type: 'string', enum: this.getEnum('vcsName') },
|
||||
}),
|
||||
pathParam({ name: 'user', example: 'codecov' }),
|
||||
pathParam({ name: 'repo', example: 'example-node' }),
|
||||
queryParam({ name: 'token', example: 'a1b2c3d4e5' }),
|
||||
queryParam({ name: 'flag', example: 'flag_name' }),
|
||||
],
|
||||
},
|
||||
queryParams: {
|
||||
token: 'a1b2c3d4e5',
|
||||
flag: 'flag_name',
|
||||
},
|
||||
staticPreview: this.render({ coverage: 90 }),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'Codecov branch',
|
||||
pattern: ':vcsName(github|gh|bitbucket|bb|gl|gitlab)/:user/:repo/:branch',
|
||||
namedParams: {
|
||||
vcsName: 'github',
|
||||
user: 'codecov',
|
||||
repo: 'example-node',
|
||||
branch: 'master',
|
||||
'/codecov/c/{vcsName}/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'Codecov (with branch)',
|
||||
description,
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'vcsName',
|
||||
example: 'github',
|
||||
schema: { type: 'string', enum: this.getEnum('vcsName') },
|
||||
}),
|
||||
pathParam({ name: 'user', example: 'codecov' }),
|
||||
pathParam({ name: 'repo', example: 'example-node' }),
|
||||
pathParam({ name: 'branch', example: 'master' }),
|
||||
queryParam({ name: 'token', example: 'a1b2c3d4e5' }),
|
||||
queryParam({ name: 'flag', example: 'flag_name' }),
|
||||
],
|
||||
},
|
||||
queryParams: {
|
||||
token: 'a1b2c3d4e5',
|
||||
flag: 'flag_name',
|
||||
},
|
||||
staticPreview: this.render({ coverage: 90 }),
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'coverage' }
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ const crateSchema = Joi.object({
|
||||
Joi.object({
|
||||
downloads: nonNegativeInteger,
|
||||
license: Joi.string().required().allow(null),
|
||||
rust_version: Joi.string().allow(null),
|
||||
}),
|
||||
)
|
||||
.min(1)
|
||||
@@ -24,17 +25,11 @@ const versionSchema = Joi.object({
|
||||
downloads: nonNegativeInteger,
|
||||
num: Joi.string().required(),
|
||||
license: Joi.string().required().allow(null),
|
||||
rust_version: Joi.string().allow(null),
|
||||
}).required(),
|
||||
}).required()
|
||||
|
||||
const errorSchema = Joi.object({
|
||||
errors: Joi.array()
|
||||
.items(Joi.object({ detail: Joi.string().required() }))
|
||||
.min(1)
|
||||
.required(),
|
||||
}).required()
|
||||
|
||||
const schema = Joi.alternatives(crateSchema, versionSchema, errorSchema)
|
||||
const schema = Joi.alternatives(crateSchema, versionSchema)
|
||||
|
||||
class BaseCratesService extends BaseJsonService {
|
||||
static defaultBadgeData = { label: 'crates.io' }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { renderDownloadsBadge } from '../downloads.js'
|
||||
import { InvalidParameter, NotFound, pathParams } from '../index.js'
|
||||
import { InvalidParameter, pathParams } from '../index.js'
|
||||
import { BaseCratesService, description } from './crates-base.js'
|
||||
|
||||
export default class CratesDownloads extends BaseCratesService {
|
||||
@@ -93,15 +93,6 @@ export default class CratesDownloads extends BaseCratesService {
|
||||
|
||||
const json = await this.fetch({ crate, version })
|
||||
|
||||
if (json.errors) {
|
||||
/* a call like
|
||||
https://crates.io/api/v1/crates/libc/0.1
|
||||
or
|
||||
https://crates.io/api/v1/crates/libc/0.1.76
|
||||
returns a 200 OK with an errors object */
|
||||
throw new NotFound({ prettyMessage: json.errors[0].detail })
|
||||
}
|
||||
|
||||
const downloads = this.transform({ variant, json })
|
||||
|
||||
return this.constructor.render({ variant, downloads, version })
|
||||
|
||||
@@ -55,7 +55,7 @@ t.create('recent downloads (with version)')
|
||||
|
||||
t.create('downloads (invalid version)')
|
||||
.get('/d/libc/7.json')
|
||||
.expectBadge({ label: 'crates.io', message: 'invalid semver: 7' })
|
||||
.expectBadge({ label: 'crates.io', message: 'not found' })
|
||||
|
||||
t.create('downloads (not found)')
|
||||
.get('/d/not-a-real-package.json')
|
||||
|
||||
@@ -36,17 +36,7 @@ export default class CratesLicense extends BaseCratesService {
|
||||
|
||||
static defaultBadgeData = { label: 'license', color: 'blue' }
|
||||
|
||||
static render({ license: message }) {
|
||||
return { message }
|
||||
}
|
||||
|
||||
static transform({ errors, version, versions }) {
|
||||
// crates.io returns a 200 response with an errors object in
|
||||
// error scenarios, e.g. https://crates.io/api/v1/crates/libc/0.1
|
||||
if (errors) {
|
||||
throw new InvalidResponse({ prettyMessage: errors[0].detail })
|
||||
}
|
||||
|
||||
static transform({ version, versions }) {
|
||||
const license = version ? version.license : versions[0].license
|
||||
if (!license) {
|
||||
throw new InvalidResponse({ prettyMessage: 'invalid null license' })
|
||||
@@ -58,6 +48,6 @@ export default class CratesLicense extends BaseCratesService {
|
||||
async handle({ crate, version }) {
|
||||
const json = await this.fetch({ crate, version })
|
||||
const { license } = this.constructor.transform(json)
|
||||
return this.constructor.render({ license })
|
||||
return { message: license }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,14 +14,6 @@ describe('CratesLicense', function () {
|
||||
}).expect({ license: 'MIT/Apache 2.0' })
|
||||
})
|
||||
|
||||
it('throws InvalidResponse on error response', function () {
|
||||
expect(() =>
|
||||
CratesLicense.transform({ errors: [{ detail: 'invalid semver' }] }),
|
||||
)
|
||||
.to.throw(InvalidResponse)
|
||||
.with.property('prettyMessage', 'invalid semver')
|
||||
})
|
||||
|
||||
it('throws InvalidResponse on null license with specific version', function () {
|
||||
expect(() =>
|
||||
CratesLicense.transform({ version: { num: '1.2.3', license: null } }),
|
||||
|
||||
68
services/crates/crates-msrv.service.js
Normal file
68
services/crates/crates-msrv.service.js
Normal file
@@ -0,0 +1,68 @@
|
||||
import { NotFound, pathParams } from '../index.js'
|
||||
import {
|
||||
BaseCratesService,
|
||||
description as cratesIoDescription,
|
||||
} from './crates-base.js'
|
||||
|
||||
const description = `
|
||||
${cratesIoDescription}
|
||||
|
||||
MSRV is a crate's minimum suppported rust version,
|
||||
the oldest version of Rust supported by the crate.
|
||||
See the [Cargo Book](https://doc.rust-lang.org/cargo/reference/manifest.html#the-rust-version-field)
|
||||
for more info.
|
||||
`
|
||||
|
||||
export default class CratesMSRV extends BaseCratesService {
|
||||
static category = 'platform-support'
|
||||
static route = {
|
||||
base: 'crates/msrv',
|
||||
pattern: ':crate/:version?',
|
||||
}
|
||||
|
||||
static openApi = {
|
||||
'/crates/msrv/{crate}': {
|
||||
get: {
|
||||
summary: 'Crates.io MSRV',
|
||||
description,
|
||||
parameters: pathParams({
|
||||
name: 'crate',
|
||||
example: 'serde',
|
||||
}),
|
||||
},
|
||||
},
|
||||
'/crates/msrv/{crate}/{version}': {
|
||||
get: {
|
||||
summary: 'Crates.io MSRV (version)',
|
||||
description,
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'crate',
|
||||
example: 'serde',
|
||||
},
|
||||
{
|
||||
name: 'version',
|
||||
example: '1.0.194',
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'msrv', color: 'blue' }
|
||||
|
||||
static transform({ version, versions }) {
|
||||
const msrv = version ? version.rust_version : versions[0].rust_version
|
||||
if (!msrv) {
|
||||
throw new NotFound({ prettyMessage: 'unknown' })
|
||||
}
|
||||
|
||||
return { msrv }
|
||||
}
|
||||
|
||||
async handle({ crate, version }) {
|
||||
const json = await this.fetch({ crate, version })
|
||||
const { msrv } = this.constructor.transform(json)
|
||||
return { message: msrv }
|
||||
}
|
||||
}
|
||||
15
services/crates/crates-msrv.tester.js
Normal file
15
services/crates/crates-msrv.tester.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { createServiceTester } from '../tester.js'
|
||||
export const t = await createServiceTester()
|
||||
|
||||
// dummy crate i created specifically for this test case
|
||||
t.create('msrv')
|
||||
.get('/shields-test-dummy-crate-msrv-3452398210.json')
|
||||
.expectBadge({ label: 'msrv', message: '1.69' })
|
||||
|
||||
t.create('msrv (with version)')
|
||||
.get('/shields-test-dummy-crate-msrv-3452398210/0.69.0.json')
|
||||
.expectBadge({ label: 'msrv', message: '1.69' })
|
||||
|
||||
t.create('msrv (not found)')
|
||||
.get('/not-a-real-package.json')
|
||||
.expectBadge({ label: 'msrv', message: 'not found' })
|
||||
@@ -1,5 +1,5 @@
|
||||
import { renderVersionBadge } from '../version.js'
|
||||
import { InvalidResponse, pathParams } from '../index.js'
|
||||
import { pathParams } from '../index.js'
|
||||
import { BaseCratesService, description } from './crates-base.js'
|
||||
|
||||
export default class CratesVersion extends BaseCratesService {
|
||||
@@ -20,9 +20,6 @@ export default class CratesVersion extends BaseCratesService {
|
||||
}
|
||||
|
||||
transform(json) {
|
||||
if (json.errors) {
|
||||
throw new InvalidResponse({ prettyMessage: json.errors[0].detail })
|
||||
}
|
||||
return json.crate.max_stable_version
|
||||
? json.crate.max_stable_version
|
||||
: json.crate.max_version
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { test, given } from 'sazerac'
|
||||
import { expect } from 'chai'
|
||||
import { InvalidResponse } from '../index.js'
|
||||
import CratesVersion from './crates-version.service.js'
|
||||
|
||||
describe('CratesVersion', function () {
|
||||
@@ -10,10 +8,4 @@ describe('CratesVersion', function () {
|
||||
crate: { max_stable_version: '1.1.0', max_version: '1.9.0-alpha' },
|
||||
}).expect('1.1.0')
|
||||
})
|
||||
|
||||
it('throws InvalidResponse on error response', function () {
|
||||
expect(() =>
|
||||
CratesVersion.prototype.transform({ errors: [{ detail: 'idk how...' }] }),
|
||||
).to.throw(InvalidResponse)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import camelcase from 'camelcase'
|
||||
import Joi from 'joi'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { nonNegativeInteger, optionalUrl } from '../validators.js'
|
||||
import { BaseJsonService } from '../index.js'
|
||||
import { BaseJsonService, queryParams } from '../index.js'
|
||||
|
||||
const schemaSingular = Joi.object({
|
||||
topic_count: nonNegativeInteger,
|
||||
@@ -24,17 +23,19 @@ const queryParamSchema = Joi.object({
|
||||
server: optionalUrl.required(),
|
||||
}).required()
|
||||
|
||||
function singular(variant) {
|
||||
return variant.slice(0, -1)
|
||||
}
|
||||
|
||||
const params = queryParams({
|
||||
name: 'server',
|
||||
example: 'https://meta.discourse.org',
|
||||
required: true,
|
||||
})
|
||||
|
||||
class DiscourseBase extends BaseJsonService {
|
||||
static category = 'chat'
|
||||
|
||||
static buildRoute(metric) {
|
||||
return {
|
||||
base: 'discourse',
|
||||
pattern: metric,
|
||||
queryParamSchema,
|
||||
}
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'discourse' }
|
||||
|
||||
async fetch({ server }) {
|
||||
@@ -45,58 +46,61 @@ class DiscourseBase extends BaseJsonService {
|
||||
}
|
||||
}
|
||||
|
||||
function DiscourseMetricIntegrationFactory({ metricType }) {
|
||||
// We supply the singular form to more easily check against both schemas.
|
||||
// But, we use the plural form as the metric name for grammatical reasons.
|
||||
const metricName = `${metricType}s`
|
||||
return class DiscourseMetric extends DiscourseBase {
|
||||
// The space is needed so we get 'DiscourseTopics' rather than
|
||||
// 'Discoursetopics'. `camelcase()` removes it.
|
||||
static name = camelcase(`Discourse ${metricName}`, { pascalCase: true })
|
||||
static route = this.buildRoute(metricName)
|
||||
class DiscourseMetric extends DiscourseBase {
|
||||
static route = {
|
||||
base: 'discourse',
|
||||
pattern: ':variant(topics|users|posts|likes)',
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: `Discourse ${metricName}`,
|
||||
namedParams: {},
|
||||
queryParams: {
|
||||
server: 'https://meta.discourse.org',
|
||||
},
|
||||
staticPreview: this.render({ stat: 100 }),
|
||||
},
|
||||
]
|
||||
static openApi = {
|
||||
'/discourse/topics': {
|
||||
get: { summary: 'Discourse Topics', parameters: params },
|
||||
},
|
||||
'/discourse/users': {
|
||||
get: { summary: 'Discourse Users', parameters: params },
|
||||
},
|
||||
'/discourse/posts': {
|
||||
get: { summary: 'Discourse Posts', parameters: params },
|
||||
},
|
||||
'/discourse/likes': {
|
||||
get: { summary: 'Discourse Likes', parameters: params },
|
||||
},
|
||||
}
|
||||
|
||||
static render({ stat }) {
|
||||
return {
|
||||
message: `${metric(stat)} ${metricName}`,
|
||||
color: 'brightgreen',
|
||||
}
|
||||
static render({ variant, stat }) {
|
||||
return {
|
||||
message: `${metric(stat)} ${variant}`,
|
||||
color: 'brightgreen',
|
||||
}
|
||||
}
|
||||
|
||||
async handle(_routeParams, { server }) {
|
||||
const data = await this.fetch({ server })
|
||||
// e.g. metricType == 'topic' --> try 'topic_count' then 'topics_count'
|
||||
let stat = data[`${metricType}_count`]
|
||||
if (stat === undefined) {
|
||||
stat = data[`${metricType}s_count`]
|
||||
}
|
||||
return this.constructor.render({ stat })
|
||||
async handle({ variant }, { server }) {
|
||||
const data = await this.fetch({ server })
|
||||
// e.g. variant == 'topics' --> try 'topic_count' then 'topics_count'
|
||||
let stat = data[`${singular(variant)}_count`]
|
||||
if (stat === undefined) {
|
||||
stat = data[`${variant}_count`]
|
||||
}
|
||||
return this.constructor.render({ variant, stat })
|
||||
}
|
||||
}
|
||||
|
||||
class DiscourseStatus extends DiscourseBase {
|
||||
static route = this.buildRoute('status')
|
||||
static examples = [
|
||||
{
|
||||
title: 'Discourse status',
|
||||
namedParams: {},
|
||||
queryParams: {
|
||||
server: 'https://meta.discourse.org',
|
||||
static route = {
|
||||
base: 'discourse',
|
||||
pattern: 'status',
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static openApi = {
|
||||
'/discourse/status': {
|
||||
get: {
|
||||
summary: 'Discourse Status',
|
||||
parameters: params,
|
||||
},
|
||||
staticPreview: this.render(),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static render() {
|
||||
return {
|
||||
@@ -113,11 +117,4 @@ class DiscourseStatus extends DiscourseBase {
|
||||
}
|
||||
}
|
||||
|
||||
const metricIntegrations = [
|
||||
{ metricType: 'topic' },
|
||||
{ metricType: 'user' },
|
||||
{ metricType: 'post' },
|
||||
{ metricType: 'like' },
|
||||
].map(DiscourseMetricIntegrationFactory)
|
||||
|
||||
export default [...metricIntegrations, DiscourseStatus]
|
||||
export default [DiscourseMetric, DiscourseStatus]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Joi from 'joi'
|
||||
import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
|
||||
import { optionalUrl } from '../validators.js'
|
||||
import { BaseJsonService } from '../index.js'
|
||||
import { BaseJsonService, queryParam, pathParam } from '../index.js'
|
||||
|
||||
const schema = Joi.object({
|
||||
status: Joi.alternatives()
|
||||
@@ -22,48 +22,51 @@ export default class DroneBuild extends BaseJsonService {
|
||||
}
|
||||
|
||||
static auth = { passKey: 'drone_token', serviceKey: 'drone' }
|
||||
static examples = [
|
||||
{
|
||||
title: 'Drone (cloud)',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: {
|
||||
user: 'harness',
|
||||
repo: 'drone',
|
||||
|
||||
static openApi = {
|
||||
'/drone/build/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'Drone',
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'user',
|
||||
example: 'drone',
|
||||
}),
|
||||
pathParam({
|
||||
name: 'repo',
|
||||
example: 'autoscaler',
|
||||
}),
|
||||
queryParam({
|
||||
name: 'server',
|
||||
example: 'https://drone.shields.io',
|
||||
}),
|
||||
],
|
||||
},
|
||||
staticPreview: renderBuildStatusBadge({ status: 'success' }),
|
||||
},
|
||||
{
|
||||
title: 'Drone (cloud) with branch',
|
||||
pattern: ':user/:repo/:branch',
|
||||
namedParams: {
|
||||
user: 'harness',
|
||||
repo: 'drone',
|
||||
branch: 'master',
|
||||
'/drone/build/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'Drone (branch)',
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'user',
|
||||
example: 'drone',
|
||||
}),
|
||||
pathParam({
|
||||
name: 'repo',
|
||||
example: 'autoscaler',
|
||||
}),
|
||||
pathParam({
|
||||
name: 'branch',
|
||||
example: 'master',
|
||||
}),
|
||||
queryParam({
|
||||
name: 'server',
|
||||
example: 'https://drone.shields.io',
|
||||
}),
|
||||
],
|
||||
},
|
||||
staticPreview: renderBuildStatusBadge({ status: 'success' }),
|
||||
},
|
||||
{
|
||||
title: 'Drone (self-hosted)',
|
||||
pattern: ':user/:repo',
|
||||
queryParams: { server: 'https://drone.shields.io' },
|
||||
namedParams: {
|
||||
user: 'badges',
|
||||
repo: 'shields',
|
||||
},
|
||||
staticPreview: renderBuildStatusBadge({ status: 'success' }),
|
||||
},
|
||||
{
|
||||
title: 'Drone (self-hosted) with branch',
|
||||
pattern: ':user/:repo/:branch',
|
||||
queryParams: { server: 'https://drone.shields.io' },
|
||||
namedParams: {
|
||||
user: 'badges',
|
||||
repo: 'shields',
|
||||
branch: 'feat/awesome-thing',
|
||||
},
|
||||
staticPreview: renderBuildStatusBadge({ status: 'success' }),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'build' }
|
||||
|
||||
|
||||
@@ -10,14 +10,14 @@ const isDroneBuildStatus = Joi.alternatives().try(
|
||||
)
|
||||
|
||||
t.create('cloud-hosted build status on default branch')
|
||||
.get('/harness/drone.json')
|
||||
.get('/drone/autoscaler.json')
|
||||
.expectBadge({
|
||||
label: 'build',
|
||||
message: isDroneBuildStatus,
|
||||
})
|
||||
|
||||
t.create('cloud-hosted build status on named branch')
|
||||
.get('/harness/drone/master.json')
|
||||
.get('/drone/autoscaler/master.json')
|
||||
.expectBadge({
|
||||
label: 'build',
|
||||
message: isDroneBuildStatus,
|
||||
|
||||
@@ -43,7 +43,7 @@ t.create('TOML from url | caching with new query params')
|
||||
|
||||
t.create('TOML from url | with prefix & suffix & label')
|
||||
.get(
|
||||
'.json?url=https://raw.githubusercontent.com/squirrelchat/smol-toml/mistress/bench/testfiles/toml-spec-example.toml&query=$.database.temp_targets.cpu&prefix=%2B&suffix=°C&label=CPU Temp Target',
|
||||
'.json?url=https://raw.githubusercontent.com/squirrelchat/smol-toml/mistress/bench/testfiles/toml-spec-example.toml&query=$.database.temp_targets.cpu&prefix=%2B&suffix=%C2%B0C&label=CPU Temp Target',
|
||||
)
|
||||
.expectBadge({ label: 'CPU Temp Target', message: '+79.5°C' })
|
||||
|
||||
|
||||
107
services/galaxytoolshed/galaxytoolshed-version.service.js
Normal file
107
services/galaxytoolshed/galaxytoolshed-version.service.js
Normal file
@@ -0,0 +1,107 @@
|
||||
import { NotFound, pathParams } from '../index.js'
|
||||
import { renderVersionBadge } from '../version.js'
|
||||
import GalaxyToolshedService from './galaxytoolshed-base.js'
|
||||
|
||||
export class GalaxyToolshedVersion extends GalaxyToolshedService {
|
||||
static category = 'version'
|
||||
static route = {
|
||||
base: 'galaxytoolshed/v',
|
||||
pattern: ':repository/:owner/:tool?/:requirement?',
|
||||
}
|
||||
|
||||
static openApi = {
|
||||
'/galaxytoolshed/v/{repository}/{owner}': {
|
||||
get: {
|
||||
summary: 'Galaxy Toolshed - Repository Version',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'repository',
|
||||
example: 'sra_tools',
|
||||
},
|
||||
{
|
||||
name: 'owner',
|
||||
example: 'iuc',
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
'/galaxytoolshed/v/{repository}/{owner}/{tool}': {
|
||||
get: {
|
||||
summary: 'Galaxy Toolshed - Tool Version',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'repository',
|
||||
example: 'sra_tools',
|
||||
},
|
||||
{
|
||||
name: 'owner',
|
||||
example: 'iuc',
|
||||
},
|
||||
{
|
||||
name: 'tool',
|
||||
example: 'fastq_dump',
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
'/galaxytoolshed/v/{repository}/{owner}/{tool}/{requirement}': {
|
||||
get: {
|
||||
summary: 'Galaxy Toolshed - Tool Requirement Version',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'repository',
|
||||
example: 'sra_tools',
|
||||
},
|
||||
{
|
||||
name: 'owner',
|
||||
example: 'iuc',
|
||||
},
|
||||
{
|
||||
name: 'tool',
|
||||
example: 'fastq_dump',
|
||||
},
|
||||
{
|
||||
name: 'requirement',
|
||||
example: 'perl',
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
static transform({ response, tool, requirement }) {
|
||||
if (tool !== undefined) {
|
||||
const dataTool = response[1].valid_tools.find(x => x.id === tool)
|
||||
if (dataTool === undefined) {
|
||||
throw new NotFound({ prettyMessage: 'tool not found' })
|
||||
}
|
||||
// Requirement version
|
||||
if (requirement !== undefined) {
|
||||
const dataRequirement = dataTool.requirements.find(
|
||||
x => x.name === requirement,
|
||||
)
|
||||
if (dataRequirement === undefined) {
|
||||
throw new NotFound({ prettyMessage: 'requirement not found' })
|
||||
}
|
||||
return dataRequirement.version
|
||||
}
|
||||
// Tool version
|
||||
return dataTool.version
|
||||
}
|
||||
// Repository version
|
||||
return response[1].changeset_revision
|
||||
}
|
||||
|
||||
async handle({ repository, owner, tool, requirement }) {
|
||||
const response = await this.fetchLastOrderedInstallableRevisionsSchema({
|
||||
repository,
|
||||
owner,
|
||||
})
|
||||
const version = this.constructor.transform({
|
||||
response,
|
||||
tool,
|
||||
requirement,
|
||||
})
|
||||
return renderVersionBadge({ version })
|
||||
}
|
||||
}
|
||||
51
services/galaxytoolshed/galaxytoolshed-version.tester.js
Normal file
51
services/galaxytoolshed/galaxytoolshed-version.tester.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import { withRegex, isVPlusTripleDottedVersion } from '../test-validators.js'
|
||||
import { createServiceTester } from '../tester.js'
|
||||
|
||||
export const t = await createServiceTester()
|
||||
|
||||
t.create('version - repository')
|
||||
.get('/sra_tools/iuc.json')
|
||||
.expectBadge({
|
||||
label: 'galaxytoolshed',
|
||||
message: withRegex(/^([\w\d]+)$/),
|
||||
})
|
||||
t.create('version - tool').get('/sra_tools/iuc/fastq_dump.json').expectBadge({
|
||||
label: 'galaxytoolshed',
|
||||
message: isVPlusTripleDottedVersion,
|
||||
})
|
||||
t.create('version - requirement')
|
||||
.get('/sra_tools/iuc/fastq_dump/perl.json')
|
||||
.expectBadge({
|
||||
label: 'galaxytoolshed',
|
||||
message: isVPlusTripleDottedVersion,
|
||||
})
|
||||
|
||||
// Not found
|
||||
t.create('version - changesetRevision not found')
|
||||
.get('/bioqc/badilla.json')
|
||||
.expectBadge({
|
||||
label: 'galaxytoolshed',
|
||||
message: 'changesetRevision not found',
|
||||
})
|
||||
t.create('version - repository not found')
|
||||
.get('/sra_too/iuc.json')
|
||||
.expectBadge({
|
||||
label: 'galaxytoolshed',
|
||||
message: 'not found',
|
||||
})
|
||||
t.create('version - owner not found').get('/sra_tool/iu.json').expectBadge({
|
||||
label: 'galaxytoolshed',
|
||||
message: 'not found',
|
||||
})
|
||||
t.create('version - tool not found')
|
||||
.get('/sra_tools/iuc/fastq_dum.json')
|
||||
.expectBadge({
|
||||
label: 'galaxytoolshed',
|
||||
message: 'tool not found',
|
||||
})
|
||||
t.create('version - requirement not found')
|
||||
.get('/sra_tools/iuc/fastq_dump/per.json')
|
||||
.expectBadge({
|
||||
label: 'galaxytoolshed',
|
||||
message: 'requirement not found',
|
||||
})
|
||||
@@ -10,7 +10,7 @@ class DummyGiteaService extends GiteaBase {
|
||||
async handle() {
|
||||
const data = await this.fetch({
|
||||
schema: Joi.any(),
|
||||
url: 'https://codeberg.org/api/v1/repos/CanisHelix/shields-badge-test/releases',
|
||||
url: 'https://gitea.com/api/v1/repos/CanisHelix/shields-badge-test/releases',
|
||||
})
|
||||
return { message: data.message }
|
||||
}
|
||||
@@ -24,7 +24,7 @@ describe('GiteaBase', function () {
|
||||
public: {
|
||||
services: {
|
||||
gitea: {
|
||||
authorizedOrigins: ['https://codeberg.org'],
|
||||
authorizedOrigins: ['https://gitea.com'],
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -34,7 +34,7 @@ describe('GiteaBase', function () {
|
||||
}
|
||||
|
||||
it('sends the auth information as configured', async function () {
|
||||
const scope = nock('https://codeberg.org')
|
||||
const scope = nock('https://gitea.com')
|
||||
.get('/api/v1/repos/CanisHelix/shields-badge-test/releases')
|
||||
.matchHeader('Authorization', 'Bearer fake-key')
|
||||
.reply(200, { message: 'fake message' })
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const documentation = `
|
||||
Note that the gitea_url parameter is required because there is canonical hosted gitea service provided by Gitea.
|
||||
const description = `
|
||||
By default this badge looks for repositories on [gitea.com](https://gitea.com).
|
||||
To specify another instance like [codeberg](https://codeberg.org/), [forgejo](https://forgejo.org/) or a self-hosted instance, use the \`gitea_url\` query param.
|
||||
`
|
||||
|
||||
function httpErrorsFor() {
|
||||
@@ -9,4 +10,4 @@ function httpErrorsFor() {
|
||||
}
|
||||
}
|
||||
|
||||
export { documentation, httpErrorsFor }
|
||||
export { description, httpErrorsFor }
|
||||
|
||||
@@ -2,7 +2,7 @@ import Joi from 'joi'
|
||||
import { nonNegativeInteger, optionalUrl } from '../validators.js'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { pathParam, queryParam } from '../index.js'
|
||||
import { documentation, httpErrorsFor } from './gitea-helper.js'
|
||||
import { description, httpErrorsFor } from './gitea-helper.js'
|
||||
import GiteaBase from './gitea-base.js'
|
||||
|
||||
/*
|
||||
@@ -12,7 +12,7 @@ The keys could be anything and {} is a valid response (e.g: for an empty repo)
|
||||
const schema = Joi.object().pattern(/./, nonNegativeInteger)
|
||||
|
||||
const queryParamSchema = Joi.object({
|
||||
gitea_url: optionalUrl.required(),
|
||||
gitea_url: optionalUrl,
|
||||
}).required()
|
||||
|
||||
export default class GiteaLanguageCount extends GiteaBase {
|
||||
@@ -28,20 +28,19 @@ export default class GiteaLanguageCount extends GiteaBase {
|
||||
'/gitea/languages/count/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'Gitea language count',
|
||||
description: documentation,
|
||||
description,
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'user',
|
||||
example: 'forgejo',
|
||||
example: 'gitea',
|
||||
}),
|
||||
pathParam({
|
||||
name: 'repo',
|
||||
example: 'forgejo',
|
||||
example: 'tea',
|
||||
}),
|
||||
queryParam({
|
||||
name: 'gitea_url',
|
||||
example: 'https://codeberg.org',
|
||||
required: true,
|
||||
example: 'https://gitea.com',
|
||||
}),
|
||||
],
|
||||
},
|
||||
@@ -58,7 +57,7 @@ export default class GiteaLanguageCount extends GiteaBase {
|
||||
}
|
||||
|
||||
async fetch({ user, repo, baseUrl }) {
|
||||
// https://try.gitea.io/api/swagger#/repository/repoGetLanguages
|
||||
// https://gitea.com/api/swagger#/repository/repoGetLanguages
|
||||
return super.fetch({
|
||||
schema,
|
||||
url: `${baseUrl}/api/v1/repos/${user}/${repo}/languages`,
|
||||
@@ -66,7 +65,7 @@ export default class GiteaLanguageCount extends GiteaBase {
|
||||
})
|
||||
}
|
||||
|
||||
async handle({ user, repo }, { gitea_url: baseUrl }) {
|
||||
async handle({ user, repo }, { gitea_url: baseUrl = 'https://gitea.com' }) {
|
||||
const data = await this.fetch({
|
||||
user,
|
||||
repo,
|
||||
|
||||
@@ -3,7 +3,12 @@ import { createServiceTester } from '../tester.js'
|
||||
|
||||
export const t = await createServiceTester()
|
||||
|
||||
t.create('language count (empty repo)')
|
||||
t.create('language count').get('/gitea/tea.json').expectBadge({
|
||||
label: 'languages',
|
||||
message: Joi.number().integer().positive(),
|
||||
})
|
||||
|
||||
t.create('language count (empty repo) (self-managed)')
|
||||
.get(
|
||||
'/CanisHelix/shields-badge-test-empty.json?gitea_url=https://codeberg.org',
|
||||
)
|
||||
@@ -12,14 +17,14 @@ t.create('language count (empty repo)')
|
||||
message: '0',
|
||||
})
|
||||
|
||||
t.create('language count')
|
||||
t.create('language count (self-managed)')
|
||||
.get('/CanisHelix/shields-badge-test.json?gitea_url=https://codeberg.org')
|
||||
.expectBadge({
|
||||
label: 'languages',
|
||||
message: Joi.number().integer().positive(),
|
||||
})
|
||||
|
||||
t.create('language count (user or repo not found)')
|
||||
t.create('language count (user or repo not found) (self-managed)')
|
||||
.get('/CanisHelix/does-not-exist.json?gitea_url=https://codeberg.org')
|
||||
.expectBadge({
|
||||
label: 'languages',
|
||||
|
||||
@@ -2,7 +2,7 @@ import Joi from 'joi'
|
||||
import { optionalUrl } from '../validators.js'
|
||||
import { latest, renderVersionBadge } from '../version.js'
|
||||
import { NotFound, pathParam, queryParam } from '../index.js'
|
||||
import { documentation, httpErrorsFor } from './gitea-helper.js'
|
||||
import { description, httpErrorsFor } from './gitea-helper.js'
|
||||
import GiteaBase from './gitea-base.js'
|
||||
|
||||
const schema = Joi.array().items(
|
||||
@@ -18,7 +18,7 @@ const displayNameEnum = ['tag', 'release']
|
||||
const dateOrderByEnum = ['created_at', 'published_at']
|
||||
|
||||
const queryParamSchema = Joi.object({
|
||||
gitea_url: optionalUrl.required(),
|
||||
gitea_url: optionalUrl,
|
||||
include_prereleases: Joi.equal(''),
|
||||
sort: Joi.string()
|
||||
.valid(...sortEnum)
|
||||
@@ -44,20 +44,19 @@ export default class GiteaRelease extends GiteaBase {
|
||||
'/gitea/v/release/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'Gitea Release',
|
||||
description: documentation,
|
||||
description,
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'user',
|
||||
example: 'forgejo',
|
||||
example: 'gitea',
|
||||
}),
|
||||
pathParam({
|
||||
name: 'repo',
|
||||
example: 'forgejo',
|
||||
example: 'tea',
|
||||
}),
|
||||
queryParam({
|
||||
name: 'gitea_url',
|
||||
example: 'https://codeberg.org',
|
||||
required: true,
|
||||
example: 'https://gitea.com',
|
||||
}),
|
||||
queryParam({
|
||||
name: 'include_prereleases',
|
||||
@@ -87,7 +86,7 @@ export default class GiteaRelease extends GiteaBase {
|
||||
static defaultBadgeData = { label: 'release' }
|
||||
|
||||
async fetch({ user, repo, baseUrl }) {
|
||||
// https://try.gitea.io/api/swagger#/repository/repoGetRelease
|
||||
// https://gitea.com/api/swagger#/repository/repoGetRelease
|
||||
return super.fetch({
|
||||
schema,
|
||||
url: `${baseUrl}/api/v1/repos/${user}/${repo}/releases`,
|
||||
@@ -122,7 +121,7 @@ export default class GiteaRelease extends GiteaBase {
|
||||
async handle(
|
||||
{ user, repo },
|
||||
{
|
||||
gitea_url: baseUrl,
|
||||
gitea_url: baseUrl = 'https://gitea.com',
|
||||
include_prereleases: pre,
|
||||
sort,
|
||||
display_name: displayName,
|
||||
|
||||
@@ -1,39 +1,48 @@
|
||||
import Joi from 'joi'
|
||||
import { createServiceTester } from '../tester.js'
|
||||
export const t = await createServiceTester()
|
||||
|
||||
t.create('Release (latest by date)')
|
||||
.get('/gitea/tea.json')
|
||||
.expectBadge({
|
||||
label: 'release',
|
||||
message: Joi.string(),
|
||||
color: Joi.any().valid(...['orange', 'blue']),
|
||||
})
|
||||
|
||||
t.create('Release (latest by date) (self-managed)')
|
||||
.get('/CanisHelix/shields-badge-test.json?gitea_url=https://codeberg.org')
|
||||
.expectBadge({ label: 'release', message: 'v3.0.0', color: 'blue' })
|
||||
|
||||
t.create('Release (latest by date, order by created_at)')
|
||||
t.create('Release (latest by date, order by created_at) (self-managed)')
|
||||
.get(
|
||||
'/CanisHelix/shields-badge-test.json?gitea_url=https://codeberg.org&date_order_by=created_at',
|
||||
)
|
||||
.expectBadge({ label: 'release', message: 'v3.0.0', color: 'blue' })
|
||||
|
||||
t.create('Release (latest by date, order by published_at)')
|
||||
t.create('Release (latest by date, order by published_at) (self-managed)')
|
||||
.get(
|
||||
'/CanisHelix/shields-badge-test.json?gitea_url=https://codeberg.org&date_order_by=published_at',
|
||||
)
|
||||
.expectBadge({ label: 'release', message: 'v3.0.0', color: 'blue' })
|
||||
|
||||
t.create('Release (latest by semver)')
|
||||
t.create('Release (latest by semver) (self-managed)')
|
||||
.get(
|
||||
'/CanisHelix/shields-badge-test.json?gitea_url=https://codeberg.org&sort=semver',
|
||||
)
|
||||
.expectBadge({ label: 'release', message: 'v4.0.0', color: 'blue' })
|
||||
|
||||
t.create('Release (latest by semver pre-release)')
|
||||
t.create('Release (latest by semver pre-release) (self-managed)')
|
||||
.get(
|
||||
'/CanisHelix/shields-badge-test.json?gitea_url=https://codeberg.org&sort=semver&include_prereleases',
|
||||
)
|
||||
.expectBadge({ label: 'release', message: 'v5.0.0-rc1', color: 'orange' })
|
||||
|
||||
t.create('Release (project not found)')
|
||||
t.create('Release (project not found) (self-managed)')
|
||||
.get('/CanisHelix/does-not-exist.json?gitea_url=https://codeberg.org')
|
||||
.expectBadge({ label: 'release', message: 'user or repo not found' })
|
||||
|
||||
t.create('Release (no tags)')
|
||||
t.create('Release (no tags) (self-managed)')
|
||||
.get(
|
||||
'/CanisHelix/shields-badge-test-empty.json?gitea_url=https://codeberg.org',
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Joi from 'joi'
|
||||
import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
|
||||
import { BaseSvgScrapingService } from '../index.js'
|
||||
import { BaseSvgScrapingService, pathParam, queryParam } from '../index.js'
|
||||
import { documentation } from './github-helpers.js'
|
||||
|
||||
const schema = Joi.object({
|
||||
@@ -14,8 +14,6 @@ const queryParamSchema = Joi.object({
|
||||
branch: Joi.alternatives().try(Joi.string(), Joi.number().cast('string')),
|
||||
}).required()
|
||||
|
||||
const keywords = ['action', 'actions']
|
||||
|
||||
export default class GithubActionsWorkflowStatus extends BaseSvgScrapingService {
|
||||
static category = 'build'
|
||||
|
||||
@@ -25,53 +23,26 @@ export default class GithubActionsWorkflowStatus extends BaseSvgScrapingService
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub Workflow Status',
|
||||
namedParams: {
|
||||
user: 'actions',
|
||||
repo: 'toolkit',
|
||||
workflow: 'unit-tests.yml',
|
||||
static openApi = {
|
||||
'/github/actions/workflow/status/{user}/{repo}/{workflow}': {
|
||||
get: {
|
||||
summary: 'GitHub Actions Workflow Status',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'actions' }),
|
||||
pathParam({ name: 'repo', example: 'toolkit' }),
|
||||
pathParam({ name: 'workflow', example: 'unit-tests.yml' }),
|
||||
queryParam({ name: 'branch', example: 'main' }),
|
||||
queryParam({
|
||||
name: 'event',
|
||||
example: 'push',
|
||||
description:
|
||||
'See GitHub Actions [Events that trigger workflows](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows) for allowed values.',
|
||||
}),
|
||||
],
|
||||
},
|
||||
staticPreview: renderBuildStatusBadge({
|
||||
status: 'passing',
|
||||
}),
|
||||
documentation,
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'GitHub Workflow Status (with branch)',
|
||||
namedParams: {
|
||||
user: 'actions',
|
||||
repo: 'toolkit',
|
||||
workflow: 'unit-tests.yml',
|
||||
},
|
||||
queryParams: {
|
||||
branch: 'main',
|
||||
},
|
||||
staticPreview: renderBuildStatusBadge({
|
||||
status: 'passing',
|
||||
}),
|
||||
documentation,
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'GitHub Workflow Status (with event)',
|
||||
namedParams: {
|
||||
user: 'actions',
|
||||
repo: 'toolkit',
|
||||
workflow: 'unit-tests.yml',
|
||||
},
|
||||
queryParams: {
|
||||
event: 'push',
|
||||
},
|
||||
staticPreview: renderBuildStatusBadge({
|
||||
status: 'passing',
|
||||
}),
|
||||
documentation,
|
||||
keywords,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static _cacheLength = 60
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import gql from 'graphql-tag'
|
||||
import Joi from 'joi'
|
||||
import parseLinkHeader from 'parse-link-header'
|
||||
import { InvalidResponse } from '../index.js'
|
||||
import { InvalidResponse, pathParam, queryParam } from '../index.js'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { GithubAuthV4Service } from './github-auth-service.js'
|
||||
@@ -35,33 +35,51 @@ export default class GitHubCommitActivity extends GithubAuthV4Service {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub commit activity',
|
||||
// Override the pattern to omit the deprecated interval "4w".
|
||||
pattern: ':interval(t|y|m|w)/:user/:repo',
|
||||
namedParams: { interval: 'm', user: 'eslint', repo: 'eslint' },
|
||||
queryParams: { authorFilter: 'nzakas' },
|
||||
staticPreview: this.render({ interval: 'm', commitCount: 457 }),
|
||||
keywords: ['commits'],
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub commit activity (branch)',
|
||||
// Override the pattern to omit the deprecated interval "4w".
|
||||
pattern: ':interval(t|y|m|w)/:user/:repo/:branch*',
|
||||
namedParams: {
|
||||
interval: 'm',
|
||||
user: 'badges',
|
||||
repo: 'squint',
|
||||
branch: 'main',
|
||||
static openApi = {
|
||||
'/github/commit-activity/{interval}/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub commit activity',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'interval',
|
||||
example: 'm',
|
||||
description: 'Commits in the last Week, Month, Year, or Total',
|
||||
schema: {
|
||||
type: 'string',
|
||||
// Override the enum to omit the deprecated interval "4w".
|
||||
enum: ['w', 'm', 'y', 't'],
|
||||
},
|
||||
}),
|
||||
pathParam({ name: 'user', example: 'badges' }),
|
||||
pathParam({ name: 'repo', example: 'squint' }),
|
||||
queryParam({ name: 'authorFilter', example: 'calebcartwright' }),
|
||||
],
|
||||
},
|
||||
queryParams: { authorFilter: 'calebcartwright' },
|
||||
staticPreview: this.render({ interval: 'm', commitCount: 5 }),
|
||||
keywords: ['commits'],
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
'/github/commit-activity/{interval}/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'GitHub commit activity (branch)',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'interval',
|
||||
example: 'm',
|
||||
description: 'Commits in the last Week, Month, Year, or Total',
|
||||
schema: {
|
||||
type: 'string',
|
||||
// Override the enum to omit the deprecated interval "4w".
|
||||
enum: ['w', 'm', 'y', 't'],
|
||||
},
|
||||
}),
|
||||
pathParam({ name: 'user', example: 'badges' }),
|
||||
pathParam({ name: 'repo', example: 'squint' }),
|
||||
pathParam({ name: 'branch', example: 'main' }),
|
||||
queryParam({ name: 'authorFilter', example: 'calebcartwright' }),
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'commit activity', color: 'blue' }
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Joi from 'joi'
|
||||
import { pathParam, queryParam } from '../index.js'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { GithubAuthV3Service } from './github-auth-service.js'
|
||||
@@ -19,23 +20,20 @@ export default class GithubCommitsDifference extends GithubAuthV3Service {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub commits difference between two branches/tags/commits',
|
||||
namedParams: {
|
||||
user: 'microsoft',
|
||||
repo: 'vscode',
|
||||
static openApi = {
|
||||
'/github/commits-difference/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub commits difference between two branches/tags/commits',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'microsoft' }),
|
||||
pathParam({ name: 'repo', example: 'vscode' }),
|
||||
queryParam({ name: 'base', example: '1.60.0', required: true }),
|
||||
queryParam({ name: 'head', example: '82f2db7', required: true }),
|
||||
],
|
||||
},
|
||||
queryParams: {
|
||||
base: '1.60.0',
|
||||
head: '82f2db7',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
commitCount: 9227,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'commits difference', namedLogo: 'github' }
|
||||
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
import Joi from 'joi'
|
||||
import { pathParam } from '../index.js'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { GithubAuthV3Service } from './github-auth-service.js'
|
||||
import {
|
||||
fetchLatestRelease,
|
||||
queryParamSchema,
|
||||
openApiQueryParams,
|
||||
} from './github-common-release.js'
|
||||
import { documentation, httpErrorsFor } from './github-helpers.js'
|
||||
|
||||
const schema = Joi.object({ ahead_by: nonNegativeInteger }).required()
|
||||
|
||||
const latestDocs =
|
||||
'<p>The <code>include_prereleases</code>, <code>sort</code> and <code>filter</code> params can be used to configure how we determine the latest version.</p>'
|
||||
|
||||
export default class GithubCommitsSince extends GithubAuthV3Service {
|
||||
static category = 'activity'
|
||||
static route = {
|
||||
@@ -18,110 +23,60 @@ export default class GithubCommitsSince extends GithubAuthV3Service {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub commits since tagged version',
|
||||
namedParams: {
|
||||
user: 'SubtitleEdit',
|
||||
repo: 'subtitleedit',
|
||||
version: '3.4.7',
|
||||
static openApi = {
|
||||
'/github/commits-since/{user}/{repo}/{version}': {
|
||||
get: {
|
||||
summary: 'GitHub commits since tagged version',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'SubtitleEdit' }),
|
||||
pathParam({ name: 'repo', example: 'subtitleedit' }),
|
||||
pathParam({
|
||||
name: 'version',
|
||||
example: '3.4.7',
|
||||
}),
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
version: '3.4.7',
|
||||
commitCount: 4225,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub commits since tagged version (branch)',
|
||||
namedParams: {
|
||||
user: 'SubtitleEdit',
|
||||
repo: 'subtitleedit',
|
||||
version: '3.4.7',
|
||||
branch: 'master',
|
||||
'/github/commits-since/{user}/{repo}/{version}/{branch}': {
|
||||
get: {
|
||||
summary: 'GitHub commits since tagged version (branch)',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'SubtitleEdit' }),
|
||||
pathParam({ name: 'repo', example: 'subtitleedit' }),
|
||||
pathParam({
|
||||
name: 'version',
|
||||
example: '3.4.7',
|
||||
}),
|
||||
pathParam({ name: 'branch', example: 'main' }),
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
version: '3.4.7',
|
||||
commitCount: 4225,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub commits since latest release (by date)',
|
||||
namedParams: {
|
||||
user: 'SubtitleEdit',
|
||||
repo: 'subtitleedit',
|
||||
version: 'latest',
|
||||
'/github/commits-since/{user}/{repo}/latest': {
|
||||
get: {
|
||||
summary: 'GitHub commits since latest release',
|
||||
description: documentation + latestDocs,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'SubtitleEdit' }),
|
||||
pathParam({ name: 'repo', example: 'subtitleedit' }),
|
||||
...openApiQueryParams,
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
version: '3.5.7',
|
||||
commitCount: 157,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub commits since latest release (by date) for a branch',
|
||||
namedParams: {
|
||||
user: 'SubtitleEdit',
|
||||
repo: 'subtitleedit',
|
||||
version: 'latest',
|
||||
branch: 'master',
|
||||
'/github/commits-since/{user}/{repo}/latest/{branch}': {
|
||||
get: {
|
||||
summary: 'GitHub commits since latest release (branch)',
|
||||
description: documentation + latestDocs,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'SubtitleEdit' }),
|
||||
pathParam({ name: 'repo', example: 'subtitleedit' }),
|
||||
pathParam({ name: 'branch', example: 'main' }),
|
||||
...openApiQueryParams,
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
version: '3.5.7',
|
||||
commitCount: 157,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title:
|
||||
'GitHub commits since latest release (by date including pre-releases)',
|
||||
namedParams: {
|
||||
user: 'SubtitleEdit',
|
||||
repo: 'subtitleedit',
|
||||
version: 'latest',
|
||||
},
|
||||
queryParams: { include_prereleases: null },
|
||||
staticPreview: this.render({
|
||||
version: 'v3.5.8-alpha.1',
|
||||
isPrerelease: true,
|
||||
commitCount: 158,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub commits since latest release (by SemVer)',
|
||||
namedParams: {
|
||||
user: 'SubtitleEdit',
|
||||
repo: 'subtitleedit',
|
||||
version: 'latest',
|
||||
},
|
||||
queryParams: { sort: 'semver' },
|
||||
staticPreview: this.render({
|
||||
version: 'v4.0.1',
|
||||
sort: 'semver',
|
||||
commitCount: 200,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title:
|
||||
'GitHub commits since latest release (by SemVer including pre-releases)',
|
||||
namedParams: {
|
||||
user: 'SubtitleEdit',
|
||||
repo: 'subtitleedit',
|
||||
version: 'latest',
|
||||
},
|
||||
queryParams: { sort: 'semver', include_prereleases: null },
|
||||
staticPreview: this.render({
|
||||
version: 'v4.0.2-alpha.1',
|
||||
sort: 'semver',
|
||||
isPrerelease: true,
|
||||
commitCount: 201,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'github', namedLogo: 'github' }
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import Joi from 'joi'
|
||||
import { matcher } from 'matcher'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { latest } from '../version.js'
|
||||
import { NotFound } from '../index.js'
|
||||
import { NotFound, queryParams } from '../index.js'
|
||||
import { httpErrorsFor } from './github-helpers.js'
|
||||
|
||||
const releaseInfoSchema = Joi.object({
|
||||
@@ -67,21 +67,37 @@ function getLatestRelease({ releases, sort, includePrereleases }) {
|
||||
return releases[0]
|
||||
}
|
||||
|
||||
const sortEnum = ['date', 'semver']
|
||||
|
||||
const queryParamSchema = Joi.object({
|
||||
include_prereleases: Joi.equal(''),
|
||||
sort: Joi.string().valid('date', 'semver').default('date'),
|
||||
sort: Joi.string()
|
||||
.valid(...sortEnum)
|
||||
.default('date'),
|
||||
filter: Joi.string(),
|
||||
}).required()
|
||||
|
||||
const filterDocs = `<div>
|
||||
<p>
|
||||
const filterDocs = `<p>
|
||||
The <code>filter</code> 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: <code>*</code> is a wildcard matching zero
|
||||
or more characters, and if the pattern starts with a <code>!</code>,
|
||||
the whole pattern is negated.
|
||||
</p>
|
||||
</div>`
|
||||
</p>`
|
||||
|
||||
const openApiQueryParams = queryParams(
|
||||
{
|
||||
name: 'include_prereleases',
|
||||
example: null,
|
||||
schema: { type: 'boolean' },
|
||||
},
|
||||
{
|
||||
name: 'sort',
|
||||
example: 'semver',
|
||||
schema: { type: 'string', enum: sortEnum },
|
||||
},
|
||||
{ name: 'filter', example: '*beta*', description: filterDocs },
|
||||
)
|
||||
|
||||
function applyFilter({ releases, filter, displayName }) {
|
||||
if (!filter) {
|
||||
@@ -137,7 +153,7 @@ async function fetchLatestRelease(
|
||||
return latestRelease
|
||||
}
|
||||
|
||||
export { fetchLatestRelease, filterDocs, queryParamSchema }
|
||||
export { fetchLatestRelease, queryParamSchema, openApiQueryParams }
|
||||
|
||||
// currently only used for tests
|
||||
export const _getLatestRelease = getLatestRelease
|
||||
|
||||
@@ -1,26 +1,9 @@
|
||||
import Joi from 'joi'
|
||||
import gql from 'graphql-tag'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { InvalidParameter } from '../index.js'
|
||||
import { InvalidParameter, pathParam, queryParam } from '../index.js'
|
||||
import { GithubAuthV4Service } from './github-auth-service.js'
|
||||
import {
|
||||
documentation as commonDocumentation,
|
||||
transformErrors,
|
||||
} from './github-helpers.js'
|
||||
|
||||
const documentation = `${commonDocumentation}
|
||||
<p>
|
||||
<b>Note:</b><br>
|
||||
1. Parameter <code>type</code> accepts either <code>file</code> or <code>dir</code> value. Passing any other value will result in an error.<br>
|
||||
2. Parameter <code>extension</code> accepts file extension without a leading dot.
|
||||
For instance for <code>.js</code> extension pass <code>js</code>.
|
||||
Only single <code>extension</code> value can be specified.
|
||||
<code>extension</code> is applicable for <code>type</code> <code>file</code> only.
|
||||
Passing it either without <code>type</code> or along with <code>type</code> <code>dir</code> will result in an error.<br>
|
||||
3. GitHub API has an upper limit of 1,000 files for a directory.
|
||||
In case a directory contains files above the limit, a badge might present inaccurate information.<br>
|
||||
</p>
|
||||
`
|
||||
import { documentation, transformErrors } from './github-helpers.js'
|
||||
|
||||
const schema = Joi.object({
|
||||
data: Joi.object({
|
||||
@@ -39,11 +22,18 @@ const schema = Joi.object({
|
||||
}).required(),
|
||||
}).required()
|
||||
|
||||
const typeEnum = ['dir', 'file']
|
||||
|
||||
const queryParamSchema = Joi.object({
|
||||
type: Joi.any().valid('dir', 'file'),
|
||||
type: Joi.any().valid(...typeEnum),
|
||||
extension: Joi.string(),
|
||||
})
|
||||
|
||||
const typeDocs =
|
||||
'Entity to count: directories or files. If not specified, both files and directories are counted. GitHub API has an upper limit of 1,000 files for a directory. If a directory contains files above the limit, the badge will show an inaccurate count.'
|
||||
const extensionDocs =
|
||||
'Filter to files of type. Specify the extension without a leading dot. For instance for `.js` extension pass `js`. This param is only applicable if type is `file`'
|
||||
|
||||
export default class GithubDirectoryFileCount extends GithubAuthV4Service {
|
||||
static category = 'size'
|
||||
|
||||
@@ -53,62 +43,51 @@ export default class GithubDirectoryFileCount extends GithubAuthV4Service {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub repo file count',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: { user: 'badges', repo: 'shields' },
|
||||
staticPreview: this.render({ count: 20 }),
|
||||
documentation,
|
||||
static openApi = {
|
||||
'/github/directory-file-count/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub repo file or directory count',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'badges' }),
|
||||
pathParam({ name: 'repo', example: 'shields' }),
|
||||
queryParam({
|
||||
name: 'type',
|
||||
example: 'file',
|
||||
schema: { type: 'string', enum: typeEnum },
|
||||
description: typeDocs,
|
||||
}),
|
||||
queryParam({
|
||||
name: 'extension',
|
||||
example: 'js',
|
||||
description: extensionDocs,
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'GitHub repo file count (custom path)',
|
||||
pattern: ':user/:repo/:path',
|
||||
namedParams: { user: 'badges', repo: 'shields', path: 'services' },
|
||||
staticPreview: this.render({ count: 10 }),
|
||||
documentation,
|
||||
'/github/directory-file-count/{user}/{repo}/{path}': {
|
||||
get: {
|
||||
summary: 'GitHub repo file or directory count (in path)',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'badges' }),
|
||||
pathParam({ name: 'repo', example: 'shields' }),
|
||||
pathParam({ name: 'path', example: 'services' }),
|
||||
queryParam({
|
||||
name: 'type',
|
||||
example: 'file',
|
||||
schema: { type: 'string', enum: typeEnum },
|
||||
description: typeDocs,
|
||||
}),
|
||||
queryParam({
|
||||
name: 'extension',
|
||||
example: 'js',
|
||||
description: extensionDocs,
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'GitHub repo directory count',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: { user: 'badges', repo: 'shields' },
|
||||
queryParams: { type: 'dir' },
|
||||
staticPreview: this.render({ count: 8 }),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub repo directory count (custom path)',
|
||||
pattern: ':user/:repo/:path',
|
||||
namedParams: { user: 'badges', repo: 'shields', path: 'services' },
|
||||
queryParams: { type: 'dir' },
|
||||
staticPreview: this.render({ count: 8 }),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub repo file count (file type)',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: { user: 'badges', repo: 'shields' },
|
||||
queryParams: { type: 'file' },
|
||||
staticPreview: this.render({ count: 2 }),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub repo file count (custom path & file type)',
|
||||
pattern: ':user/:repo/:path',
|
||||
namedParams: { user: 'badges', repo: 'shields', path: 'services' },
|
||||
queryParams: { type: 'file' },
|
||||
staticPreview: this.render({ count: 2 }),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub repo file count (file extension)',
|
||||
pattern: ':user/:repo/:path',
|
||||
namedParams: { user: 'badges', repo: 'shields', path: 'services' },
|
||||
queryParams: { type: 'file', extension: 'js' },
|
||||
staticPreview: this.render({ count: 1 }),
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { color: 'blue', label: 'files' }
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import gql from 'graphql-tag'
|
||||
import Joi from 'joi'
|
||||
import { pathParam, queryParam } from '../index.js'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { GithubAuthV4Service } from './github-auth-service.js'
|
||||
import { documentation, transformErrors } from './github-helpers.js'
|
||||
|
||||
const discussionsSearchDocs = `
|
||||
For a full list of available filters and allowed values that can be used in the <code>query</code>,
|
||||
For a full list of available filters and allowed values,
|
||||
see GitHub's documentation on
|
||||
[Searching discussions](https://docs.github.com/en/search-github/searching-on-github/searching-discussions).
|
||||
${documentation}
|
||||
`
|
||||
|
||||
const discussionCountSchema = Joi.object({
|
||||
@@ -56,21 +56,22 @@ class GithubDiscussionsSearch extends BaseGithubDiscussionsSearch {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub discussions custom search',
|
||||
namedParams: {},
|
||||
queryParams: {
|
||||
query: 'repo:badges/shields is:answered answered-by:chris48s',
|
||||
static openApi = {
|
||||
'/github/discussions-search': {
|
||||
get: {
|
||||
summary: 'GitHub discussions custom search',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
queryParam({
|
||||
name: 'query',
|
||||
description: discussionsSearchDocs,
|
||||
example: 'repo:badges/shields is:answered answered-by:chris48s',
|
||||
required: true,
|
||||
}),
|
||||
],
|
||||
},
|
||||
staticPreview: {
|
||||
label: 'query',
|
||||
message: '2',
|
||||
color: 'blue',
|
||||
},
|
||||
documentation: discussionsSearchDocs,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
async handle(namedParams, { query }) {
|
||||
const discussionCount = await this.fetch({ query })
|
||||
@@ -85,24 +86,24 @@ class GithubRepoDiscussionsSearch extends BaseGithubDiscussionsSearch {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub discussions custom search in repo',
|
||||
namedParams: {
|
||||
user: 'badges',
|
||||
repo: 'shields',
|
||||
static openApi = {
|
||||
'/github/discussions-search/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub discussions custom search in repo',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'badges' }),
|
||||
pathParam({ name: 'repo', example: 'shields' }),
|
||||
queryParam({
|
||||
name: 'query',
|
||||
description: discussionsSearchDocs,
|
||||
example: 'is:answered answered-by:chris48s',
|
||||
required: true,
|
||||
}),
|
||||
],
|
||||
},
|
||||
queryParams: {
|
||||
query: 'is:answered answered-by:chris48s',
|
||||
},
|
||||
staticPreview: {
|
||||
label: 'query',
|
||||
message: '2',
|
||||
color: 'blue',
|
||||
},
|
||||
documentation: discussionsSearchDocs,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
async handle({ user, repo }, { query }) {
|
||||
query = `repo:${user}/${repo} ${query}`
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import Joi from 'joi'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { renderDownloadsBadge } from '../downloads.js'
|
||||
import { NotFound } from '../index.js'
|
||||
import { NotFound, pathParam, queryParam } from '../index.js'
|
||||
import { GithubAuthV3Service } from './github-auth-service.js'
|
||||
import { fetchLatestRelease } from './github-common-release.js'
|
||||
import { documentation, httpErrorsFor } from './github-helpers.js'
|
||||
|
||||
const sortEnum = ['date', 'semver']
|
||||
|
||||
const queryParamSchema = Joi.object({
|
||||
sort: Joi.string().valid('date', 'semver').default('date'),
|
||||
sort: Joi.string()
|
||||
.valid(...sortEnum)
|
||||
.default('date'),
|
||||
}).required()
|
||||
|
||||
const releaseSchema = Joi.object({
|
||||
@@ -24,173 +28,84 @@ const releaseArraySchema = Joi.alternatives().try(
|
||||
Joi.array().length(0),
|
||||
)
|
||||
|
||||
const variantParam = pathParam({
|
||||
name: 'variant',
|
||||
example: 'downloads',
|
||||
description: 'downloads including or excluding pre-releases',
|
||||
schema: { type: 'string', enum: ['downloads', 'downloads-pre'] },
|
||||
})
|
||||
const userParam = pathParam({ name: 'user', example: 'atom' })
|
||||
const repoParam = pathParam({ name: 'repo', example: 'atom' })
|
||||
const tagParam = pathParam({ name: 'tag', example: 'v0.190.0' })
|
||||
const assetNameParam = pathParam({
|
||||
name: 'assetName',
|
||||
example: 'atom-amd64.deb',
|
||||
})
|
||||
const sortParam = queryParam({
|
||||
name: 'sort',
|
||||
example: 'semver',
|
||||
schema: { type: 'string', enum: sortEnum },
|
||||
description: 'Method used to determine latest release. Default: `date`',
|
||||
})
|
||||
|
||||
export default class GithubDownloads extends GithubAuthV3Service {
|
||||
static category = 'downloads'
|
||||
static route = {
|
||||
base: 'github',
|
||||
pattern: ':kind(downloads|downloads-pre)/:user/:repo/:tag*/:assetName',
|
||||
pattern: ':variant(downloads|downloads-pre)/:user/:repo/:tag*/:assetName',
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub all releases',
|
||||
pattern: 'downloads/:user/:repo/total',
|
||||
namedParams: {
|
||||
user: 'atom',
|
||||
repo: 'atom',
|
||||
static openApi = {
|
||||
'/github/downloads/{user}/{repo}/total': {
|
||||
get: {
|
||||
summary: 'GitHub Downloads (all assets, all releases)',
|
||||
description: documentation,
|
||||
parameters: [userParam, repoParam],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
assetName: 'total',
|
||||
downloads: 857000,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub release (latest by date)',
|
||||
pattern: 'downloads/:user/:repo/:tag/total',
|
||||
namedParams: {
|
||||
user: 'atom',
|
||||
repo: 'atom',
|
||||
tag: 'latest',
|
||||
'/github/{variant}/{user}/{repo}/latest/total': {
|
||||
get: {
|
||||
summary: 'GitHub Downloads (all assets, latest release)',
|
||||
description: documentation,
|
||||
parameters: [variantParam, userParam, repoParam, sortParam],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
tag: 'latest',
|
||||
assetName: 'total',
|
||||
downloads: 27000,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub release (latest by SemVer)',
|
||||
pattern: 'downloads/:user/:repo/:tag/total',
|
||||
namedParams: {
|
||||
user: 'atom',
|
||||
repo: 'atom',
|
||||
tag: 'latest',
|
||||
'/github/downloads/{user}/{repo}/{tag}/total': {
|
||||
get: {
|
||||
summary: 'GitHub Downloads (all assets, specific tag)',
|
||||
description: documentation,
|
||||
parameters: [userParam, repoParam, tagParam],
|
||||
},
|
||||
queryParams: { sort: 'semver' },
|
||||
staticPreview: this.render({
|
||||
tag: 'latest',
|
||||
assetName: 'total',
|
||||
downloads: 27000,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub release (latest by date including pre-releases)',
|
||||
pattern: 'downloads-pre/:user/:repo/:tag/total',
|
||||
namedParams: {
|
||||
user: 'atom',
|
||||
repo: 'atom',
|
||||
tag: 'latest',
|
||||
'/github/downloads/{user}/{repo}/{assetName}': {
|
||||
get: {
|
||||
summary: 'GitHub Downloads (specific asset, all releases)',
|
||||
description: documentation,
|
||||
parameters: [userParam, repoParam, assetNameParam],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
tag: 'latest',
|
||||
assetName: 'total',
|
||||
downloads: 2000,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub release (latest by SemVer including pre-releases)',
|
||||
pattern: 'downloads-pre/:user/:repo/:tag/total',
|
||||
namedParams: {
|
||||
user: 'atom',
|
||||
repo: 'atom',
|
||||
tag: 'latest',
|
||||
'/github/{variant}/{user}/{repo}/latest/{assetName}': {
|
||||
get: {
|
||||
summary: 'GitHub Downloads (specific asset, latest release)',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
variantParam,
|
||||
userParam,
|
||||
repoParam,
|
||||
assetNameParam,
|
||||
sortParam,
|
||||
],
|
||||
},
|
||||
queryParams: { sort: 'semver' },
|
||||
staticPreview: this.render({
|
||||
tag: 'latest',
|
||||
assetName: 'total',
|
||||
downloads: 2000,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub release (by tag)',
|
||||
pattern: 'downloads/:user/:repo/:tag/total',
|
||||
namedParams: {
|
||||
user: 'atom',
|
||||
repo: 'atom',
|
||||
tag: 'v0.190.0',
|
||||
'/github/downloads/{user}/{repo}/{tag}/{assetName}': {
|
||||
get: {
|
||||
summary: 'GitHub Downloads (specific asset, specific tag)',
|
||||
description: documentation,
|
||||
parameters: [userParam, repoParam, tagParam, assetNameParam],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
tag: 'v0.190.0',
|
||||
assetName: 'total',
|
||||
downloads: 490000,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub release (latest by date and asset)',
|
||||
pattern: 'downloads/:user/:repo/:tag/:assetName',
|
||||
namedParams: {
|
||||
user: 'atom',
|
||||
repo: 'atom',
|
||||
tag: 'latest',
|
||||
assetName: 'atom-amd64.deb',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
tag: 'latest',
|
||||
assetName: 'atom-amd64.deb',
|
||||
downloads: 3000,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub release (latest by SemVer and asset)',
|
||||
pattern: 'downloads/:user/:repo/:tag/:assetName',
|
||||
namedParams: {
|
||||
user: 'atom',
|
||||
repo: 'atom',
|
||||
tag: 'latest',
|
||||
assetName: 'atom-amd64.deb',
|
||||
},
|
||||
queryParams: { sort: 'semver' },
|
||||
staticPreview: this.render({
|
||||
tag: 'latest',
|
||||
assetName: 'atom-amd64.deb',
|
||||
downloads: 3000,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub release (latest by date and asset including pre-releases)',
|
||||
pattern: 'downloads-pre/:user/:repo/:tag/:assetName',
|
||||
namedParams: {
|
||||
user: 'atom',
|
||||
repo: 'atom',
|
||||
tag: 'latest',
|
||||
assetName: 'atom-amd64.deb',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
tag: 'latest',
|
||||
assetName: 'atom-amd64.deb',
|
||||
downloads: 237,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title:
|
||||
'GitHub release (latest by SemVer and asset including pre-releases)',
|
||||
pattern: 'downloads-pre/:user/:repo/:tag/:assetName',
|
||||
namedParams: {
|
||||
user: 'atom',
|
||||
repo: 'atom',
|
||||
tag: 'latest',
|
||||
assetName: 'atom-amd64.deb',
|
||||
},
|
||||
queryParams: { sort: 'semver' },
|
||||
staticPreview: this.render({
|
||||
tag: 'latest',
|
||||
assetName: 'atom-amd64.deb',
|
||||
downloads: 237,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'downloads', namedLogo: 'github' }
|
||||
|
||||
@@ -219,10 +134,10 @@ export default class GithubDownloads extends GithubAuthV3Service {
|
||||
return { downloads }
|
||||
}
|
||||
|
||||
async handle({ kind, user, repo, tag, assetName }, { sort }) {
|
||||
async handle({ variant, user, repo, tag, assetName }, { sort }) {
|
||||
let releases
|
||||
if (tag === 'latest') {
|
||||
const includePre = kind === 'downloads-pre' || undefined
|
||||
const includePre = variant === 'downloads-pre' || undefined
|
||||
const latestRelease = await fetchLatestRelease(
|
||||
this,
|
||||
{ user, repo },
|
||||
|
||||
@@ -10,7 +10,7 @@ const mockLatestRelease = release => nock =>
|
||||
|
||||
const mockReleases = releases => nock =>
|
||||
nock('https://api.github.com')
|
||||
.get('/repos/photonstorm/phaser/releases')
|
||||
.get('/repos/photonstorm/phaser/releases?per_page=100')
|
||||
.reply(200, releases)
|
||||
|
||||
t.create('Downloads all releases')
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Joi from 'joi'
|
||||
import { pathParams } from '../index.js'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { GithubAuthV3Service } from './github-auth-service.js'
|
||||
@@ -11,18 +12,15 @@ const schema = Joi.object({
|
||||
export default class GithubFollowers extends GithubAuthV3Service {
|
||||
static category = 'social'
|
||||
static route = { base: 'github/followers', pattern: ':user' }
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub followers',
|
||||
namedParams: { user: 'espadrine' },
|
||||
staticPreview: Object.assign(this.render({ followers: 150 }), {
|
||||
label: 'Follow',
|
||||
style: 'social',
|
||||
}),
|
||||
queryParams: { label: 'Follow' },
|
||||
documentation,
|
||||
static openApi = {
|
||||
'/github/followers/{user}': {
|
||||
get: {
|
||||
summary: 'GitHub followers',
|
||||
description: documentation,
|
||||
parameters: pathParams({ name: 'user', example: 'espadrine' }),
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'followers', namedLogo: 'github' }
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import gql from 'graphql-tag'
|
||||
import Joi from 'joi'
|
||||
import { pathParams } from '../index.js'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { GithubAuthV4Service } from './github-auth-service.js'
|
||||
@@ -16,29 +17,18 @@ const schema = Joi.object({
|
||||
export default class GithubForks extends GithubAuthV4Service {
|
||||
static category = 'social'
|
||||
static route = { base: 'github/forks', pattern: ':user/:repo' }
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub forks',
|
||||
namedParams: {
|
||||
user: 'badges',
|
||||
repo: 'shields',
|
||||
static openApi = {
|
||||
'/github/forks/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub forks',
|
||||
description: documentation,
|
||||
parameters: pathParams(
|
||||
{ name: 'user', example: 'badges' },
|
||||
{ name: 'repo', example: 'shields' },
|
||||
),
|
||||
},
|
||||
// TODO: This is currently a literal, as `staticPreview` doesn't
|
||||
// support `link`.
|
||||
staticPreview: {
|
||||
label: 'Fork',
|
||||
message: '150',
|
||||
style: 'social',
|
||||
},
|
||||
// staticPreview: {
|
||||
// ...this.render({ user: 'badges', repo: 'shields', forkCount: 150 }),
|
||||
// label: 'fork',
|
||||
// style: 'social',
|
||||
// },
|
||||
queryParams: { label: 'Fork' },
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'forks', namedLogo: 'github' }
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Joi from 'joi'
|
||||
import { renderVersionBadge } from '../version.js'
|
||||
import { InvalidResponse } from '../index.js'
|
||||
import { InvalidResponse, pathParam, queryParam } from '../index.js'
|
||||
import { ConditionalGithubAuthV3Service } from './github-auth-service.js'
|
||||
import { fetchRepoContent } from './github-common-fetch.js'
|
||||
import { documentation } from './github-helpers.js'
|
||||
@@ -11,7 +11,8 @@ const queryParamSchema = Joi.object({
|
||||
|
||||
const goVersionRegExp = /^go (.+)$/m
|
||||
|
||||
const keywords = ['golang']
|
||||
const filenameDescription =
|
||||
'The `filename` param can be used to specify the path to `go.mod`. By default, we look for `go.mod` in the repo root'
|
||||
|
||||
export default class GithubGoModGoVersion extends ConditionalGithubAuthV3Service {
|
||||
static category = 'version'
|
||||
@@ -21,42 +22,39 @@ export default class GithubGoModGoVersion extends ConditionalGithubAuthV3Service
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub go.mod Go version',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: { user: 'gohugoio', repo: 'hugo' },
|
||||
staticPreview: this.render({ version: '1.12' }),
|
||||
documentation,
|
||||
keywords,
|
||||
static openApi = {
|
||||
'/github/go-mod/go-version/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub go.mod Go version',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'gohugoio' }),
|
||||
pathParam({ name: 'repo', example: 'hugo' }),
|
||||
queryParam({
|
||||
name: 'filename',
|
||||
example: 'src/go.mod',
|
||||
description: filenameDescription,
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'GitHub go.mod Go version (branch)',
|
||||
pattern: ':user/:repo/:branch',
|
||||
namedParams: { user: 'gohugoio', repo: 'hugo', branch: 'master' },
|
||||
staticPreview: this.render({ version: '1.12', branch: 'master' }),
|
||||
documentation,
|
||||
keywords,
|
||||
'/github/go-mod/go-version/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'GitHub go.mod Go version (branch)',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'gohugoio' }),
|
||||
pathParam({ name: 'repo', example: 'hugo' }),
|
||||
pathParam({ name: 'branch', example: 'master' }),
|
||||
queryParam({
|
||||
name: 'filename',
|
||||
example: 'src/go.mod',
|
||||
description: filenameDescription,
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'GitHub go.mod Go version (subdirectory of monorepo)',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: { user: 'golang', repo: 'go' },
|
||||
queryParams: { filename: 'src/go.mod' },
|
||||
staticPreview: this.render({ version: '1.14' }),
|
||||
documentation,
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'GitHub go.mod Go version (branch & subdirectory of monorepo)',
|
||||
pattern: ':user/:repo/:branch',
|
||||
namedParams: { user: 'golang', repo: 'go', branch: 'master' },
|
||||
queryParams: { filename: 'src/go.mod' },
|
||||
staticPreview: this.render({ version: '1.14' }),
|
||||
documentation,
|
||||
keywords,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'Go' }
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import gql from 'graphql-tag'
|
||||
import Joi from 'joi'
|
||||
import dayjs from 'dayjs'
|
||||
import { pathParam, queryParam } from '../index.js'
|
||||
import { metric, maybePluralize } from '../text-formatters.js'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { GithubAuthV4Service } from './github-auth-service.js'
|
||||
@@ -9,7 +10,7 @@ import {
|
||||
transformErrors,
|
||||
} from './github-helpers.js'
|
||||
|
||||
const documentation = `
|
||||
const description = `
|
||||
This badge is designed for projects hosted on GitHub which are
|
||||
participating in
|
||||
[Hacktoberfest](https://hacktoberfest.digitalocean.com),
|
||||
@@ -55,40 +56,24 @@ export default class GithubHacktoberfestCombinedStatus extends GithubAuthV4Servi
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub Hacktoberfest combined status',
|
||||
namedParams: {
|
||||
year: '2023',
|
||||
user: 'snyk',
|
||||
repo: 'snyk',
|
||||
static openApi = {
|
||||
'/github/hacktoberfest/{year}/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub Hacktoberfest combined status',
|
||||
description,
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'year',
|
||||
example: '2023',
|
||||
schema: { type: 'string', enum: this.getEnum('year') },
|
||||
}),
|
||||
pathParam({ name: 'user', example: 'tmrowco' }),
|
||||
pathParam({ name: 'repo', example: 'tmrowapp-contrib' }),
|
||||
queryParam({ name: 'suggestion_label', example: 'help wanted' }),
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
suggestedIssueCount: 12,
|
||||
contributionCount: 8,
|
||||
daysLeft: 15,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub Hacktoberfest combined status (suggestion label override)',
|
||||
namedParams: {
|
||||
year: '2023',
|
||||
user: 'tmrowco',
|
||||
repo: 'tmrowapp-contrib',
|
||||
},
|
||||
queryParams: {
|
||||
suggestion_label: 'help wanted',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
year: '2023',
|
||||
suggestedIssueCount: 12,
|
||||
contributionCount: 8,
|
||||
daysLeft: 15,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'hacktoberfest', color: 'orange' }
|
||||
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import gql from 'graphql-tag'
|
||||
import Joi from 'joi'
|
||||
import { pathParam, queryParam } from '../index.js'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { GithubAuthV4Service } from './github-auth-service.js'
|
||||
import { documentation, transformErrors } from './github-helpers.js'
|
||||
|
||||
const issuesSearchDocs = `
|
||||
For a full list of available filters and allowed values that can be used in the <code>query</code>,
|
||||
For a full list of available filters and allowed values,
|
||||
see GitHub's documentation on
|
||||
[Searching issues and pull requests](https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests)
|
||||
|
||||
${documentation}
|
||||
`
|
||||
|
||||
const issueCountSchema = Joi.object({
|
||||
@@ -57,21 +56,23 @@ class GithubIssuesSearch extends BaseGithubIssuesSearch {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub issue custom search',
|
||||
namedParams: {},
|
||||
queryParams: {
|
||||
query: 'repo:badges/shields is:closed label:bug author:app/sentry-io',
|
||||
static openApi = {
|
||||
'/github/issues-search': {
|
||||
get: {
|
||||
summary: 'GitHub issue custom search',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
queryParam({
|
||||
name: 'query',
|
||||
description: issuesSearchDocs,
|
||||
example:
|
||||
'repo:badges/shields is:closed label:bug author:app/sentry-io',
|
||||
required: true,
|
||||
}),
|
||||
],
|
||||
},
|
||||
staticPreview: {
|
||||
label: 'query',
|
||||
message: '10',
|
||||
color: 'blue',
|
||||
},
|
||||
documentation: issuesSearchDocs,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
async handle(namedParams, { query }) {
|
||||
const issueCount = await this.fetch({ query })
|
||||
@@ -86,24 +87,24 @@ class GithubRepoIssuesSearch extends BaseGithubIssuesSearch {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub issue custom search in repo',
|
||||
namedParams: {
|
||||
user: 'badges',
|
||||
repo: 'shields',
|
||||
static openApi = {
|
||||
'/github/issues-search/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub issue custom search in repo',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'badges' }),
|
||||
pathParam({ name: 'repo', example: 'shields' }),
|
||||
queryParam({
|
||||
name: 'query',
|
||||
description: issuesSearchDocs,
|
||||
example: 'is:closed label:bug author:app/sentry-io',
|
||||
required: true,
|
||||
}),
|
||||
],
|
||||
},
|
||||
queryParams: {
|
||||
query: 'is:closed label:bug author:app/sentry-io',
|
||||
},
|
||||
staticPreview: {
|
||||
label: 'query',
|
||||
message: '10',
|
||||
color: 'blue',
|
||||
},
|
||||
documentation: issuesSearchDocs,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
async handle({ user, repo }, { query }) {
|
||||
query = `repo:${user}/${repo} ${query}`
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import Joi from 'joi'
|
||||
import { pathParam, queryParam } from '../index.js'
|
||||
import { formatDate } from '../text-formatters.js'
|
||||
import { age as ageColor } from '../color-formatters.js'
|
||||
import { GithubAuthV3Service } from './github-auth-service.js'
|
||||
import { documentation, httpErrorsFor } from './github-helpers.js'
|
||||
const commonExampleAttrs = {
|
||||
keywords: ['latest'],
|
||||
documentation,
|
||||
}
|
||||
|
||||
const schema = Joi.array()
|
||||
.items(
|
||||
@@ -24,9 +21,11 @@ const schema = Joi.array()
|
||||
.required()
|
||||
.min(1)
|
||||
|
||||
const displayEnum = ['author', 'committer']
|
||||
|
||||
const queryParamSchema = Joi.object({
|
||||
display_timestamp: Joi.string()
|
||||
.valid('author', 'committer')
|
||||
.valid(...displayEnum)
|
||||
.default('author'),
|
||||
}).required()
|
||||
|
||||
@@ -38,40 +37,41 @@ export default class GithubLastCommit extends GithubAuthV3Service {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub last commit',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: {
|
||||
user: 'google',
|
||||
repo: 'skia',
|
||||
static openApi = {
|
||||
'/github/last-commit/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub last commit',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'google' }),
|
||||
pathParam({ name: 'repo', example: 'skia' }),
|
||||
queryParam({
|
||||
name: 'display_timestamp',
|
||||
example: 'committer',
|
||||
schema: { type: 'string', enum: displayEnum },
|
||||
description: 'Defaults to `author` if not specified',
|
||||
}),
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({ commitDate: '2013-07-31T20:01:41Z' }),
|
||||
...commonExampleAttrs,
|
||||
},
|
||||
{
|
||||
title: 'GitHub last commit (branch)',
|
||||
pattern: ':user/:repo/:branch',
|
||||
namedParams: {
|
||||
user: 'google',
|
||||
repo: 'skia',
|
||||
branch: 'infra/config',
|
||||
'/github/last-commit/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'GitHub last commit (branch)',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'google' }),
|
||||
pathParam({ name: 'repo', example: 'skia' }),
|
||||
pathParam({ name: 'branch', example: 'infra/config' }),
|
||||
queryParam({
|
||||
name: 'display_timestamp',
|
||||
example: 'committer',
|
||||
schema: { type: 'string', enum: displayEnum },
|
||||
description: 'Defaults to `author` if not specified',
|
||||
}),
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({ commitDate: '2013-07-31T20:01:41Z' }),
|
||||
...commonExampleAttrs,
|
||||
},
|
||||
{
|
||||
title: 'GitHub last commit (by committer)',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: {
|
||||
user: 'google',
|
||||
repo: 'skia',
|
||||
},
|
||||
queryParams: { display_timestamp: 'committer' },
|
||||
staticPreview: this.render({ commitDate: '2022-10-15T20:01:41Z' }),
|
||||
...commonExampleAttrs,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'last commit' }
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Joi from 'joi'
|
||||
import { pathParam, queryParam } from '../index.js'
|
||||
import { renderVersionBadge } from '../version.js'
|
||||
import {
|
||||
individualValueSchema,
|
||||
@@ -27,56 +28,31 @@ class GithubManifestVersion extends ConditionalGithubAuthV3Service {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub manifest version',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: {
|
||||
user: 'sindresorhus',
|
||||
repo: 'show-all-github-issues',
|
||||
static openApi = {
|
||||
'/github/manifest-json/v/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub manifest version',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'sindresorhus' }),
|
||||
pathParam({ name: 'repo', example: 'show-all-github-issues' }),
|
||||
queryParam({ name: 'filename', example: 'extension/manifest.json' }),
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({ version: '1.0.3' }),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub manifest version',
|
||||
pattern: ':user/:repo/:branch',
|
||||
namedParams: {
|
||||
user: 'sindresorhus',
|
||||
repo: 'show-all-github-issues',
|
||||
branch: 'master',
|
||||
'/github/manifest-json/v/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'GitHub manifest version (branch)',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'sindresorhus' }),
|
||||
pathParam({ name: 'repo', example: 'show-all-github-issues' }),
|
||||
pathParam({ name: 'branch', example: 'master' }),
|
||||
queryParam({ name: 'filename', example: 'extension/manifest.json' }),
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({ version: '1.0.3', branch: 'master' }),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub manifest version (path)',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: {
|
||||
user: 'RedSparr0w',
|
||||
repo: 'IndieGala-Helper',
|
||||
},
|
||||
queryParams: {
|
||||
filename: 'extension/manifest.json',
|
||||
},
|
||||
staticPreview: this.render({ version: 2 }),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub manifest version (path)',
|
||||
pattern: ':user/:repo/:branch',
|
||||
namedParams: {
|
||||
user: 'RedSparr0w',
|
||||
repo: 'IndieGala-Helper',
|
||||
branch: 'master',
|
||||
},
|
||||
queryParams: {
|
||||
filename: 'extension/manifest.json',
|
||||
},
|
||||
staticPreview: this.render({ version: 2, branch: 'master' }),
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static render({ version, branch }) {
|
||||
return renderVersionBadge({
|
||||
@@ -106,74 +82,33 @@ class DynamicGithubManifest extends ConditionalGithubAuthV3Service {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub manifest.json dynamic',
|
||||
pattern: ':key/:user/:repo',
|
||||
namedParams: {
|
||||
key: 'permissions',
|
||||
user: 'sindresorhus',
|
||||
repo: 'show-all-github-issues',
|
||||
static openApi = {
|
||||
'/github/manifest-json/{key}/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub manifest.json dynamic',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'key', example: 'permissions' }),
|
||||
pathParam({ name: 'user', example: 'sindresorhus' }),
|
||||
pathParam({ name: 'repo', example: 'show-all-github-issues' }),
|
||||
queryParam({ name: 'filename', example: 'extension/manifest.json' }),
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
key: 'permissions',
|
||||
value: ['webRequest', 'webRequestBlocking'],
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub manifest.json dynamic',
|
||||
pattern: ':key/:user/:repo/:branch',
|
||||
namedParams: {
|
||||
key: 'permissions',
|
||||
user: 'sindresorhus',
|
||||
repo: 'show-all-github-issues',
|
||||
branch: 'master',
|
||||
'/github/manifest-json/{key}/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'GitHub manifest.json dynamic (branch)',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'key', example: 'permissions' }),
|
||||
pathParam({ name: 'user', example: 'sindresorhus' }),
|
||||
pathParam({ name: 'repo', example: 'show-all-github-issues' }),
|
||||
pathParam({ name: 'branch', example: 'main' }),
|
||||
queryParam({ name: 'filename', example: 'extension/manifest.json' }),
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
key: 'permissions',
|
||||
value: ['webRequest', 'webRequestBlocking'],
|
||||
branch: 'master',
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub manifest.json dynamic (path)',
|
||||
pattern: ':key/:user/:repo',
|
||||
namedParams: {
|
||||
key: 'permissions',
|
||||
user: 'RedSparr0w',
|
||||
repo: 'IndieGala-Helper',
|
||||
},
|
||||
queryParams: {
|
||||
filename: 'extension/manifest.json',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
key: 'permissions',
|
||||
value: ['bundle', 'rollup', 'micro library'],
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub manifest.json dynamic (path)',
|
||||
pattern: ':key/:user/:repo/:branch',
|
||||
namedParams: {
|
||||
key: 'permissions',
|
||||
user: 'RedSparr0w',
|
||||
repo: 'IndieGala-Helper',
|
||||
branch: 'master',
|
||||
},
|
||||
queryParams: {
|
||||
filename: 'extension/manifest.json',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
key: 'permissions',
|
||||
value: ['bundle', 'rollup', 'micro library'],
|
||||
branch: 'master',
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'manifest' }
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Joi from 'joi'
|
||||
import { pathParam, pathParams, queryParam } from '../index.js'
|
||||
import { renderVersionBadge } from '../version.js'
|
||||
import { transformAndValidate, renderDynamicBadge } from '../dynamic-common.js'
|
||||
import {
|
||||
@@ -10,8 +11,6 @@ import { ConditionalGithubAuthV3Service } from './github-auth-service.js'
|
||||
import { fetchJsonFromRepo } from './github-common-fetch.js'
|
||||
import { documentation } from './github-helpers.js'
|
||||
|
||||
const keywords = ['npm', 'node']
|
||||
|
||||
const versionSchema = Joi.object({
|
||||
version: semver,
|
||||
}).required()
|
||||
@@ -28,42 +27,31 @@ class GithubPackageJsonVersion extends ConditionalGithubAuthV3Service {
|
||||
queryParamSchema: subfolderQueryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub package.json version',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: { user: 'IcedFrisby', repo: 'IcedFrisby' },
|
||||
staticPreview: this.render({ version: '2.0.0-alpha.2' }),
|
||||
documentation,
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'GitHub package.json version (branch)',
|
||||
pattern: ':user/:repo/:branch',
|
||||
namedParams: {
|
||||
user: 'IcedFrisby',
|
||||
repo: 'IcedFrisby',
|
||||
branch: 'master',
|
||||
static openApi = {
|
||||
'/github/package-json/v/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub package.json version',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'badges' }),
|
||||
pathParam({ name: 'repo', example: 'shields' }),
|
||||
queryParam({ name: 'filename', example: 'badge-maker/package.json' }),
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({ version: '2.0.0-alpha.2' }),
|
||||
documentation,
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'GitHub package.json version (subfolder of monorepo)',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: {
|
||||
user: 'metabolize',
|
||||
repo: 'anafanafo',
|
||||
'/github/package-json/v/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'GitHub package.json version (branch)',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'badges' }),
|
||||
pathParam({ name: 'repo', example: 'shields' }),
|
||||
pathParam({ name: 'branch', example: 'master' }),
|
||||
queryParam({ name: 'filename', example: 'badge-maker/package.json' }),
|
||||
],
|
||||
},
|
||||
queryParams: {
|
||||
filename: 'packages/char-width-table-builder/package.json',
|
||||
},
|
||||
staticPreview: this.render({ version: '2.0.0' }),
|
||||
documentation,
|
||||
keywords,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static render({ version, branch }) {
|
||||
return renderVersionBadge({
|
||||
@@ -85,6 +73,9 @@ class GithubPackageJsonVersion extends ConditionalGithubAuthV3Service {
|
||||
}
|
||||
}
|
||||
|
||||
const packageNameDescription =
|
||||
'This may be the name of an unscoped package like `package-name` or a [scoped package](https://docs.npmjs.com/about-scopes) like `@author/package-name`'
|
||||
|
||||
class GithubPackageJsonDependencyVersion extends ConditionalGithubAuthV3Service {
|
||||
static category = 'platform-support'
|
||||
static route = {
|
||||
@@ -94,58 +85,100 @@ class GithubPackageJsonDependencyVersion extends ConditionalGithubAuthV3Service
|
||||
queryParamSchema: subfolderQueryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub package.json dependency version (prod)',
|
||||
pattern: ':user/:repo/:packageName',
|
||||
namedParams: {
|
||||
user: 'developit',
|
||||
repo: 'microbundle',
|
||||
packageName: 'rollup',
|
||||
static openApi = {
|
||||
'/github/package-json/dependency-version/{user}/{repo}/{packageName}': {
|
||||
get: {
|
||||
summary: 'GitHub package.json prod dependency version',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'badges' }),
|
||||
pathParam({ name: 'repo', example: 'shields' }),
|
||||
pathParam({
|
||||
name: 'packageName',
|
||||
example: 'dayjs',
|
||||
description: packageNameDescription,
|
||||
}),
|
||||
queryParam({
|
||||
name: 'filename',
|
||||
example: 'badge-maker/package.json',
|
||||
}),
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
dependency: 'rollup',
|
||||
range: '^0.67.3',
|
||||
}),
|
||||
documentation,
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'GitHub package.json dependency version (dev dep on branch)',
|
||||
pattern: ':user/:repo/dev/:scope?/:packageName/:branch*',
|
||||
namedParams: {
|
||||
user: 'zeit',
|
||||
repo: 'next.js',
|
||||
branch: 'canary',
|
||||
scope: '@babel',
|
||||
packageName: 'preset-react',
|
||||
'/github/package-json/dependency-version/{user}/{repo}/{packageName}/{branch}':
|
||||
{
|
||||
get: {
|
||||
summary: 'GitHub package.json prod dependency version (branch)',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'badges' }),
|
||||
pathParam({ name: 'repo', example: 'shields' }),
|
||||
pathParam({
|
||||
name: 'packageName',
|
||||
example: 'dayjs',
|
||||
description: packageNameDescription,
|
||||
}),
|
||||
pathParam({ name: 'branch', example: 'master' }),
|
||||
queryParam({
|
||||
name: 'filename',
|
||||
example: 'badge-maker/package.json',
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
staticPreview: this.render({
|
||||
dependency: '@babel/preset-react',
|
||||
range: '7.0.0',
|
||||
}),
|
||||
documentation,
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'GitHub package.json dependency version (subfolder of monorepo)',
|
||||
pattern: ':user/:repo/:packageName',
|
||||
namedParams: {
|
||||
user: 'metabolize',
|
||||
repo: 'anafanafo',
|
||||
packageName: 'puppeteer',
|
||||
'/github/package-json/dependency-version/{user}/{repo}/{kind}/{packageName}':
|
||||
{
|
||||
get: {
|
||||
summary: 'GitHub package.json dev/peer/optional dependency version',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'gatsbyjs' }),
|
||||
pathParam({ name: 'repo', example: 'gatsby' }),
|
||||
pathParam({
|
||||
name: 'kind',
|
||||
example: 'dev',
|
||||
schema: { type: 'string', enum: this.getEnum('kind') },
|
||||
}),
|
||||
pathParam({
|
||||
name: 'packageName',
|
||||
example: 'cross-env',
|
||||
description: packageNameDescription,
|
||||
}),
|
||||
queryParam({
|
||||
name: 'filename',
|
||||
example: 'packages/gatsby-cli/package.json',
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
queryParams: {
|
||||
filename: 'packages/char-width-table-builder/package.json',
|
||||
'/github/package-json/dependency-version/{user}/{repo}/{kind}/{packageName}/{branch}':
|
||||
{
|
||||
get: {
|
||||
summary:
|
||||
'GitHub package.json dev/peer/optional dependency version (branch)',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'gatsbyjs' }),
|
||||
pathParam({ name: 'repo', example: 'gatsby' }),
|
||||
pathParam({
|
||||
name: 'kind',
|
||||
example: 'dev',
|
||||
schema: { type: 'string', enum: this.getEnum('kind') },
|
||||
}),
|
||||
pathParam({
|
||||
name: 'packageName',
|
||||
example: 'cross-env',
|
||||
description: packageNameDescription,
|
||||
}),
|
||||
pathParam({ name: 'branch', example: 'master' }),
|
||||
queryParam({
|
||||
name: 'filename',
|
||||
example: 'packages/gatsby-cli/package.json',
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
staticPreview: this.render({
|
||||
dependency: 'puppeteer',
|
||||
range: '^1.14.0',
|
||||
}),
|
||||
documentation,
|
||||
keywords,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'dependency' }
|
||||
|
||||
@@ -200,40 +233,39 @@ class DynamicGithubPackageJson extends ConditionalGithubAuthV3Service {
|
||||
pattern: ':key/:user/:repo/:branch*',
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub package.json dynamic',
|
||||
pattern: ':key/:user/:repo',
|
||||
namedParams: {
|
||||
key: 'keywords',
|
||||
user: 'developit',
|
||||
repo: 'microbundle',
|
||||
static openApi = {
|
||||
'/github/package-json/{key}/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub package.json dynamic',
|
||||
description: documentation,
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'key',
|
||||
example: 'keywords',
|
||||
description: 'any key in package.json',
|
||||
},
|
||||
{ name: 'user', example: 'developit' },
|
||||
{ name: 'repo', example: 'microbundle' },
|
||||
),
|
||||
},
|
||||
staticPreview: this.render({
|
||||
key: 'keywords',
|
||||
value: ['bundle', 'rollup', 'micro library'],
|
||||
}),
|
||||
documentation,
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'GitHub package.json dynamic',
|
||||
pattern: ':key/:user/:repo/:branch',
|
||||
namedParams: {
|
||||
key: 'keywords',
|
||||
user: 'developit',
|
||||
repo: 'microbundle',
|
||||
branch: 'master',
|
||||
'/github/package-json/{key}/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'GitHub package.json dynamic (branch)',
|
||||
description: documentation,
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'key',
|
||||
example: 'keywords',
|
||||
description: 'any key in package.json',
|
||||
},
|
||||
{ name: 'user', example: 'developit' },
|
||||
{ name: 'repo', example: 'microbundle' },
|
||||
{ name: 'branch', example: 'master' },
|
||||
),
|
||||
},
|
||||
staticPreview: this.render({
|
||||
key: 'keywords',
|
||||
value: ['bundle', 'rollup', 'micro library'],
|
||||
branch: 'master',
|
||||
}),
|
||||
documentation,
|
||||
keywords,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'package.json' }
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ import { createServiceTester } from '../tester.js'
|
||||
export const t = await createServiceTester()
|
||||
|
||||
t.create('github pull request check state')
|
||||
.get('/s/pulls/badges/shields/8486.json')
|
||||
.expectBadge({ label: 'checks', message: 'failure' })
|
||||
.get('/s/pulls/badges/shields/9863.json')
|
||||
.expectBadge({ label: 'checks', message: 'success' })
|
||||
|
||||
t.create('github pull request check state (pull request not found)')
|
||||
.get('/s/pulls/badges/shields/5101.json')
|
||||
@@ -26,5 +26,5 @@ t.create(
|
||||
})
|
||||
|
||||
t.create('github pull request check contexts')
|
||||
.get('/contexts/pulls/badges/shields/8486.json')
|
||||
.expectBadge({ label: 'checks', message: '2 success, 4 failure' })
|
||||
.get('/contexts/pulls/badges/shields/9863.json')
|
||||
.expectBadge({ label: 'checks', message: '1 success' })
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Joi from 'joi'
|
||||
import { renderVersionBadge } from '../version.js'
|
||||
import { InvalidResponse } from '../index.js'
|
||||
import { InvalidResponse, pathParam, queryParam } from '../index.js'
|
||||
import { ConditionalGithubAuthV3Service } from './github-auth-service.js'
|
||||
import { fetchRepoContent } from './github-common-fetch.js'
|
||||
import { documentation } from './github-helpers.js'
|
||||
@@ -11,6 +11,9 @@ const queryParamSchema = Joi.object({
|
||||
|
||||
const versionRegExp = /^Version:[\s]*(.+)$/m
|
||||
|
||||
const filenameDescription =
|
||||
'The `filename` param can be used to specify the path to `DESCRIPTION`. By default, we look for `DESCRIPTION` in the repo root'
|
||||
|
||||
export default class GithubRPackageVersion extends ConditionalGithubAuthV3Service {
|
||||
static category = 'version'
|
||||
|
||||
@@ -20,38 +23,39 @@ export default class GithubRPackageVersion extends ConditionalGithubAuthV3Servic
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub R package version',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: { user: 'mixOmicsTeam', repo: 'mixOmics' },
|
||||
staticPreview: this.render({ version: '6.10.9' }),
|
||||
documentation,
|
||||
static openApi = {
|
||||
'/github/r-package/v/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub R package version',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'mixOmicsTeam' }),
|
||||
pathParam({ name: 'repo', example: 'mixOmics' }),
|
||||
queryParam({
|
||||
name: 'filename',
|
||||
example: 'subdirectory/DESCRIPTION',
|
||||
description: filenameDescription,
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'GitHub R package version (branch)',
|
||||
pattern: ':user/:repo/:branch',
|
||||
namedParams: { user: 'mixOmicsTeam', repo: 'mixOmics', branch: 'master' },
|
||||
staticPreview: this.render({ version: '6.10.9', branch: 'master' }),
|
||||
documentation,
|
||||
'/github/r-package/v/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'GitHub R package version (branch)',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'mixOmicsTeam' }),
|
||||
pathParam({ name: 'repo', example: 'mixOmics' }),
|
||||
pathParam({ name: 'branch', example: 'master' }),
|
||||
queryParam({
|
||||
name: 'filename',
|
||||
example: 'subdirectory/DESCRIPTION',
|
||||
description: filenameDescription,
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'GitHub R package version (subdirectory of monorepo)',
|
||||
pattern: ':user/:repo',
|
||||
namedParams: { user: 'mixOmicsTeam', repo: 'mixOmics' },
|
||||
queryParams: { filename: 'subdirectory/DESCRIPTION' },
|
||||
staticPreview: this.render({ version: '6.10.9' }),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub R package version (branch & subdirectory of monorepo)',
|
||||
pattern: ':user/:repo/:branch',
|
||||
namedParams: { user: 'mixOmicsTeam', repo: 'mixOmics', branch: 'master' },
|
||||
queryParams: { filename: 'subdirectory/DESCRIPTION' },
|
||||
staticPreview: this.render({ version: '6.10.9', branch: 'master' }),
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'R' }
|
||||
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
import Joi from 'joi'
|
||||
import { addv } from '../text-formatters.js'
|
||||
import { version as versionColor } from '../color-formatters.js'
|
||||
import { redirector } from '../index.js'
|
||||
import { redirector, pathParam, queryParam } from '../index.js'
|
||||
import { GithubAuthV3Service } from './github-auth-service.js'
|
||||
import {
|
||||
fetchLatestRelease,
|
||||
filterDocs,
|
||||
queryParamSchema,
|
||||
openApiQueryParams,
|
||||
} from './github-common-release.js'
|
||||
import { documentation } from './github-helpers.js'
|
||||
|
||||
const displayNameEnum = ['tag', 'release']
|
||||
const extendedQueryParamSchema = Joi.object({
|
||||
display_name: Joi.string().valid('tag', 'release').default('tag'),
|
||||
display_name: Joi.string()
|
||||
.valid(...displayNameEnum)
|
||||
.default('tag'),
|
||||
})
|
||||
|
||||
class GithubRelease extends GithubAuthV3Service {
|
||||
@@ -22,86 +25,24 @@ class GithubRelease extends GithubAuthV3Service {
|
||||
queryParamSchema: queryParamSchema.concat(extendedQueryParamSchema),
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub release (latest by date)',
|
||||
namedParams: { user: 'expressjs', repo: 'express' },
|
||||
queryParams: { display_name: 'tag' },
|
||||
staticPreview: this.render({
|
||||
version: 'v4.16.4',
|
||||
sort: 'date',
|
||||
isPrerelease: false,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub release (latest by date including pre-releases)',
|
||||
namedParams: { user: 'expressjs', repo: 'express' },
|
||||
queryParams: { include_prereleases: null, display_name: 'tag' },
|
||||
staticPreview: this.render({
|
||||
version: 'v5.0.0-alpha.7',
|
||||
sort: 'date',
|
||||
isPrerelease: true,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub release (latest SemVer)',
|
||||
namedParams: { user: 'expressjs', repo: 'express' },
|
||||
queryParams: { sort: 'semver', display_name: 'tag' },
|
||||
staticPreview: this.render({
|
||||
version: 'v4.16.4',
|
||||
sort: 'semver',
|
||||
isPrerelease: false,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub release (latest SemVer including pre-releases)',
|
||||
namedParams: { user: 'expressjs', repo: 'express' },
|
||||
queryParams: {
|
||||
sort: 'semver',
|
||||
include_prereleases: null,
|
||||
display_name: 'tag',
|
||||
static openApi = {
|
||||
'/github/v/release/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub Release',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'expressjs' }),
|
||||
pathParam({ name: 'repo', example: 'express' }),
|
||||
...openApiQueryParams,
|
||||
queryParam({
|
||||
name: 'display_name',
|
||||
example: 'tag',
|
||||
schema: { type: 'string', enum: displayNameEnum },
|
||||
}),
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
version: 'v5.0.0-alpha.7',
|
||||
sort: 'semver',
|
||||
isPrerelease: true,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub release (release name instead of tag name)',
|
||||
namedParams: { user: 'gooddata', repo: 'gooddata-java' },
|
||||
queryParams: {
|
||||
sort: 'date',
|
||||
include_prereleases: null,
|
||||
display_name: 'release',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
version: '3.7.0+api3',
|
||||
sort: 'date',
|
||||
isPrerelease: true,
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub release (with filter)',
|
||||
namedParams: { user: 'RetroMusicPlayer', repo: 'RetroMusicPlayer' },
|
||||
queryParams: {
|
||||
sort: 'date',
|
||||
display_name: 'release',
|
||||
filter: '*Open Beta',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
version: 'Release v6.0.2 - Open Beta',
|
||||
sort: 'date',
|
||||
isPrerelease: false,
|
||||
}),
|
||||
documentation: documentation + filterDocs,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'release', namedLogo: 'github' }
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Joi from 'joi'
|
||||
import prettyBytes from 'pretty-bytes'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { NotFound } from '../index.js'
|
||||
import { NotFound, pathParam, queryParam } from '../index.js'
|
||||
import { GithubAuthV3Service } from './github-auth-service.js'
|
||||
import { documentation, httpErrorsFor } from './github-helpers.js'
|
||||
|
||||
@@ -25,33 +25,24 @@ export default class GithubSize extends GithubAuthV3Service {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub file size in bytes',
|
||||
namedParams: {
|
||||
user: 'webcaetano',
|
||||
repo: 'craft',
|
||||
path: 'build/phaser-craft.min.js',
|
||||
},
|
||||
staticPreview: this.render({ size: 9170 }),
|
||||
keywords: ['repo'],
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub file size in bytes on a specified ref (branch/commit/tag)',
|
||||
namedParams: {
|
||||
user: 'webcaetano',
|
||||
repo: 'craft',
|
||||
path: 'build/phaser-craft.min.js',
|
||||
},
|
||||
staticPreview: this.render({ size: 9170 }),
|
||||
keywords: ['repo'],
|
||||
documentation,
|
||||
queryParams: {
|
||||
branch: 'master',
|
||||
static openApi = {
|
||||
'/github/size/{user}/{repo}/{path}': {
|
||||
get: {
|
||||
summary: 'GitHub file size in bytes',
|
||||
description: documentation,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'webcaetano' }),
|
||||
pathParam({ name: 'repo', example: 'craft' }),
|
||||
pathParam({ name: 'path', example: 'build/phaser-craft.min.js' }),
|
||||
queryParam({
|
||||
name: 'branch',
|
||||
example: 'master',
|
||||
description: 'Can be a branch, a tag or a commit hash.',
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static render({ size }) {
|
||||
return {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Joi from 'joi'
|
||||
import { pathParams } from '../index.js'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { GithubAuthV3Service } from './github-auth-service.js'
|
||||
@@ -16,24 +17,18 @@ export default class GithubStars extends GithubAuthV3Service {
|
||||
pattern: ':user/:repo',
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub Repo stars',
|
||||
namedParams: {
|
||||
user: 'badges',
|
||||
repo: 'shields',
|
||||
static openApi = {
|
||||
'/github/stars/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub Repo stars',
|
||||
description: documentation,
|
||||
parameters: pathParams(
|
||||
{ name: 'user', example: 'badges' },
|
||||
{ name: 'repo', example: 'shields' },
|
||||
),
|
||||
},
|
||||
queryParams: { style: 'social' },
|
||||
// TODO: This is currently a literal, as `staticPreview` doesn't
|
||||
// support `link`.
|
||||
staticPreview: {
|
||||
label: 'Stars',
|
||||
message: '7k',
|
||||
style: 'social',
|
||||
},
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = {
|
||||
label: 'stars',
|
||||
|
||||
@@ -4,9 +4,12 @@ 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 } from '../index.js'
|
||||
import { NotFound, redirector, pathParam } from '../index.js'
|
||||
import { GithubAuthV4Service } from './github-auth-service.js'
|
||||
import { filterDocs, queryParamSchema } from './github-common-release.js'
|
||||
import {
|
||||
queryParamSchema,
|
||||
openApiQueryParams,
|
||||
} from './github-common-release.js'
|
||||
import { documentation, transformErrors } from './github-helpers.js'
|
||||
|
||||
const schema = Joi.object({
|
||||
@@ -34,44 +37,19 @@ class GithubTag extends GithubAuthV4Service {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub tag (latest by date)',
|
||||
namedParams: { user: 'expressjs', repo: 'express' },
|
||||
staticPreview: this.render({
|
||||
version: 'v5.0.0-alpha.7',
|
||||
sort: 'date',
|
||||
}),
|
||||
documentation,
|
||||
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,
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'GitHub tag (latest SemVer)',
|
||||
namedParams: { user: 'expressjs', repo: 'express' },
|
||||
queryParams: { sort: 'semver' },
|
||||
staticPreview: this.render({ version: 'v4.16.4', sort: 'semver' }),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub tag (latest SemVer pre-release)',
|
||||
namedParams: { user: 'expressjs', repo: 'express' },
|
||||
queryParams: { sort: 'semver', include_prereleases: null },
|
||||
staticPreview: this.render({
|
||||
version: 'v5.0.0-alpha.7',
|
||||
sort: 'semver',
|
||||
}),
|
||||
documentation,
|
||||
},
|
||||
{
|
||||
title: 'GitHub tag (with filter)',
|
||||
namedParams: { user: 'badges', repo: 'shields' },
|
||||
queryParams: { filter: '!server-*' },
|
||||
staticPreview: this.render({
|
||||
version: 'v3.3.1',
|
||||
sort: 'date',
|
||||
}),
|
||||
documentation: documentation + filterDocs,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = {
|
||||
label: 'tag',
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Joi from 'joi'
|
||||
import gql from 'graphql-tag'
|
||||
import { pathParam, queryParam } from '../index.js'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { GithubAuthV4Service } from './github-auth-service.js'
|
||||
@@ -10,22 +11,15 @@ import {
|
||||
|
||||
const MAX_REPO_LIMIT = 200
|
||||
|
||||
const customDocumentation = `This badge takes into account up to <code>${MAX_REPO_LIMIT}</code> of the most starred repositories of given user / org.`
|
||||
|
||||
const userDocumentation = `${commonDocumentation}
|
||||
const description = `${commonDocumentation}
|
||||
<p>
|
||||
<b>Note:</b><br>
|
||||
1. ${customDocumentation}<br>
|
||||
2. <code>affiliations</code> query param accepts three values (must be UPPER case) <code>OWNER</code>, <code>COLLABORATOR</code>, <code>ORGANIZATION_MEMBER</code>.
|
||||
One can pass comma separated combinations of these values (no spaces) e.g. <code>OWNER,COLLABORATOR</code> or <code>OWNER,COLLABORATOR,ORGANIZATION_MEMBER</code>.
|
||||
Default value is <code>OWNER</code>. See the explanation of these values <a href="https://docs.github.com/en/graphql/reference/enums#repositoryaffiliation">here</a>.
|
||||
</p>
|
||||
`
|
||||
const orgDocumentation = `${commonDocumentation}
|
||||
<p>
|
||||
<b>Note:</b> ${customDocumentation}
|
||||
<b>Note:</b> This badge takes into account up to <code>${MAX_REPO_LIMIT}</code> of the most starred repositories of given user / org.
|
||||
</p>`
|
||||
|
||||
const affiliationsDescription = `This param accepts three values (must be UPPER case) <code>OWNER</code>, <code>COLLABORATOR</code>, <code>ORGANIZATION_MEMBER</code>.
|
||||
One can pass comma separated combinations of these values (no spaces) e.g. <code>OWNER,COLLABORATOR</code> or <code>OWNER,COLLABORATOR,ORGANIZATION_MEMBER</code>.
|
||||
Default value is <code>OWNER</code>. See the explanation of these values <a href="https://docs.github.com/en/graphql/reference/enums#repositoryaffiliation">here</a>.`
|
||||
|
||||
const pageInfoSchema = Joi.object({
|
||||
hasNextPage: Joi.boolean().required(),
|
||||
endCursor: Joi.string().allow(null).required(),
|
||||
@@ -141,34 +135,29 @@ export default class GithubTotalStarService extends GithubAuthV4Service {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: "GitHub User's stars",
|
||||
namedParams: {
|
||||
user: 'chris48s',
|
||||
static openApi = {
|
||||
'/github/stars/{user}': {
|
||||
get: {
|
||||
summary: "GitHub User's stars",
|
||||
description,
|
||||
parameters: [
|
||||
pathParam({ name: 'user', example: 'chris48s' }),
|
||||
queryParam({
|
||||
name: 'affiliations',
|
||||
example: 'OWNER,COLLABORATOR',
|
||||
description: affiliationsDescription,
|
||||
}),
|
||||
],
|
||||
},
|
||||
queryParams: { affiliations: 'OWNER,COLLABORATOR' },
|
||||
staticPreview: {
|
||||
label: this.defaultLabel,
|
||||
message: 54,
|
||||
style: 'social',
|
||||
},
|
||||
documentation: userDocumentation,
|
||||
},
|
||||
{
|
||||
title: "GitHub Org's stars",
|
||||
pattern: ':org',
|
||||
namedParams: {
|
||||
org: 'badges',
|
||||
'/github/stars/{org}': {
|
||||
get: {
|
||||
summary: "GitHub Org's stars",
|
||||
description,
|
||||
parameters: [pathParam({ name: 'org', example: 'badges' })],
|
||||
},
|
||||
staticPreview: {
|
||||
label: this.defaultLabel,
|
||||
message: metric(7000),
|
||||
style: 'social',
|
||||
},
|
||||
documentation: orgDocumentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = {
|
||||
label: this.defaultLabel,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Joi from 'joi'
|
||||
import { pathParams } from '../index.js'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { GithubAuthV3Service } from './github-auth-service.js'
|
||||
@@ -16,24 +17,18 @@ export default class GithubWatchers extends GithubAuthV3Service {
|
||||
pattern: ':user/:repo',
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'GitHub watchers',
|
||||
namedParams: {
|
||||
user: 'badges',
|
||||
repo: 'shields',
|
||||
static openApi = {
|
||||
'/github/watchers/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'GitHub watchers',
|
||||
description: documentation,
|
||||
parameters: pathParams(
|
||||
{ name: 'user', example: 'badges' },
|
||||
{ name: 'repo', example: 'shields' },
|
||||
),
|
||||
},
|
||||
// TODO: This is currently a literal, as `staticPreview` doesn't
|
||||
// support `link`.
|
||||
staticPreview: {
|
||||
label: 'Watch',
|
||||
message: '96',
|
||||
style: 'social',
|
||||
},
|
||||
queryParams: { label: 'Watch' },
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = {
|
||||
label: 'watchers',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { redirector } from '../index.js'
|
||||
import { documentation } from '../maven-metadata/maven-metadata.js'
|
||||
import { redirector, pathParam, queryParam } from '../index.js'
|
||||
import { description } from '../maven-metadata/maven-metadata.js'
|
||||
|
||||
export default redirector({
|
||||
category: 'version',
|
||||
@@ -8,24 +8,27 @@ export default redirector({
|
||||
base: 'gradle-plugin-portal/v',
|
||||
pattern: ':pluginId',
|
||||
},
|
||||
examples: [
|
||||
{
|
||||
title: 'Gradle Plugin Portal',
|
||||
queryParams: {
|
||||
versionSuffix: '.1',
|
||||
versionPrefix: '0.10',
|
||||
openApi: {
|
||||
'/gradle-plugin-portal/v/{pluginId}': {
|
||||
get: {
|
||||
summary: 'Gradle Plugin Portal Version',
|
||||
description,
|
||||
parameters: [
|
||||
pathParam({ name: 'pluginId', example: 'com.gradle.plugin-publish' }),
|
||||
queryParam({
|
||||
name: 'versionPrefix',
|
||||
example: '0.10',
|
||||
description: 'Filter only versions with this prefix.',
|
||||
}),
|
||||
queryParam({
|
||||
name: 'versionSuffix',
|
||||
example: '.1',
|
||||
description: 'Filter only versions with this suffix.',
|
||||
}),
|
||||
],
|
||||
},
|
||||
namedParams: {
|
||||
pluginId: 'com.gradle.plugin-publish',
|
||||
},
|
||||
staticPreview: {
|
||||
label: 'plugin portal',
|
||||
message: 'v0.10.1',
|
||||
color: 'blue',
|
||||
},
|
||||
documentation,
|
||||
},
|
||||
],
|
||||
},
|
||||
transformPath: () => '/maven-metadata/v',
|
||||
transformQueryParams: ({ pluginId }) => {
|
||||
const groupPath = pluginId.replace(/\./g, '/')
|
||||
|
||||
37
services/hangar/hangar-base.js
Normal file
37
services/hangar/hangar-base.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import Joi from 'joi'
|
||||
import { BaseJsonService } from '../index.js'
|
||||
|
||||
const description = `
|
||||
<p><a href="https://hangar.papermc.io/">Hangar</a> is a plugin repository for the Paper, Waterfall and Folia platforms.</p>`
|
||||
|
||||
const resourceSchema = Joi.object({
|
||||
stats: Joi.object({
|
||||
views: Joi.number().required(),
|
||||
downloads: Joi.number().required(),
|
||||
recentViews: Joi.number().required(),
|
||||
recentDownloads: Joi.number().required(),
|
||||
stars: Joi.number().required(),
|
||||
watchers: Joi.number().required(),
|
||||
}).required(),
|
||||
}).required()
|
||||
|
||||
class BaseHangarService extends BaseJsonService {
|
||||
static _cacheLength = 3600
|
||||
|
||||
async fetch({
|
||||
slug,
|
||||
schema = resourceSchema,
|
||||
url = `https://hangar.papermc.io/api/v1/projects/${slug}`,
|
||||
}) {
|
||||
return this._requestJson({
|
||||
schema,
|
||||
url,
|
||||
httpErrors: {
|
||||
401: 'Api session missing, invalid or expired',
|
||||
403: 'Not enough permission to use this endpoint',
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export { description, BaseHangarService }
|
||||
34
services/hangar/hangar-downloads.service.js
Normal file
34
services/hangar/hangar-downloads.service.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import { pathParams } from '../index.js'
|
||||
import { renderDownloadsBadge } from '../downloads.js'
|
||||
import { BaseHangarService, description } from './hangar-base.js'
|
||||
|
||||
export default class HangarDownloads extends BaseHangarService {
|
||||
static category = 'downloads'
|
||||
|
||||
static route = {
|
||||
base: 'hangar/dt',
|
||||
pattern: ':slug',
|
||||
}
|
||||
|
||||
static openApi = {
|
||||
'/hangar/dt/{slug}': {
|
||||
get: {
|
||||
summary: 'Hangar Downloads',
|
||||
description,
|
||||
parameters: pathParams({
|
||||
name: 'slug',
|
||||
example: 'Essentials',
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'downloads' }
|
||||
|
||||
async handle({ slug }) {
|
||||
const {
|
||||
stats: { downloads },
|
||||
} = await this.fetch({ slug })
|
||||
return renderDownloadsBadge({ downloads })
|
||||
}
|
||||
}
|
||||
13
services/hangar/hangar-downloads.tester.js
Normal file
13
services/hangar/hangar-downloads.tester.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import { isMetric } from '../test-validators.js'
|
||||
import { createServiceTester } from '../tester.js'
|
||||
export const t = await createServiceTester()
|
||||
|
||||
t.create('Essentials').get('/Essentials.json').expectBadge({
|
||||
label: 'downloads',
|
||||
message: isMetric,
|
||||
})
|
||||
|
||||
t.create('Invalid Resource').get('/1.json').expectBadge({
|
||||
label: 'downloads',
|
||||
message: 'not found',
|
||||
})
|
||||
43
services/hangar/hangar-stars.service.js
Normal file
43
services/hangar/hangar-stars.service.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import { pathParams } from '../index.js'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { BaseHangarService, description } from './hangar-base.js'
|
||||
|
||||
export default class HangarStars extends BaseHangarService {
|
||||
static category = 'social'
|
||||
|
||||
static route = {
|
||||
base: 'hangar/stars',
|
||||
pattern: ':slug',
|
||||
}
|
||||
|
||||
static openApi = {
|
||||
'/hangar/stars/{slug}': {
|
||||
get: {
|
||||
summary: 'Hangar Stars',
|
||||
description,
|
||||
parameters: pathParams({
|
||||
name: 'slug',
|
||||
example: 'Essentials',
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
static defaultBadgeData = {
|
||||
label: 'stars',
|
||||
color: 'blue',
|
||||
}
|
||||
|
||||
static render({ stars }) {
|
||||
return {
|
||||
message: metric(stars),
|
||||
}
|
||||
}
|
||||
|
||||
async handle({ slug }) {
|
||||
const {
|
||||
stats: { stars },
|
||||
} = await this.fetch({ slug })
|
||||
return this.constructor.render({ stars })
|
||||
}
|
||||
}
|
||||
13
services/hangar/hangar-stars.tester.js
Normal file
13
services/hangar/hangar-stars.tester.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import { isMetric } from '../test-validators.js'
|
||||
import { createServiceTester } from '../tester.js'
|
||||
export const t = await createServiceTester()
|
||||
|
||||
t.create('Essentials').get('/Essentials.json').expectBadge({
|
||||
label: 'stars',
|
||||
message: isMetric,
|
||||
})
|
||||
|
||||
t.create('Invalid Resource').get('/1.json').expectBadge({
|
||||
label: 'stars',
|
||||
message: 'not found',
|
||||
})
|
||||
43
services/hangar/hangar-views.service.js
Normal file
43
services/hangar/hangar-views.service.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import { pathParams } from '../index.js'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { BaseHangarService, description } from './hangar-base.js'
|
||||
|
||||
export default class HangarViews extends BaseHangarService {
|
||||
static category = 'other'
|
||||
|
||||
static route = {
|
||||
base: 'hangar/views',
|
||||
pattern: ':slug',
|
||||
}
|
||||
|
||||
static openApi = {
|
||||
'/hangar/views/{slug}': {
|
||||
get: {
|
||||
summary: 'Hangar Views',
|
||||
description,
|
||||
parameters: pathParams({
|
||||
name: 'slug',
|
||||
example: 'Essentials',
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
static defaultBadgeData = {
|
||||
label: 'views',
|
||||
color: 'blue',
|
||||
}
|
||||
|
||||
static render({ views }) {
|
||||
return {
|
||||
message: metric(views),
|
||||
}
|
||||
}
|
||||
|
||||
async handle({ slug }) {
|
||||
const {
|
||||
stats: { views },
|
||||
} = await this.fetch({ slug })
|
||||
return this.constructor.render({ views })
|
||||
}
|
||||
}
|
||||
13
services/hangar/hangar-views.tester.js
Normal file
13
services/hangar/hangar-views.tester.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import { isMetric } from '../test-validators.js'
|
||||
import { createServiceTester } from '../tester.js'
|
||||
export const t = await createServiceTester()
|
||||
|
||||
t.create('Essentials').get('/Essentials.json').expectBadge({
|
||||
label: 'views',
|
||||
message: isMetric,
|
||||
})
|
||||
|
||||
t.create('Invalid Resource').get('/1.json').expectBadge({
|
||||
label: 'views',
|
||||
message: 'not found',
|
||||
})
|
||||
43
services/hangar/hangar-watchers.service.js
Normal file
43
services/hangar/hangar-watchers.service.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import { pathParams } from '../index.js'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { BaseHangarService, description } from './hangar-base.js'
|
||||
|
||||
export default class HangarWatchers extends BaseHangarService {
|
||||
static category = 'social'
|
||||
|
||||
static route = {
|
||||
base: 'hangar/watchers',
|
||||
pattern: ':slug',
|
||||
}
|
||||
|
||||
static openApi = {
|
||||
'/hangar/watchers/{slug}': {
|
||||
get: {
|
||||
summary: 'Hangar Watchers',
|
||||
description,
|
||||
parameters: pathParams({
|
||||
name: 'slug',
|
||||
example: 'Essentials',
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
static defaultBadgeData = {
|
||||
label: 'watchers',
|
||||
color: 'blue',
|
||||
}
|
||||
|
||||
static render({ watchers }) {
|
||||
return {
|
||||
message: metric(watchers),
|
||||
}
|
||||
}
|
||||
|
||||
async handle({ slug }) {
|
||||
const {
|
||||
stats: { watchers },
|
||||
} = await this.fetch({ slug })
|
||||
return this.constructor.render({ watchers })
|
||||
}
|
||||
}
|
||||
13
services/hangar/hangar-watchers.tester.js
Normal file
13
services/hangar/hangar-watchers.tester.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import { isMetric } from '../test-validators.js'
|
||||
import { createServiceTester } from '../tester.js'
|
||||
export const t = await createServiceTester()
|
||||
|
||||
t.create('Essentials').get('/Essentials.json').expectBadge({
|
||||
label: 'watchers',
|
||||
message: isMetric,
|
||||
})
|
||||
|
||||
t.create('Invalid Resource').get('/1.json').expectBadge({
|
||||
label: 'watchers',
|
||||
message: 'not found',
|
||||
})
|
||||
@@ -1,18 +1,16 @@
|
||||
import Joi from 'joi'
|
||||
import { BaseJsonService, InvalidResponse } from '../index.js'
|
||||
import {
|
||||
BaseJsonService,
|
||||
InvalidResponse,
|
||||
queryParam,
|
||||
pathParam,
|
||||
} from '../index.js'
|
||||
import { coveragePercentage } from '../color-formatters.js'
|
||||
|
||||
const keywords = [
|
||||
'l10n',
|
||||
'i18n',
|
||||
'localization',
|
||||
'internationalization',
|
||||
'translation',
|
||||
'translations',
|
||||
]
|
||||
|
||||
const documentation = `
|
||||
const description = `
|
||||
<p>
|
||||
<a href="https://localizely.com/" target="_blank">Localizely</a> is a management system for translation, localization, and internationalization of your projects.
|
||||
<br/>
|
||||
The <b>read-only</b> API token from the Localizely account is required to fetch necessary data.
|
||||
<br/>
|
||||
<br/>
|
||||
@@ -58,40 +56,58 @@ export default class Localizely extends BaseJsonService {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'Localizely overall progress',
|
||||
keywords,
|
||||
documentation,
|
||||
namedParams: {
|
||||
projectId: '5cc34208-0418-40b1-8353-acc70c95f802',
|
||||
branch: 'main',
|
||||
static openApi = {
|
||||
'/localizely/progress/{projectId}': {
|
||||
get: {
|
||||
summary: 'Localizely progress',
|
||||
description,
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'projectId',
|
||||
example: '5cc34208-0418-40b1-8353-acc70c95f802',
|
||||
}),
|
||||
queryParam({
|
||||
name: 'token',
|
||||
example:
|
||||
'0f4d5e31a44f48dcbab966c52cfb0a67c5f1982186c14b85ab389a031dbc225a',
|
||||
required: true,
|
||||
}),
|
||||
queryParam({
|
||||
name: 'languageCode',
|
||||
example: 'en-US',
|
||||
required: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
queryParams: {
|
||||
token:
|
||||
'0f4d5e31a44f48dcbab966c52cfb0a67c5f1982186c14b85ab389a031dbc225a',
|
||||
},
|
||||
staticPreview: this.render({ reviewedProgress: 93 }),
|
||||
},
|
||||
{
|
||||
title: 'Localizely language progress',
|
||||
keywords,
|
||||
documentation,
|
||||
namedParams: {
|
||||
projectId: '5cc34208-0418-40b1-8353-acc70c95f802',
|
||||
branch: 'main',
|
||||
'/localizely/progress/{projectId}/{branch}': {
|
||||
get: {
|
||||
summary: 'Localizely progress (branch)',
|
||||
description,
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'projectId',
|
||||
example: '5cc34208-0418-40b1-8353-acc70c95f802',
|
||||
}),
|
||||
pathParam({
|
||||
name: 'branch',
|
||||
example: 'main',
|
||||
}),
|
||||
queryParam({
|
||||
name: 'token',
|
||||
example:
|
||||
'0f4d5e31a44f48dcbab966c52cfb0a67c5f1982186c14b85ab389a031dbc225a',
|
||||
required: true,
|
||||
}),
|
||||
queryParam({
|
||||
name: 'languageCode',
|
||||
example: 'en-US',
|
||||
required: false,
|
||||
}),
|
||||
],
|
||||
},
|
||||
queryParams: {
|
||||
token:
|
||||
'0f4d5e31a44f48dcbab966c52cfb0a67c5f1982186c14b85ab389a031dbc225a',
|
||||
languageCode: 'en-US',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
langName: 'English (US)',
|
||||
reviewedProgress: 97,
|
||||
}),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'localized' }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { redirector } from '../index.js'
|
||||
import { documentation } from '../maven-metadata/maven-metadata.js'
|
||||
import { redirector, pathParam, queryParam } from '../index.js'
|
||||
import { description } from '../maven-metadata/maven-metadata.js'
|
||||
|
||||
export default redirector({
|
||||
category: 'version',
|
||||
@@ -8,26 +8,28 @@ export default redirector({
|
||||
base: 'maven-central/v',
|
||||
pattern: ':groupId/:artifactId/:versionPrefix?',
|
||||
},
|
||||
examples: [
|
||||
{
|
||||
title: 'Maven Central',
|
||||
pattern: ':groupId/:artifactId',
|
||||
queryParams: {
|
||||
versionSuffix: '-android',
|
||||
versionPrefix: '29',
|
||||
openApi: {
|
||||
'/maven-central/v/{groupId}/{artifactId}': {
|
||||
get: {
|
||||
summary: 'Maven Central Version',
|
||||
description,
|
||||
parameters: [
|
||||
pathParam({ name: 'groupId', example: 'com.google.guava' }),
|
||||
pathParam({ name: 'artifactId', example: 'guava' }),
|
||||
queryParam({
|
||||
name: 'versionPrefix',
|
||||
example: '29',
|
||||
description: 'Filter only versions with this prefix.',
|
||||
}),
|
||||
queryParam({
|
||||
name: 'versionSuffix',
|
||||
example: '-android',
|
||||
description: 'Filter only versions with this suffix.',
|
||||
}),
|
||||
],
|
||||
},
|
||||
namedParams: {
|
||||
groupId: 'com.google.guava',
|
||||
artifactId: 'guava',
|
||||
},
|
||||
staticPreview: {
|
||||
label: 'maven-central',
|
||||
message: 'v29.0-android',
|
||||
color: 'blue',
|
||||
},
|
||||
documentation,
|
||||
},
|
||||
],
|
||||
},
|
||||
transformPath: () => '/maven-metadata/v',
|
||||
transformQueryParams: ({ groupId, artifactId, versionPrefix }) => {
|
||||
const group = encodeURIComponent(groupId).replace(/\./g, '/')
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
// the file contains common constants for badges uses maven-metadata
|
||||
|
||||
export const documentation = `
|
||||
export const description = `
|
||||
<p>
|
||||
<code>versionPrefix</code> and <code>versionSuffix</code> allow narrowing down
|
||||
the range of versions the badge will take into account,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import Joi from 'joi'
|
||||
import { optionalUrl } from '../validators.js'
|
||||
import { renderVersionBadge } from '../version.js'
|
||||
import { BaseXmlService, NotFound } from '../index.js'
|
||||
import { documentation } from './maven-metadata.js'
|
||||
import { BaseXmlService, NotFound, queryParams } from '../index.js'
|
||||
import { description } from './maven-metadata.js'
|
||||
|
||||
const queryParamSchema = Joi.object({
|
||||
metadataUrl: optionalUrl.required(),
|
||||
@@ -29,20 +29,32 @@ export default class MavenMetadata extends BaseXmlService {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'Maven metadata URL',
|
||||
namedParams: {},
|
||||
queryParams: {
|
||||
metadataUrl:
|
||||
'https://repo1.maven.org/maven2/com/google/guava/guava/maven-metadata.xml',
|
||||
versionPrefix: '29.',
|
||||
versionSuffix: '-android',
|
||||
static openApi = {
|
||||
'/maven-metadata/v': {
|
||||
get: {
|
||||
summary: 'Maven metadata URL',
|
||||
description,
|
||||
parameters: queryParams(
|
||||
{
|
||||
name: 'metadataUrl',
|
||||
example:
|
||||
'https://repo1.maven.org/maven2/com/google/guava/guava/maven-metadata.xml',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'versionPrefix',
|
||||
example: '29',
|
||||
description: 'Filter only versions with this prefix.',
|
||||
},
|
||||
{
|
||||
name: 'versionSuffix',
|
||||
example: '-android',
|
||||
description: 'Filter only versions with this suffix.',
|
||||
},
|
||||
),
|
||||
},
|
||||
staticPreview: renderVersionBadge({ version: '29.0-android' }),
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = {
|
||||
label: 'maven',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Joi from 'joi'
|
||||
import { BaseJsonService } from '../index.js'
|
||||
import { BaseJsonService, queryParam, pathParam } from '../index.js'
|
||||
|
||||
const schema = Joi.object({
|
||||
state: Joi.string()
|
||||
@@ -25,11 +25,13 @@ const queryParamSchema = Joi.object({
|
||||
publish: Joi.equal(''),
|
||||
}).required()
|
||||
|
||||
const documentation = `
|
||||
const description = `
|
||||
The [Mozilla HTTP Observatory](https://observatory.mozilla.org)
|
||||
is a set of tools to analyze your website
|
||||
is a set of security tools to analyze your website
|
||||
and inform you if you are utilizing the many available methods to secure it.
|
||||
`
|
||||
|
||||
const publishDescription = `
|
||||
By default the scan result is hidden from the public result list.
|
||||
You can activate the publication of the scan result
|
||||
by setting the \`publish\` parameter.
|
||||
@@ -50,21 +52,31 @@ export default class MozillaObservatory extends BaseJsonService {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'Mozilla HTTP Observatory Grade',
|
||||
namedParams: { format: 'grade', host: 'github.com' },
|
||||
staticPreview: this.render({
|
||||
format: 'grade',
|
||||
state: 'FINISHED',
|
||||
grade: 'A+',
|
||||
score: 115,
|
||||
}),
|
||||
queryParams: { publish: null },
|
||||
keywords: ['scanner', 'security'],
|
||||
documentation,
|
||||
static openApi = {
|
||||
'/mozilla-observatory/{format}/{host}': {
|
||||
get: {
|
||||
summary: 'Mozilla HTTP Observatory Grade',
|
||||
description,
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'format',
|
||||
example: 'grade',
|
||||
schema: { type: 'string', enum: this.getEnum('format') },
|
||||
}),
|
||||
pathParam({
|
||||
name: 'host',
|
||||
example: 'github.com',
|
||||
}),
|
||||
queryParam({
|
||||
name: 'publish',
|
||||
schema: { type: 'boolean' },
|
||||
example: null,
|
||||
description: publishDescription,
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = {
|
||||
label: 'observatory',
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { pathParams } from '../index.js'
|
||||
import { createServiceFamily } from '../nuget/nuget-v3-service-family.js'
|
||||
|
||||
const { NugetVersionService: Version, NugetDownloadService: Downloads } =
|
||||
@@ -8,51 +9,73 @@ const { NugetVersionService: Version, NugetDownloadService: Downloads } =
|
||||
})
|
||||
|
||||
class MyGetVersionService extends Version {
|
||||
static examples = [
|
||||
{
|
||||
title: 'MyGet',
|
||||
pattern: 'myget/:feed/v/:packageName',
|
||||
namedParams: { feed: 'mongodb', packageName: 'MongoDB.Driver.Core' },
|
||||
staticPreview: this.render({ version: '2.6.1' }),
|
||||
},
|
||||
{
|
||||
title: 'MyGet (with prereleases)',
|
||||
pattern: 'myget/:feed/vpre/:packageName',
|
||||
namedParams: { feed: 'mongodb', packageName: 'MongoDB.Driver.Core' },
|
||||
staticPreview: this.render({ version: '2.7.0-beta0001' }),
|
||||
},
|
||||
{
|
||||
title: 'MyGet tenant',
|
||||
pattern: ':tenant.myget/:feed/v/:packageName',
|
||||
namedParams: {
|
||||
tenant: 'tizen',
|
||||
feed: 'dotnet',
|
||||
packageName: 'Tizen.NET',
|
||||
static openApi = {
|
||||
'/myget/{feed}/{variant}/{packageName}': {
|
||||
get: {
|
||||
summary: 'MyGet Version',
|
||||
parameters: pathParams(
|
||||
{ name: 'feed', example: 'mongodb' },
|
||||
{
|
||||
name: 'variant',
|
||||
example: 'v',
|
||||
schema: { type: 'variant', enum: ['v', 'vpre'] },
|
||||
description:
|
||||
'Latest stable version (`v`) or Latest version including prereleases (`vpre`).',
|
||||
},
|
||||
{ name: 'packageName', example: 'MongoDB.Driver.Core' },
|
||||
),
|
||||
},
|
||||
staticPreview: this.render({ version: '9.0.0.16564' }),
|
||||
},
|
||||
]
|
||||
'/{tenant}/{feed}/{variant}/{packageName}': {
|
||||
get: {
|
||||
summary: 'MyGet Version (tenant)',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'tenant',
|
||||
example: 'tizen.myget',
|
||||
description: 'MyGet Tenant in the format `name.myget`',
|
||||
},
|
||||
{ name: 'feed', example: 'dotnet' },
|
||||
{
|
||||
name: 'variant',
|
||||
example: 'v',
|
||||
schema: { type: 'variant', enum: ['v', 'vpre'] },
|
||||
description:
|
||||
'Latest stable version (`v`) or Latest version including prereleases (`vpre`).',
|
||||
},
|
||||
{ name: 'packageName', example: 'Tizen.NET' },
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
class MyGetDownloadService extends Downloads {
|
||||
static examples = [
|
||||
{
|
||||
title: 'MyGet',
|
||||
pattern: 'myget/:feed/dt/:packageName',
|
||||
namedParams: { feed: 'mongodb', packageName: 'MongoDB.Driver.Core' },
|
||||
staticPreview: this.render({ downloads: 419 }),
|
||||
},
|
||||
{
|
||||
title: 'MyGet tenant',
|
||||
pattern: ':tenant.myget/:feed/dt/:packageName',
|
||||
namedParams: {
|
||||
tenant: 'cefsharp',
|
||||
feed: 'cefsharp',
|
||||
packageName: 'CefSharp.Common',
|
||||
static openApi = {
|
||||
'/myget/{feed}/dt/{packageName}': {
|
||||
get: {
|
||||
summary: 'MyGet Downloads',
|
||||
parameters: pathParams(
|
||||
{ name: 'feed', example: 'mongodb' },
|
||||
{ name: 'packageName', example: 'MongoDB.Driver.Core' },
|
||||
),
|
||||
},
|
||||
staticPreview: this.render({ downloads: 9748 }),
|
||||
},
|
||||
]
|
||||
'/{tenant}/{feed}/dt/{packageName}': {
|
||||
get: {
|
||||
summary: 'MyGet Downloads (tenant)',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'tenant',
|
||||
example: 'tizen.myget',
|
||||
description: 'MyGet Tenant in the format `name.myget`',
|
||||
},
|
||||
{ name: 'feed', example: 'dotnet' },
|
||||
{ name: 'packageName', example: 'Tizen.NET' },
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export { MyGetVersionService, MyGetDownloadService }
|
||||
|
||||
67
services/nostr-band/nostr-band-followers.service.js
Normal file
67
services/nostr-band/nostr-band-followers.service.js
Normal file
@@ -0,0 +1,67 @@
|
||||
import Joi from 'joi'
|
||||
import { metric } from '../text-formatters.js'
|
||||
import { BaseJsonService, pathParams } from '../index.js'
|
||||
|
||||
const npubSchema = Joi.object({
|
||||
followers_pubkey_count: Joi.number().required(),
|
||||
}).required()
|
||||
|
||||
const mainSchema = Joi.object({
|
||||
stats: Joi.object()
|
||||
.pattern(Joi.string(), npubSchema)
|
||||
.min(1)
|
||||
.max(1)
|
||||
.required(),
|
||||
}).required()
|
||||
|
||||
export default class NostrBandFollowers extends BaseJsonService {
|
||||
static category = 'social'
|
||||
|
||||
static route = {
|
||||
base: 'nostr-band/followers',
|
||||
pattern: ':npub',
|
||||
}
|
||||
|
||||
static openApi = {
|
||||
'/nostr-band/followers/{npub}': {
|
||||
get: {
|
||||
summary: 'Nostr.band Followers',
|
||||
description:
|
||||
'Returns the number of followers for a Nostr pubkey using the Nostr.band API.',
|
||||
parameters: pathParams({
|
||||
name: 'npub',
|
||||
description: 'Nostr pubkey in (npub1...) format or hex.',
|
||||
example:
|
||||
'npub18c556t7n8xa3df2q82rwxejfglw5przds7sqvefylzjh8tjne28qld0we7',
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'followers' }
|
||||
|
||||
static render({ followers }) {
|
||||
return {
|
||||
message: metric(followers),
|
||||
style: 'social',
|
||||
}
|
||||
}
|
||||
|
||||
async fetch({ npub }) {
|
||||
const data = await this._requestJson({
|
||||
url: `https://api.nostr.band/v0/stats/profile/${npub}`,
|
||||
schema: mainSchema,
|
||||
httpErrors: {
|
||||
400: 'invalid pubkey',
|
||||
},
|
||||
})
|
||||
const stats = data.stats
|
||||
const firstKey = Object.keys(stats)[0]
|
||||
return stats[firstKey].followers_pubkey_count
|
||||
}
|
||||
|
||||
async handle({ npub }) {
|
||||
const followers = await this.fetch({ npub })
|
||||
return this.constructor.render({ followers })
|
||||
}
|
||||
}
|
||||
15
services/nostr-band/nostr-band-followers.tester.js
Normal file
15
services/nostr-band/nostr-band-followers.tester.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { isMetric } from '../test-validators.js'
|
||||
import { createServiceTester } from '../tester.js'
|
||||
export const t = await createServiceTester()
|
||||
|
||||
t.create('fetch: valid npub')
|
||||
.get('/npub18c556t7n8xa3df2q82rwxejfglw5przds7sqvefylzjh8tjne28qld0we7.json')
|
||||
.expectBadge({
|
||||
label: 'followers',
|
||||
message: isMetric,
|
||||
})
|
||||
|
||||
t.create('fetch: invalid npub').get('/invalidnpub.json').expectBadge({
|
||||
label: 'followers',
|
||||
message: 'invalid pubkey',
|
||||
})
|
||||
@@ -34,6 +34,9 @@ export const queryParamSchema = Joi.object({
|
||||
registry_uri: optionalUrl,
|
||||
}).required()
|
||||
|
||||
export const packageNameDescription =
|
||||
'This may be the name of an unscoped package like `package-name` or a [scoped package](https://docs.npmjs.com/about-scopes) like `@author/package-name`'
|
||||
|
||||
// Abstract class for NPM badges which display data about the latest version
|
||||
// of a package.
|
||||
export default class NpmBase extends BaseJsonService {
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
import { pathParam, queryParam } from '../index.js'
|
||||
import { renderContributorBadge } from '../contributor-count.js'
|
||||
import NpmBase from './npm-base.js'
|
||||
|
||||
const keywords = ['node']
|
||||
import NpmBase, { packageNameDescription } from './npm-base.js'
|
||||
|
||||
export default class NpmCollaborators extends NpmBase {
|
||||
static category = 'activity'
|
||||
|
||||
static route = this.buildRoute('npm/collaborators', { withTag: false })
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'npm collaborators',
|
||||
pattern: ':packageName',
|
||||
namedParams: { packageName: 'prettier' },
|
||||
staticPreview: this.render({ collaborators: 6 }),
|
||||
keywords,
|
||||
static openApi = {
|
||||
'/npm/collaborators/{packageName}': {
|
||||
get: {
|
||||
summary: 'NPM Collaborators',
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'packageName',
|
||||
example: 'prettier',
|
||||
description: packageNameDescription,
|
||||
}),
|
||||
queryParam({
|
||||
name: 'registry_uri',
|
||||
example: 'https://registry.npmjs.com',
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'npm collaborators',
|
||||
pattern: ':packageName',
|
||||
namedParams: { packageName: 'prettier' },
|
||||
queryParams: { registry_uri: 'https://registry.npmjs.com' },
|
||||
staticPreview: this.render({ collaborators: 6 }),
|
||||
keywords,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = {
|
||||
label: 'npm collaborators',
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { pathParam, queryParam } from '../index.js'
|
||||
import { getDependencyVersion } from '../package-json-helpers.js'
|
||||
import NpmBase from './npm-base.js'
|
||||
|
||||
const { queryParamSchema } = NpmBase
|
||||
const keywords = ['node']
|
||||
import NpmBase, {
|
||||
queryParamSchema,
|
||||
packageNameDescription,
|
||||
} from './npm-base.js'
|
||||
|
||||
export default class NpmDependencyVersion extends NpmBase {
|
||||
static category = 'platform-support'
|
||||
@@ -14,89 +15,55 @@ export default class NpmDependencyVersion extends NpmBase {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'npm peer dependency version',
|
||||
pattern: ':packageName/peer/:dependency',
|
||||
namedParams: {
|
||||
packageName: 'react-boxplot',
|
||||
dependency: 'prop-types',
|
||||
static openApi = {
|
||||
'/npm/dependency-version/{packageName}/{dependency}': {
|
||||
get: {
|
||||
summary: 'NPM (prod) Dependency Version',
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'packageName',
|
||||
example: 'react-boxplot',
|
||||
description: packageNameDescription,
|
||||
}),
|
||||
pathParam({
|
||||
name: 'dependency',
|
||||
example: 'simple-statistics',
|
||||
description: packageNameDescription,
|
||||
}),
|
||||
queryParam({
|
||||
name: 'registry_uri',
|
||||
example: 'https://registry.npmjs.com',
|
||||
}),
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
dependency: 'prop-types',
|
||||
range: '^15.5.4',
|
||||
}),
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'npm peer dependency version (scoped)',
|
||||
pattern: ':scope?/:packageName/peer/:dependencyScope?/:dependency',
|
||||
namedParams: {
|
||||
scope: '@swellaby',
|
||||
packageName: 'eslint-config',
|
||||
dependency: 'eslint',
|
||||
'/npm/dependency-version/{packageName}/{kind}/{dependency}': {
|
||||
get: {
|
||||
summary: 'NPM dev or peer Dependency Version',
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'packageName',
|
||||
example: 'react-boxplot',
|
||||
description: packageNameDescription,
|
||||
}),
|
||||
pathParam({
|
||||
name: 'kind',
|
||||
example: 'dev',
|
||||
schema: { type: 'string', enum: this.getEnum('kind') },
|
||||
}),
|
||||
pathParam({
|
||||
name: 'dependency',
|
||||
example: 'prop-types',
|
||||
description: packageNameDescription,
|
||||
}),
|
||||
queryParam({
|
||||
name: 'registry_uri',
|
||||
example: 'https://registry.npmjs.com',
|
||||
}),
|
||||
],
|
||||
},
|
||||
staticPreview: this.render({
|
||||
dependency: 'eslint',
|
||||
range: '^3.0.0',
|
||||
}),
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'npm dev dependency version',
|
||||
pattern: ':packageName/dev/:dependency',
|
||||
namedParams: {
|
||||
packageName: 'react-boxplot',
|
||||
dependency: 'eslint-config-standard',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
dependency: 'eslint-config-standard',
|
||||
range: '^12.0.0',
|
||||
}),
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'npm dev dependency version (scoped)',
|
||||
pattern: ':scope?/:packageName/dev/:dependencyScope?/:dependency',
|
||||
namedParams: {
|
||||
packageName: 'mocha',
|
||||
dependencyScope: '@mocha',
|
||||
dependency: 'contributors',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
dependency: '@mocha/contributors',
|
||||
range: '^1.0.3',
|
||||
}),
|
||||
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,
|
||||
},
|
||||
{
|
||||
title: 'npm (prod) dependency version (scoped)',
|
||||
pattern: ':scope?/:packageName/:dependencyScope?/:dependency',
|
||||
namedParams: {
|
||||
packageName: 'got',
|
||||
dependencyScope: '@sindresorhus',
|
||||
dependency: 'is',
|
||||
},
|
||||
staticPreview: this.render({
|
||||
dependency: '@sindresorhus/is',
|
||||
range: '^0.15.0',
|
||||
}),
|
||||
keywords,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = {
|
||||
label: 'dependency',
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import Joi from 'joi'
|
||||
import { renderDownloadsBadge } from '../downloads.js'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { BaseJsonService } from '../index.js'
|
||||
import { BaseJsonService, pathParams } from '../index.js'
|
||||
import { packageNameDescription } from './npm-base.js'
|
||||
|
||||
// https://github.com/npm/registry/blob/master/docs/download-counts.md#output
|
||||
const pointResponseSchema = Joi.object({
|
||||
@@ -50,14 +51,26 @@ export default class NpmDownloads extends BaseJsonService {
|
||||
pattern: ':interval(dw|dm|dy|dt)/:scope(@.+)?/:packageName',
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'npm',
|
||||
namedParams: { interval: 'dw', packageName: 'localeval' },
|
||||
staticPreview: this.render({ interval: 'dw', downloadCount: 30000 }),
|
||||
keywords: ['node'],
|
||||
static openApi = {
|
||||
'/npm/{interval}/{packageName}': {
|
||||
get: {
|
||||
summary: 'NPM Downloads',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'interval',
|
||||
example: 'dw',
|
||||
description: 'Weekly, Monthly, Yearly, or Total downloads',
|
||||
schema: { type: 'string', enum: this.getEnum('interval') },
|
||||
},
|
||||
{
|
||||
name: 'packageName',
|
||||
example: 'localeval',
|
||||
description: packageNameDescription,
|
||||
},
|
||||
),
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
// For testing.
|
||||
static _intervalMap = intervalMap
|
||||
|
||||
@@ -1,29 +1,31 @@
|
||||
import { pathParam, queryParam } from '../index.js'
|
||||
import { renderLicenseBadge } from '../licenses.js'
|
||||
import toArray from '../../core/base-service/to-array.js'
|
||||
import NpmBase from './npm-base.js'
|
||||
import NpmBase, { packageNameDescription } from './npm-base.js'
|
||||
|
||||
export default class NpmLicense extends NpmBase {
|
||||
static category = 'license'
|
||||
|
||||
static route = this.buildRoute('npm/l', { withTag: false })
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'NPM',
|
||||
pattern: ':packageName',
|
||||
namedParams: { packageName: 'express' },
|
||||
staticPreview: this.render({ licenses: ['MIT'] }),
|
||||
keywords: ['node'],
|
||||
static openApi = {
|
||||
'/npm/l/{packageName}': {
|
||||
get: {
|
||||
summary: 'NPM License',
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'packageName',
|
||||
example: 'express',
|
||||
description: packageNameDescription,
|
||||
}),
|
||||
queryParam({
|
||||
name: 'registry_uri',
|
||||
example: 'https://registry.npmjs.com',
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'NPM',
|
||||
pattern: ':packageName',
|
||||
namedParams: { packageName: 'express' },
|
||||
queryParams: { registry_uri: 'https://registry.npmjs.com' },
|
||||
staticPreview: this.render({ licenses: ['MIT'] }),
|
||||
keywords: ['node'],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static render({ licenses }) {
|
||||
return renderLicenseBadge({ licenses })
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { pathParams } from '../index.js'
|
||||
import NpmBase from './npm-base.js'
|
||||
import { pathParam, queryParam } from '../index.js'
|
||||
import NpmBase, { packageNameDescription } from './npm-base.js'
|
||||
|
||||
// For this badge to correctly detect type definitions, either the relevant
|
||||
// dependencies must be declared, or the `types` key must be set in
|
||||
@@ -12,11 +12,18 @@ export default class NpmTypeDefinitions extends NpmBase {
|
||||
static openApi = {
|
||||
'/npm/types/{packageName}': {
|
||||
get: {
|
||||
summary: 'npm type definitions',
|
||||
parameters: pathParams({
|
||||
name: 'packageName',
|
||||
example: 'chalk',
|
||||
}),
|
||||
summary: 'NPM Type Definitions',
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'packageName',
|
||||
example: 'chalk',
|
||||
description: packageNameDescription,
|
||||
}),
|
||||
queryParam({
|
||||
name: 'registry_uri',
|
||||
example: 'https://registry.npmjs.com',
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import Joi from 'joi'
|
||||
import { renderVersionBadge } from '../version.js'
|
||||
import { NotFound } from '../index.js'
|
||||
import NpmBase from './npm-base.js'
|
||||
|
||||
const keywords = ['node']
|
||||
import { NotFound, pathParam, queryParam } from '../index.js'
|
||||
import NpmBase, { packageNameDescription } from './npm-base.js'
|
||||
|
||||
// Joi.string should be a semver.
|
||||
const schema = Joi.object()
|
||||
@@ -16,44 +14,44 @@ export default class NpmVersion extends NpmBase {
|
||||
|
||||
static route = this.buildRoute('npm/v', { withTag: true })
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'npm',
|
||||
pattern: ':packageName',
|
||||
namedParams: { packageName: 'npm' },
|
||||
staticPreview: this.render({ version: '6.3.0' }),
|
||||
keywords,
|
||||
static openApi = {
|
||||
'/npm/v/{packageName}': {
|
||||
get: {
|
||||
summary: 'NPM Version',
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'packageName',
|
||||
example: 'npm',
|
||||
description: packageNameDescription,
|
||||
}),
|
||||
queryParam({
|
||||
name: 'registry_uri',
|
||||
example: 'https://registry.npmjs.com',
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'npm (scoped)',
|
||||
pattern: ':scope/:packageName',
|
||||
namedParams: { scope: '@cycle', packageName: 'core' },
|
||||
staticPreview: this.render({ version: '7.0.0' }),
|
||||
keywords,
|
||||
'/npm/v/{packageName}/{tag}': {
|
||||
get: {
|
||||
summary: 'NPM Version (with dist tag)',
|
||||
parameters: [
|
||||
pathParam({
|
||||
name: 'packageName',
|
||||
example: 'npm',
|
||||
description: packageNameDescription,
|
||||
}),
|
||||
pathParam({
|
||||
name: 'tag',
|
||||
example: 'next-8',
|
||||
}),
|
||||
queryParam({
|
||||
name: 'registry_uri',
|
||||
example: 'https://registry.npmjs.com',
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'npm (tag)',
|
||||
pattern: ':packageName/:tag',
|
||||
namedParams: { packageName: 'npm', tag: 'next-8' },
|
||||
staticPreview: this.render({ tag: 'latest', version: '6.3.0' }),
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'npm (custom registry)',
|
||||
pattern: ':packageName/:tag',
|
||||
namedParams: { packageName: 'npm', tag: 'next-8' },
|
||||
queryParams: { registry_uri: 'https://registry.npmjs.com' },
|
||||
staticPreview: this.render({ tag: 'latest', version: '7.0.0' }),
|
||||
keywords,
|
||||
},
|
||||
{
|
||||
title: 'npm (scoped with tag)',
|
||||
pattern: ':scope/:packageName/:tag',
|
||||
namedParams: { scope: '@cycle', packageName: 'core', tag: 'canary' },
|
||||
staticPreview: this.render({ tag: 'latest', version: '6.3.0' }),
|
||||
keywords,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = {
|
||||
label: 'npm',
|
||||
|
||||
@@ -5,6 +5,9 @@ import {
|
||||
BaseXmlService,
|
||||
NotFound,
|
||||
redirector,
|
||||
pathParams,
|
||||
pathParam,
|
||||
queryParam,
|
||||
} from '../index.js'
|
||||
import {
|
||||
renderVersionBadge,
|
||||
@@ -138,22 +141,25 @@ function createServiceFamily({
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
if (!title) return []
|
||||
static get openApi() {
|
||||
if (!title) return {}
|
||||
|
||||
return [
|
||||
{
|
||||
title: `${title} Version`,
|
||||
namedParams: { packageName: examplePackageName },
|
||||
staticPreview: this.render({ version: exampleVersion }),
|
||||
const key = `/${serviceBaseUrl}/v/{packageName}`
|
||||
const route = {}
|
||||
route[key] = {
|
||||
get: {
|
||||
summary: `${title} Version`,
|
||||
parameters: [
|
||||
pathParam({ name: 'packageName', example: examplePackageName }),
|
||||
queryParam({
|
||||
name: 'include_prereleases',
|
||||
schema: { type: 'boolean' },
|
||||
example: null,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
title: `${title} Version (including pre-releases)`,
|
||||
namedParams: { packageName: examplePackageName },
|
||||
queryParams: { include_prereleases: null },
|
||||
staticPreview: this.render({ version: examplePrereleaseVersion }),
|
||||
},
|
||||
]
|
||||
}
|
||||
return route
|
||||
}
|
||||
|
||||
static defaultBadgeData = {
|
||||
@@ -199,16 +205,21 @@ function createServiceFamily({
|
||||
pattern: 'dt/:packageName',
|
||||
}
|
||||
|
||||
static get examples() {
|
||||
if (!title) return []
|
||||
static get openApi() {
|
||||
if (!title) return {}
|
||||
|
||||
return [
|
||||
{
|
||||
title,
|
||||
namedParams: { packageName: examplePackageName },
|
||||
staticPreview: this.render({ downloads: exampleDownloadCount }),
|
||||
const key = `/${serviceBaseUrl}/dt/{packageName}`
|
||||
const route = {}
|
||||
route[key] = {
|
||||
get: {
|
||||
summary: `${title} Downloads`,
|
||||
parameters: pathParams({
|
||||
name: 'packageName',
|
||||
example: examplePackageName,
|
||||
}),
|
||||
},
|
||||
]
|
||||
}
|
||||
return route
|
||||
}
|
||||
|
||||
static render(props) {
|
||||
|
||||
@@ -121,7 +121,7 @@ function createServiceFamily({
|
||||
.push('(.+?)', 'packageName')
|
||||
.toObject()
|
||||
|
||||
static examples = []
|
||||
static openApi = {}
|
||||
|
||||
static defaultBadgeData = {
|
||||
label: defaultLabel,
|
||||
@@ -170,7 +170,7 @@ function createServiceFamily({
|
||||
.push('(.+?)', 'packageName')
|
||||
.toObject()
|
||||
|
||||
static examples = []
|
||||
static openApi = {}
|
||||
|
||||
static render(props) {
|
||||
return renderDownloadBadge(props)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { pathParams } from '../index.js'
|
||||
import { createServiceFamily } from './nuget-v3-service-family.js'
|
||||
|
||||
const { NugetVersionService: Version, NugetDownloadService: Downloads } =
|
||||
@@ -10,31 +11,37 @@ const { NugetVersionService: Version, NugetDownloadService: Downloads } =
|
||||
})
|
||||
|
||||
class NugetVersionService extends Version {
|
||||
static examples = [
|
||||
{
|
||||
title: 'Nuget',
|
||||
pattern: 'v/:packageName',
|
||||
namedParams: { packageName: 'Microsoft.AspNet.Mvc' },
|
||||
staticPreview: this.render({ version: '5.2.4' }),
|
||||
static openApi = {
|
||||
'/nuget/{variant}/{packageName}': {
|
||||
get: {
|
||||
summary: 'NuGet Version',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'variant',
|
||||
example: 'v',
|
||||
schema: { type: 'variant', enum: ['v', 'vpre'] },
|
||||
description:
|
||||
'Latest stable version (`v`) or Latest version including prereleases (`vpre`).',
|
||||
},
|
||||
{ name: 'packageName', example: 'Microsoft.AspNet.Mvc' },
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Nuget (with prereleases)',
|
||||
pattern: 'vpre/:packageName',
|
||||
namedParams: { packageName: 'Microsoft.AspNet.Mvc' },
|
||||
staticPreview: this.render({ version: '5.2.5-preview1' }),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
class NugetDownloadService extends Downloads {
|
||||
static examples = [
|
||||
{
|
||||
title: 'Nuget',
|
||||
pattern: 'dt/:packageName',
|
||||
namedParams: { packageName: 'Microsoft.AspNet.Mvc' },
|
||||
staticPreview: this.render({ downloads: 49e6 }),
|
||||
static openApi = {
|
||||
'/nuget/dt/{packageName}': {
|
||||
get: {
|
||||
summary: 'NuGet Downloads',
|
||||
parameters: pathParams({
|
||||
name: 'packageName',
|
||||
example: 'Microsoft.AspNet.Mvc',
|
||||
}),
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
export { NugetVersionService, NugetDownloadService }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Joi from 'joi'
|
||||
import { BaseXmlService } from '../index.js'
|
||||
import { BaseXmlService, pathParam, queryParam } from '../index.js'
|
||||
import { optionalUrl } from '../validators.js'
|
||||
import { isBuildStatus, renderBuildStatusBadge } from './obs-build-status.js'
|
||||
|
||||
@@ -26,23 +26,22 @@ export default class ObsService extends BaseXmlService {
|
||||
isRequired: true,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'OBS package build status',
|
||||
namedParams: {
|
||||
project: 'openSUSE:Tools',
|
||||
packageName: 'osc',
|
||||
repository: 'Debian_11',
|
||||
arch: 'x86_64',
|
||||
static openApi = {
|
||||
'/obs/{project}/{packageName}/{repository}/{arch}': {
|
||||
get: {
|
||||
summary: 'OBS package build status',
|
||||
description:
|
||||
'[Open Build Service](https://openbuildservice.org/) (OBS) is a generic system to build and distribute binary packages',
|
||||
parameters: [
|
||||
pathParam({ name: 'project', example: 'openSUSE:Tools' }),
|
||||
pathParam({ name: 'packageName', example: 'osc' }),
|
||||
pathParam({ name: 'repository', example: 'Debian_11' }),
|
||||
pathParam({ name: 'arch', example: 'x86_64' }),
|
||||
queryParam({ name: 'instance', example: 'https://api.opensuse.org' }),
|
||||
],
|
||||
},
|
||||
queryParams: { instance: 'https://api.opensuse.org' },
|
||||
staticPreview: this.render({
|
||||
repository: 'Debian_11',
|
||||
status: 'succeeded',
|
||||
}),
|
||||
keywords: ['open build service'],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'build' }
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import Joi from 'joi'
|
||||
import { renderDownloadsBadge } from '../downloads.js'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { BaseJsonService } from '../index.js'
|
||||
|
||||
const keywords = ['sublime', 'sublimetext', 'packagecontrol']
|
||||
import { BaseJsonService, pathParams } from '../index.js'
|
||||
|
||||
const schema = Joi.object({
|
||||
installs: Joi.object({
|
||||
@@ -20,92 +18,91 @@ const schema = Joi.object({
|
||||
}).required(),
|
||||
})
|
||||
|
||||
function DownloadsForInterval(downloadInterval) {
|
||||
const { base, interval, transform, name } = {
|
||||
day: {
|
||||
base: 'packagecontrol/dd',
|
||||
interval: 'day',
|
||||
transform: resp => {
|
||||
const platforms = resp.installs.daily.data
|
||||
let downloads = 0
|
||||
platforms.forEach(platform => {
|
||||
// use the downloads from yesterday
|
||||
downloads += platform.totals[1]
|
||||
})
|
||||
return downloads
|
||||
},
|
||||
name: 'PackageControlDownloadsDay',
|
||||
},
|
||||
week: {
|
||||
base: 'packagecontrol/dw',
|
||||
interval: 'week',
|
||||
transform: resp => {
|
||||
const platforms = resp.installs.daily.data
|
||||
let downloads = 0
|
||||
platforms.forEach(platform => {
|
||||
// total for the first 7 days
|
||||
for (let i = 0; i < 7; i++) {
|
||||
downloads += platform.totals[i]
|
||||
}
|
||||
})
|
||||
return downloads
|
||||
},
|
||||
name: 'PackageControlDownloadsWeek',
|
||||
},
|
||||
month: {
|
||||
base: 'packagecontrol/dm',
|
||||
interval: 'month',
|
||||
transform: resp => {
|
||||
const platforms = resp.installs.daily.data
|
||||
let downloads = 0
|
||||
platforms.forEach(platform => {
|
||||
// total for the first 30 days
|
||||
for (let i = 0; i < 30; i++) {
|
||||
downloads += platform.totals[i]
|
||||
}
|
||||
})
|
||||
return downloads
|
||||
},
|
||||
name: 'PackageControlDownloadsMonth',
|
||||
},
|
||||
total: {
|
||||
base: 'packagecontrol/dt',
|
||||
transform: resp => resp.installs.total,
|
||||
name: 'PackageControlDownloadsTotal',
|
||||
},
|
||||
}[downloadInterval]
|
||||
|
||||
return class PackageControlDownloads extends BaseJsonService {
|
||||
static name = name
|
||||
|
||||
static category = 'downloads'
|
||||
|
||||
static route = { base, pattern: ':packageName' }
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'Package Control',
|
||||
namedParams: { packageName: 'GitGutter' },
|
||||
staticPreview: renderDownloadsBadge({ downloads: 12000 }),
|
||||
keywords,
|
||||
},
|
||||
]
|
||||
|
||||
static defaultBadgeData = { label: 'downloads' }
|
||||
|
||||
async fetch({ packageName }) {
|
||||
const url = `https://packagecontrol.io/packages/${packageName}.json`
|
||||
return this._requestJson({ schema, url })
|
||||
}
|
||||
|
||||
async handle({ packageName }) {
|
||||
const data = await this.fetch({ packageName })
|
||||
return renderDownloadsBadge({
|
||||
downloads: transform(data),
|
||||
interval,
|
||||
const intervalMap = {
|
||||
dd: {
|
||||
label: 'day',
|
||||
transform: resp => {
|
||||
const platforms = resp.installs.daily.data
|
||||
let downloads = 0
|
||||
platforms.forEach(platform => {
|
||||
// use the downloads from yesterday
|
||||
downloads += platform.totals[1]
|
||||
})
|
||||
}
|
||||
}
|
||||
return downloads
|
||||
},
|
||||
},
|
||||
dw: {
|
||||
label: 'week',
|
||||
transform: resp => {
|
||||
const platforms = resp.installs.daily.data
|
||||
let downloads = 0
|
||||
platforms.forEach(platform => {
|
||||
// total for the first 7 days
|
||||
for (let i = 0; i < 7; i++) {
|
||||
downloads += platform.totals[i]
|
||||
}
|
||||
})
|
||||
return downloads
|
||||
},
|
||||
},
|
||||
dm: {
|
||||
label: 'month',
|
||||
transform: resp => {
|
||||
const platforms = resp.installs.daily.data
|
||||
let downloads = 0
|
||||
platforms.forEach(platform => {
|
||||
// total for the first 30 days
|
||||
for (let i = 0; i < 30; i++) {
|
||||
downloads += platform.totals[i]
|
||||
}
|
||||
})
|
||||
return downloads
|
||||
},
|
||||
},
|
||||
dt: {
|
||||
transform: resp => resp.installs.total,
|
||||
},
|
||||
}
|
||||
|
||||
export default ['day', 'week', 'month', 'total'].map(DownloadsForInterval)
|
||||
export default class PackageControlDownloads extends BaseJsonService {
|
||||
static category = 'downloads'
|
||||
|
||||
static route = {
|
||||
base: 'packagecontrol',
|
||||
pattern: ':interval(dd|dw|dm|dt)/:packageName',
|
||||
}
|
||||
|
||||
static openApi = {
|
||||
'/packagecontrol/{interval}/{packageName}': {
|
||||
get: {
|
||||
summary: 'Package Control Downloads',
|
||||
description:
|
||||
'Package Control is a package registry for Sublime Text packages',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'interval',
|
||||
example: 'dt',
|
||||
schema: { type: 'string', enum: this.getEnum('interval') },
|
||||
description: 'Daily, Weekly, Monthly, or Total downloads',
|
||||
},
|
||||
{ name: 'packageName', example: 'GitGutter' },
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'downloads' }
|
||||
|
||||
async fetch({ packageName }) {
|
||||
const url = `https://packagecontrol.io/packages/${packageName}.json`
|
||||
return this._requestJson({ schema, url })
|
||||
}
|
||||
|
||||
async handle({ interval, packageName }) {
|
||||
const data = await this.fetch({ packageName })
|
||||
return renderDownloadsBadge({
|
||||
downloads: intervalMap[interval].transform(data),
|
||||
interval: intervalMap[interval].label,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
import Joi from 'joi'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { coveragePercentage } from '../color-formatters.js'
|
||||
import { BaseJsonService, InvalidResponse } from '../index.js'
|
||||
import {
|
||||
BaseJsonService,
|
||||
InvalidResponse,
|
||||
pathParam,
|
||||
queryParam,
|
||||
} from '../index.js'
|
||||
|
||||
const documentation = `
|
||||
You must specify the read-only API token from the POEditor account to which the project belongs.
|
||||
const description = `
|
||||
POEditor is an web-based tool for translation and internationalization
|
||||
|
||||
As per [the POEditor API documentation](https://poeditor.com/docs/api)
|
||||
|
||||
> All requests to the API must contain the parameter api_token.
|
||||
> You can get a read-only key from your POEditor account.
|
||||
> You'll find it in [My Account > API Access](https://poeditor.com/account/api).
|
||||
All requests to must contain the parameter \`token\`.
|
||||
You can get a read-only token from your POEditor account in [My Account > API Access](https://poeditor.com/account/api).
|
||||
This token will be exposed as part of the badge URL so be sure to generate a read-only token.
|
||||
`
|
||||
|
||||
const schema = Joi.object({
|
||||
@@ -42,20 +45,25 @@ export default class POEditor extends BaseJsonService {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'POEditor',
|
||||
namedParams: { projectId: '323337', languageCode: 'fr' },
|
||||
queryParams: { token: 'abc123def456' },
|
||||
staticPreview: this.render({
|
||||
code: 200,
|
||||
message: 'OK',
|
||||
language: { percentage: 93, code: 'fr', name: 'French' },
|
||||
}),
|
||||
keywords: ['l10n'],
|
||||
documentation,
|
||||
static openApi = {
|
||||
'/poeditor/progress/{projectId}/{languageCode}': {
|
||||
get: {
|
||||
summary: 'POEditor',
|
||||
description,
|
||||
parameters: [
|
||||
pathParam({ name: 'projectId', example: '323337' }),
|
||||
pathParam({ name: 'languageCode', example: 'fr' }),
|
||||
queryParam({
|
||||
name: 'token',
|
||||
example: 'abc123def456',
|
||||
description:
|
||||
'A read-only token from your POEditor account from [My Account > API Access](https://poeditor.com/account/api)',
|
||||
required: true,
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static render({ code, message, language }) {
|
||||
if (code !== 200) {
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import Joi from 'joi'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { BaseJsonService } from '../index.js'
|
||||
import { BaseJsonService, pathParams } from '../index.js'
|
||||
import { renderDownloadsBadge } from '../downloads.js'
|
||||
|
||||
const keywords = ['python']
|
||||
|
||||
const schema = Joi.object({
|
||||
data: Joi.object({
|
||||
last_day: nonNegativeInteger,
|
||||
@@ -38,20 +36,24 @@ export default class PypiDownloads extends BaseJsonService {
|
||||
pattern: ':period(dd|dw|dm)/:packageName',
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'PyPI - Downloads',
|
||||
namedParams: {
|
||||
period: 'dd',
|
||||
packageName: 'Django',
|
||||
static openApi = {
|
||||
'/pypi/{period}/{packageName}': {
|
||||
get: {
|
||||
summary: 'PyPI - Downloads',
|
||||
description:
|
||||
'Python package downloads from [pypistats](https://pypistats.org/)',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'period',
|
||||
example: 'dd',
|
||||
schema: { type: 'string', enum: this.getEnum('period') },
|
||||
description: 'Daily, Weekly, or Monthly downloads',
|
||||
},
|
||||
{ name: 'packageName', example: 'Django' },
|
||||
),
|
||||
},
|
||||
staticPreview: renderDownloadsBadge({
|
||||
interval: 'day',
|
||||
downloads: 14000,
|
||||
}),
|
||||
keywords,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static _cacheLength = 28800
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { InvalidResponse } from '../index.js'
|
||||
import { InvalidResponse, pathParams } from '../index.js'
|
||||
import PypiBase from './pypi-base.js'
|
||||
import { sortPypiVersions, parseClassifiers } from './pypi-helpers.js'
|
||||
|
||||
@@ -37,7 +37,7 @@ const frameworkNameMap = {
|
||||
},
|
||||
}
|
||||
|
||||
const documentation = `
|
||||
const description = `
|
||||
<p>
|
||||
This service currently support the following Frameworks: <br/>
|
||||
${Object.values(frameworkNameMap).map(obj => ` <strong>${obj.name}</strong>`)}
|
||||
@@ -53,21 +53,22 @@ export default class PypiFrameworkVersion extends PypiBase {
|
||||
)})/:packageName+`,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'PyPI - Versions from Framework Classifiers',
|
||||
namedParams: {
|
||||
frameworkName: 'Plone',
|
||||
packageName: 'plone.volto',
|
||||
static openApi = {
|
||||
'/pypi/frameworkversions/{frameworkName}/{packageName}': {
|
||||
get: {
|
||||
summary: 'PyPI - Versions from Framework Classifiers',
|
||||
description,
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'frameworkName',
|
||||
example: 'plone',
|
||||
schema: { type: 'string', enum: Object.keys(frameworkNameMap) },
|
||||
},
|
||||
{ name: 'packageName', example: 'plone.volto' },
|
||||
),
|
||||
},
|
||||
staticPreview: this.render({
|
||||
name: 'Plone',
|
||||
versions: ['5.2', '6.0'],
|
||||
}),
|
||||
keywords: ['python'],
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'versions' }
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Joi from 'joi'
|
||||
import BaseTomlService from '../../core/base-service/base-toml.js'
|
||||
import { queryParams } from '../index.js'
|
||||
import { optionalUrl } from '../validators.js'
|
||||
|
||||
const queryParamSchema = Joi.object({
|
||||
@@ -12,7 +13,7 @@ const schema = Joi.object({
|
||||
}).required(),
|
||||
}).required()
|
||||
|
||||
const documentation = `Shows the required python version for a package based on the values in the requires-python field in PEP 621 compliant pyproject.toml \n
|
||||
const description = `Shows the required python version for a package based on the values in the requires-python field in PEP 621 compliant pyproject.toml \n
|
||||
a URL of the toml is required, please note that when linking to files in github or similar sites, provide URL to raw file, for example:
|
||||
|
||||
Use https://raw.githubusercontent.com/numpy/numpy/main/pyproject.toml \n
|
||||
@@ -28,18 +29,20 @@ class PythonVersionFromToml extends BaseTomlService {
|
||||
queryParamSchema,
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'Python Version from PEP 621 TOML',
|
||||
namedParams: {},
|
||||
queryParams: {
|
||||
tomlFilePath:
|
||||
'https://raw.githubusercontent.com/numpy/numpy/main/pyproject.toml',
|
||||
static openApi = {
|
||||
'/python/required-version-toml': {
|
||||
get: {
|
||||
summary: 'Python Version from PEP 621 TOML',
|
||||
description,
|
||||
parameters: queryParams({
|
||||
name: 'tomlFilePath',
|
||||
example:
|
||||
'https://raw.githubusercontent.com/numpy/numpy/main/pyproject.toml',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
staticPreview: this.render({ requiresPythonString: '>=3.9' }),
|
||||
documentation,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'python' }
|
||||
|
||||
|
||||
@@ -12,10 +12,12 @@ export const t = new ServiceTester({
|
||||
|
||||
// downloads
|
||||
|
||||
t.create('total downloads (valid)').get('/dt/ReSharper.Nuke.json').expectBadge({
|
||||
label: 'downloads',
|
||||
message: isMetric,
|
||||
})
|
||||
t.create('total downloads (valid)')
|
||||
.get('/dt/StyleCop.StyleCop.json')
|
||||
.expectBadge({
|
||||
label: 'downloads',
|
||||
message: isMetric,
|
||||
})
|
||||
|
||||
t.create('total downloads (not found)')
|
||||
.get('/dt/not-a-real-package.json')
|
||||
@@ -23,7 +25,7 @@ t.create('total downloads (not found)')
|
||||
|
||||
// version
|
||||
|
||||
t.create('version (valid)').get('/v/ReSharper.Nuke.json').expectBadge({
|
||||
t.create('version (valid)').get('/v/StyleCop.StyleCop.json').expectBadge({
|
||||
label: 'resharper',
|
||||
message: isVPlusDottedVersionNClauses,
|
||||
})
|
||||
@@ -35,7 +37,7 @@ t.create('version (not found)')
|
||||
// version (pre)
|
||||
|
||||
t.create('version (pre) (valid)')
|
||||
.get('/v/ReSharper.Nuke.json?include_prereleases')
|
||||
.get('/v/StyleCop.StyleCop.json?include_prereleases')
|
||||
.expectBadge({
|
||||
label: 'resharper',
|
||||
message: isVPlusDottedVersionNClausesWithOptionalSuffix,
|
||||
@@ -46,5 +48,5 @@ t.create('version (pre) (not found)')
|
||||
.expectBadge({ label: 'resharper', message: 'not found' })
|
||||
|
||||
t.create('version (legacy redirect: vpre)')
|
||||
.get('/vpre/ReSharper.Nuke.svg')
|
||||
.expectRedirect('/resharper/v/ReSharper.Nuke.svg?include_prereleases')
|
||||
.get('/vpre/StyleCop.StyleCop.svg')
|
||||
.expectRedirect('/resharper/v/StyleCop.StyleCop.svg?include_prereleases')
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Joi from 'joi'
|
||||
import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
|
||||
import { pathParams } from '../index.js'
|
||||
import ScrutinizerBase from './scrutinizer-base.js'
|
||||
|
||||
const schema = Joi.object({
|
||||
@@ -38,19 +39,39 @@ class ScrutinizerBuild extends ScrutinizerBuildBase {
|
||||
pattern: ':vcs(g|b)/:user/:repo/:branch*',
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'Scrutinizer build (GitHub/Bitbucket)',
|
||||
pattern: ':vcs(g|b)/:user/:repo/:branch?',
|
||||
namedParams: {
|
||||
vcs: 'g',
|
||||
user: 'filp',
|
||||
repo: 'whoops',
|
||||
branch: 'master',
|
||||
static openApi = {
|
||||
'/scrutinizer/build/{vcs}/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'Scrutinizer build (GitHub/Bitbucket)',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'vcs',
|
||||
example: 'g',
|
||||
description: 'Platform: Either Github or Bitbucket',
|
||||
schema: { type: 'string', enum: this.getEnum('vcs') },
|
||||
},
|
||||
{ name: 'user', example: 'filp' },
|
||||
{ name: 'repo', example: 'whoops' },
|
||||
),
|
||||
},
|
||||
staticPreview: renderBuildStatusBadge({ status: 'passing' }),
|
||||
},
|
||||
]
|
||||
'/scrutinizer/build/{vcs}/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'Scrutinizer build (GitHub/Bitbucket) with branch',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'vcs',
|
||||
example: 'g',
|
||||
description: 'Platform: Either Github or Bitbucket',
|
||||
schema: { type: 'string', enum: this.getEnum('vcs') },
|
||||
},
|
||||
{ name: 'user', example: 'filp' },
|
||||
{ name: 'repo', example: 'whoops' },
|
||||
{ name: 'branch', example: 'master' },
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
async handle({ vcs, user, repo, branch }) {
|
||||
return this.makeBadge({
|
||||
@@ -71,19 +92,29 @@ class ScrutinizerGitLabBuild extends ScrutinizerBuildBase {
|
||||
// The example used is valid, but the project will not be accessible if Shields users try to use it.
|
||||
// https://gitlab.propertywindow.nl/propertywindow/client
|
||||
// https://scrutinizer-ci.com/gl/propertywindow/propertywindow/client/badges/quality-score.png?b=master&s=dfae6992a48184cc2333b4c349cec0447f0d67c2
|
||||
static examples = [
|
||||
{
|
||||
title: 'Scrutinizer build (GitLab)',
|
||||
pattern: ':instance/:user/:repo/:branch?',
|
||||
namedParams: {
|
||||
instance: 'propertywindow',
|
||||
user: 'propertywindow',
|
||||
repo: 'client',
|
||||
branch: 'master',
|
||||
static openApi = {
|
||||
'/scrutinizer/build/gl/{instance}/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'Scrutinizer build (GitLab)',
|
||||
parameters: pathParams(
|
||||
{ name: 'instance', example: 'propertywindow' },
|
||||
{ name: 'user', example: 'propertywindow' },
|
||||
{ name: 'repo', example: 'client' },
|
||||
),
|
||||
},
|
||||
staticPreview: renderBuildStatusBadge({ status: 'passing' }),
|
||||
},
|
||||
]
|
||||
'/scrutinizer/build/gl/{instance}/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'Scrutinizer build (GitLab) with branch',
|
||||
parameters: pathParams(
|
||||
{ name: 'instance', example: 'propertywindow' },
|
||||
{ name: 'user', example: 'propertywindow' },
|
||||
{ name: 'repo', example: 'client' },
|
||||
{ name: 'branch', example: 'master' },
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
async handle({ instance, user, repo, branch }) {
|
||||
return this.makeBadge({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Joi from 'joi'
|
||||
import { colorScale } from '../color-formatters.js'
|
||||
import { NotFound } from '../index.js'
|
||||
import { NotFound, pathParams } from '../index.js'
|
||||
import ScrutinizerBase from './scrutinizer-base.js'
|
||||
|
||||
const schema = Joi.object({
|
||||
@@ -70,19 +70,39 @@ class ScrutinizerCoverage extends ScrutinizerCoverageBase {
|
||||
pattern: ':vcs(g|b)/:user/:repo/:branch*',
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'Scrutinizer coverage (GitHub/BitBucket)',
|
||||
pattern: ':vcs(g|b)/:user/:repo/:branch?',
|
||||
namedParams: {
|
||||
vcs: 'g',
|
||||
user: 'filp',
|
||||
repo: 'whoops',
|
||||
branch: 'master',
|
||||
static openApi = {
|
||||
'/scrutinizer/coverage/{vcs}/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'Scrutinizer coverage (GitHub/Bitbucket)',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'vcs',
|
||||
example: 'g',
|
||||
description: 'Platform: Either Github or Bitbucket',
|
||||
schema: { type: 'string', enum: this.getEnum('vcs') },
|
||||
},
|
||||
{ name: 'user', example: 'filp' },
|
||||
{ name: 'repo', example: 'whoops' },
|
||||
),
|
||||
},
|
||||
staticPreview: this.render({ coverage: 86 }),
|
||||
},
|
||||
]
|
||||
'/scrutinizer/coverage/{vcs}/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'Scrutinizer coverage (GitHub/Bitbucket) with branch',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'vcs',
|
||||
example: 'g',
|
||||
description: 'Platform: Either Github or Bitbucket',
|
||||
schema: { type: 'string', enum: this.getEnum('vcs') },
|
||||
},
|
||||
{ name: 'user', example: 'filp' },
|
||||
{ name: 'repo', example: 'whoops' },
|
||||
{ name: 'branch', example: 'master' },
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
async handle({ vcs, user, repo, branch }) {
|
||||
return this.makeBadge({
|
||||
@@ -103,19 +123,29 @@ class ScrutinizerCoverageGitLab extends ScrutinizerCoverageBase {
|
||||
// The example used is valid, but the project will not be accessible if Shields users try to use it.
|
||||
// https://gitlab.propertywindow.nl/propertywindow/client
|
||||
// https://scrutinizer-ci.com/gl/propertywindow/propertywindow/client/badges/quality-score.png?b=master&s=dfae6992a48184cc2333b4c349cec0447f0d67c2
|
||||
static examples = [
|
||||
{
|
||||
title: 'Scrutinizer coverage (GitLab)',
|
||||
pattern: ':instance/:user/:repo/:branch?',
|
||||
namedParams: {
|
||||
instance: 'propertywindow',
|
||||
user: 'propertywindow',
|
||||
repo: 'client',
|
||||
branch: 'master',
|
||||
static openApi = {
|
||||
'/scrutinizer/coverage/gl/{instance}/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'Scrutinizer coverage (GitLab)',
|
||||
parameters: pathParams(
|
||||
{ name: 'instance', example: 'propertywindow' },
|
||||
{ name: 'user', example: 'propertywindow' },
|
||||
{ name: 'repo', example: 'client' },
|
||||
),
|
||||
},
|
||||
staticPreview: this.render({ coverage: 94 }),
|
||||
},
|
||||
]
|
||||
'/scrutinizer/coverage/gl/{instance}/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'Scrutinizer coverage (GitLab) with branch',
|
||||
parameters: pathParams(
|
||||
{ name: 'instance', example: 'propertywindow' },
|
||||
{ name: 'user', example: 'propertywindow' },
|
||||
{ name: 'repo', example: 'client' },
|
||||
{ name: 'branch', example: 'master' },
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
async handle({ instance, user, repo, branch }) {
|
||||
return this.makeBadge({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Joi from 'joi'
|
||||
import { colorScale } from '../color-formatters.js'
|
||||
import { pathParams } from '../index.js'
|
||||
import ScrutinizerBase from './scrutinizer-base.js'
|
||||
|
||||
const schema = Joi.object({
|
||||
@@ -58,19 +59,39 @@ class ScrutinizerQuality extends ScrutinizerQualityBase {
|
||||
pattern: ':vcs(g|b)/:user/:repo/:branch*',
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'Scrutinizer code quality (GitHub/Bitbucket)',
|
||||
pattern: ':vcs(g|b)/:user/:repo/:branch?',
|
||||
namedParams: {
|
||||
vcs: 'g',
|
||||
user: 'filp',
|
||||
repo: 'whoops',
|
||||
branch: 'master',
|
||||
static openApi = {
|
||||
'/scrutinizer/quality/{vcs}/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'Scrutinizer quality (GitHub/Bitbucket)',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'vcs',
|
||||
example: 'g',
|
||||
description: 'Platform: Either Github or Bitbucket',
|
||||
schema: { type: 'string', enum: this.getEnum('vcs') },
|
||||
},
|
||||
{ name: 'user', example: 'filp' },
|
||||
{ name: 'repo', example: 'whoops' },
|
||||
),
|
||||
},
|
||||
staticPreview: this.render({ score: 8.26 }),
|
||||
},
|
||||
]
|
||||
'/scrutinizer/quality/{vcs}/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'Scrutinizer quality (GitHub/Bitbucket) with branch',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'vcs',
|
||||
example: 'g',
|
||||
description: 'Platform: Either Github or Bitbucket',
|
||||
schema: { type: 'string', enum: this.getEnum('vcs') },
|
||||
},
|
||||
{ name: 'user', example: 'filp' },
|
||||
{ name: 'repo', example: 'whoops' },
|
||||
{ name: 'branch', example: 'master' },
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
async handle({ vcs, user, repo, branch }) {
|
||||
return this.makeBadge({
|
||||
@@ -91,19 +112,29 @@ class ScrutinizerQualityGitLab extends ScrutinizerQualityBase {
|
||||
// The example used is valid, but the project will not be accessible if Shields users try to use it.
|
||||
// https://gitlab.propertywindow.nl/propertywindow/client
|
||||
// https://scrutinizer-ci.com/gl/propertywindow/propertywindow/client/badges/quality-score.png?b=master&s=dfae6992a48184cc2333b4c349cec0447f0d67c2
|
||||
static examples = [
|
||||
{
|
||||
title: 'Scrutinizer coverage (GitLab)',
|
||||
pattern: ':instance/:user/:repo/:branch?',
|
||||
namedParams: {
|
||||
instance: 'propertywindow',
|
||||
user: 'propertywindow',
|
||||
repo: 'client',
|
||||
branch: 'master',
|
||||
static openApi = {
|
||||
'/scrutinizer/quality/gl/{instance}/{user}/{repo}': {
|
||||
get: {
|
||||
summary: 'Scrutinizer quality (GitLab)',
|
||||
parameters: pathParams(
|
||||
{ name: 'instance', example: 'propertywindow' },
|
||||
{ name: 'user', example: 'propertywindow' },
|
||||
{ name: 'repo', example: 'client' },
|
||||
),
|
||||
},
|
||||
staticPreview: this.render({ score: 10.0 }),
|
||||
},
|
||||
]
|
||||
'/scrutinizer/quality/gl/{instance}/{user}/{repo}/{branch}': {
|
||||
get: {
|
||||
summary: 'Scrutinizer quality (GitLab) with branch',
|
||||
parameters: pathParams(
|
||||
{ name: 'instance', example: 'propertywindow' },
|
||||
{ name: 'user', example: 'propertywindow' },
|
||||
{ name: 'repo', example: 'client' },
|
||||
{ name: 'branch', example: 'master' },
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
async handle({ instance, user, repo, branch }) {
|
||||
return this.makeBadge({
|
||||
|
||||
@@ -2,7 +2,7 @@ import Joi from 'joi'
|
||||
import dayjs from 'dayjs'
|
||||
import { renderDownloadsBadge } from '../downloads.js'
|
||||
import { nonNegativeInteger } from '../validators.js'
|
||||
import { BaseJsonService } from '../index.js'
|
||||
import { BaseJsonService, pathParams } from '../index.js'
|
||||
|
||||
const schema = Joi.object({
|
||||
total: nonNegativeInteger,
|
||||
@@ -32,36 +32,40 @@ export default class SourceforgeDownloads extends BaseJsonService {
|
||||
|
||||
static route = {
|
||||
base: 'sourceforge',
|
||||
pattern: ':interval(dt|dm|dw|dd)/:project/:folder*',
|
||||
pattern: ':interval(dd|dw|dm|dt)/:project/:folder*',
|
||||
}
|
||||
|
||||
static examples = [
|
||||
{
|
||||
title: 'SourceForge Downloads',
|
||||
pattern: ':interval(dt|dm|dw|dd)/:project',
|
||||
namedParams: {
|
||||
interval: 'dm',
|
||||
project: 'sevenzip',
|
||||
static openApi = {
|
||||
'/sourceforge/{interval}/{project}': {
|
||||
get: {
|
||||
summary: 'SourceForge Downloads',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'interval',
|
||||
example: 'dm',
|
||||
description: 'Daily, Weekly, Monthly, or Total downloads',
|
||||
schema: { type: 'string', enum: this.getEnum('interval') },
|
||||
},
|
||||
{ name: 'project', example: 'sevenzip' },
|
||||
),
|
||||
},
|
||||
staticPreview: this.render({
|
||||
downloads: 215990,
|
||||
interval: 'dm',
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: 'SourceForge Downloads (folder)',
|
||||
pattern: ':interval(dt|dm|dw|dd)/:project/:folder',
|
||||
namedParams: {
|
||||
interval: 'dm',
|
||||
project: 'arianne',
|
||||
folder: 'stendhal',
|
||||
'/sourceforge/{interval}/{project}/{folder}': {
|
||||
get: {
|
||||
summary: 'SourceForge Downloads (folder)',
|
||||
parameters: pathParams(
|
||||
{
|
||||
name: 'interval',
|
||||
example: 'dm',
|
||||
description: 'Daily, Weekly, Monthly, or Total downloads',
|
||||
schema: { type: 'string', enum: this.getEnum('interval') },
|
||||
},
|
||||
{ name: 'project', example: 'arianne' },
|
||||
{ name: 'folder', example: 'stendhal' },
|
||||
),
|
||||
},
|
||||
staticPreview: this.render({
|
||||
downloads: 550,
|
||||
interval: 'dm',
|
||||
}),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
static defaultBadgeData = { label: 'sourceforge' }
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user