From b0084085919fcf3553d51d328fd4988561e03f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=99=8B=E6=99=93=E7=82=9C=20Amio=20/?= Date: Mon, 18 Nov 2019 23:52:07 +0800 Subject: [PATCH] chore: migrate to Now v2 (#320) * feat: new doc generator (stage 1) * feat: migrate badges to now v2 (stage 2) * chore: update build & deploy config (stage 3) * chore: address review comments * chore: cleanup files * fix: now deployment config * fix: ts config * chore: remove topbar * chore: update routes config --- .gitignore | 1 + .nowignore | 4 + README.md | 4 +- {endpoints => api}/amo.ts | 22 ++-- {endpoints => api}/apm.ts | 22 ++-- {endpoints => api}/appveyor.ts | 22 ++-- {endpoints => api}/azure-pipelines.ts | 22 ++-- api/badge.ts | 39 ++++++ {endpoints => api}/badgesize.ts | 22 ++-- {endpoints => api}/bundlephobia.ts | 24 ++-- {endpoints => api}/chrome-web-store.ts | 23 ++-- {endpoints => api}/circleci.ts | 22 ++-- {endpoints => api}/codacy.ts | 23 ++-- {endpoints => api}/codeclimate.ts | 22 ++-- {endpoints => api}/codecov.ts | 22 ++-- {endpoints => api}/coveralls.ts | 22 ++-- {endpoints => api}/crates.ts | 22 ++-- {endpoints => api}/david.ts | 22 ++-- {endpoints => api}/dependabot.ts | 24 ++-- {endpoints => api}/docker.ts | 22 ++-- {endpoints => api}/github.ts | 59 ++++----- {endpoints => api}/hackage.ts | 22 ++-- {endpoints => api}/homebrew.ts | 22 ++-- {endpoints => api}/https.ts | 24 ++-- {endpoints => api}/jsdelivr.ts | 24 ++-- {endpoints => api}/keybase.ts | 22 ++-- {endpoints => api}/lgtm.ts | 24 ++-- {endpoints => api}/npm.ts | 30 ++--- {endpoints => api}/nuget.ts | 22 ++-- {endpoints => api}/opencollective.ts | 22 ++-- {endpoints => api}/packagephobia.ts | 24 ++-- {endpoints => api}/packagist.ts | 26 ++-- {endpoints => api}/pypi.ts | 22 ++-- {endpoints => api}/rubygems.ts | 26 ++-- {endpoints => api}/runkit.ts | 24 ++-- {endpoints => api}/travis.ts | 22 ++-- {endpoints => api}/twitter.ts | 22 ++-- {endpoints => api}/uptime-robot.ts | 22 ++-- {endpoints => api}/vs-marketplace.ts | 22 ++-- {endpoints => api}/xo.ts | 24 ++-- components/home-intro.tsx | 4 +- endpoints/badge.ts | 42 ------- index.ts | 4 +- libs/badge-list.ts | 15 ++- libs/badgen-serve.ts | 165 ------------------------- libs/create-badgen-handler.ts | 22 ++-- libs/gen-help.ts | 71 ----------- libs/{serve-docs.ts => serve-doc.ts} | 69 ++++++++--- now-v1.json | 34 +++++ now-v2.json | 44 ------- now.json | 32 ++--- package.json | 1 - pages/index.tsx | 3 +- server.tsconfig.json | 5 +- tsconfig.json | 8 +- 55 files changed, 463 insertions(+), 967 deletions(-) create mode 100644 .nowignore rename {endpoints => api}/amo.ts (81%) rename {endpoints => api}/apm.ts (78%) rename {endpoints => api}/appveyor.ts (57%) rename {endpoints => api}/azure-pipelines.ts (74%) create mode 100644 api/badge.ts rename {endpoints => api}/badgesize.ts (68%) rename {endpoints => api}/bundlephobia.ts (74%) rename {endpoints => api}/chrome-web-store.ts (81%) rename {endpoints => api}/circleci.ts (67%) rename {endpoints => api}/codacy.ts (79%) rename {endpoints => api}/codeclimate.ts (90%) rename {endpoints => api}/codecov.ts (74%) rename {endpoints => api}/coveralls.ts (74%) rename {endpoints => api}/crates.ts (71%) rename {endpoints => api}/david.ts (80%) rename {endpoints => api}/dependabot.ts (86%) rename {endpoints => api}/docker.ts (72%) rename {endpoints => api}/github.ts (89%) rename {endpoints => api}/hackage.ts (73%) rename {endpoints => api}/homebrew.ts (57%) rename {endpoints => api}/https.ts (80%) rename {endpoints => api}/jsdelivr.ts (75%) rename {endpoints => api}/keybase.ts (65%) rename {endpoints => api}/lgtm.ts (82%) rename {endpoints => api}/npm.ts (92%) rename {endpoints => api}/nuget.ts (75%) rename {endpoints => api}/opencollective.ts (76%) rename {endpoints => api}/packagephobia.ts (69%) rename {endpoints => api}/packagist.ts (89%) rename {endpoints => api}/pypi.ts (64%) rename {endpoints => api}/rubygems.ts (83%) rename {endpoints => api}/runkit.ts (84%) rename {endpoints => api}/travis.ts (75%) rename {endpoints => api}/twitter.ts (60%) rename {endpoints => api}/uptime-robot.ts (88%) rename {endpoints => api}/vs-marketplace.ts (84%) rename {endpoints => api}/xo.ts (74%) delete mode 100644 endpoints/badge.ts delete mode 100644 libs/badgen-serve.ts delete mode 100644 libs/gen-help.ts rename libs/{serve-docs.ts => serve-doc.ts} (58%) create mode 100644 now-v1.json delete mode 100644 now-v2.json diff --git a/.gitignore b/.gitignore index c676298..94d4504 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ dist yarn.lock node_modules +public .firebase .next .meta diff --git a/.nowignore b/.nowignore new file mode 100644 index 0000000..6f724c2 --- /dev/null +++ b/.nowignore @@ -0,0 +1,4 @@ +dist +test +.next +public diff --git a/README.md b/README.md index 0491f9e..d00cfd0 100644 --- a/README.md +++ b/README.md @@ -70,9 +70,9 @@ To ensure that your addition is working correctly, start the development server __NOTES__ -- You can create live badge without touching badgen.net's code. Checkout docs for [/runkit](https://badgen.net/docs/runkit) or [/https](https://badgen.net/docs/https). +- You can create live badge without touching badgen.net's code. Checkout docs for [/runkit](https://badgen.net/runkit) or [/https](https://badgen.net/https). -- The [/runkit](https://badgen.net/docs/runkit) support would be super handy for prototyping a new live badge. +- The [/runkit](https://badgen.net/runkit) support would be super handy for prototyping a new live badge. ### Add Icon diff --git a/endpoints/amo.ts b/api/amo.ts similarity index 81% rename from endpoints/amo.ts rename to api/amo.ts index aa7120a..3ce03a4 100644 --- a/endpoints/amo.ts +++ b/api/amo.ts @@ -1,13 +1,8 @@ import got from '../libs/got' import { millify, stars, version, versionColor } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Mozilla Add-on', examples: { '/amo/v/markdown-viewer-chrome': 'version', @@ -15,14 +10,13 @@ export const meta: Meta = { '/amo/rating/markdown-viewer-chrome': 'rating', '/amo/stars/markdown-viewer-chrome': 'stars', '/amo/reviews/markdown-viewer-chrome': 'reviews', + }, + handlers: { + '/amo/:topic/:name': handler } -} +}) -export const handlers: Handlers = { - '/amo/:topic/:name': handler -} - -async function handler ({ topic, name }: Args) { +async function handler ({ topic, name }: PathArgs) { const endpoint = `https://addons.mozilla.org/api/v3/addons/addon/${name}/` const addon = await got(endpoint).then(res => res.body) @@ -65,5 +59,3 @@ async function handler ({ topic, name }: Args) { } } } - -export default badgenServe(handlers) diff --git a/endpoints/apm.ts b/api/apm.ts similarity index 78% rename from endpoints/apm.ts rename to api/apm.ts index 4da85f1..d58b318 100644 --- a/endpoints/apm.ts +++ b/api/apm.ts @@ -1,28 +1,22 @@ import millify from 'millify' import got from '../libs/got' import { version, versionColor } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Atom Package', examples: { '/apm/v/linter': 'version', '/apm/stars/linter': 'stars', '/apm/license/linter': 'license', '/apm/downloads/linter': 'downloads' + }, + handlers: { + '/apm/:topic/:pkg': handler } -} +}) -export const handlers: Handlers = { - '/apm/:topic/:pkg': handler -} - -async function handler ({ topic, pkg }: Args) { +async function handler ({ topic, pkg }: PathArgs) { const endpoint = `https://atom.io/api/packages/${pkg}` const data = await got(endpoint).then(res => res.body) @@ -66,5 +60,3 @@ async function handler ({ topic, pkg }: Args) { } } } - -export default badgenServe(handlers) diff --git a/endpoints/appveyor.ts b/api/appveyor.ts similarity index 57% rename from endpoints/appveyor.ts rename to api/appveyor.ts index 7831626..e8a2c06 100644 --- a/endpoints/appveyor.ts +++ b/api/appveyor.ts @@ -1,24 +1,18 @@ import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'AppVeyor', examples: { '/appveyor/ci/gruntjs/grunt': 'build', '/appveyor/ci/gruntjs/grunt/deprecate': 'build (branch)' + }, + handlers: { + '/appveyor/ci/:account/:project/:branch?': handler } -} +}) -export const handlers: Handlers = { - '/appveyor/ci/:account/:project/:branch?': handler -} - -async function handler ({ account, project, branch }: Args) { +async function handler ({ account, project, branch }: PathArgs) { branch = branch ? `/branch/${branch}` : '' const endpoint = `https://ci.appveyor.com/api/projects/${account}/${project}${branch}` const { build } = await got(endpoint).then(res => res.body) @@ -29,5 +23,3 @@ async function handler ({ account, project, branch }: Args) { color: build.status === 'success' ? 'green' : 'red' } } - -export default badgenServe(handlers) diff --git a/endpoints/azure-pipelines.ts b/api/azure-pipelines.ts similarity index 74% rename from endpoints/azure-pipelines.ts rename to api/azure-pipelines.ts index 8fb53dd..f5f69ab 100644 --- a/endpoints/azure-pipelines.ts +++ b/api/azure-pipelines.ts @@ -1,27 +1,19 @@ import cheerio from 'cheerio' import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Azure Piplines', examples: { '/azure-pipelines/yarnpkg/yarn/Yarn Acceptance Tests': 'build', '/azure-pipelines/yarnpkg/yarn/Yarn Acceptance Tests/azure-pipelines': 'build (branch)', + }, + handlers: { + '/azure-pipelines/:org/:project/:definition/:branch?': handler } -} +}) -export const handlers: Handlers = { - '/azure-pipelines/:org/:project/:definition/:branch?': handler -} - -export default badgenServe(handlers) - -async function handler ({ org, project, definition, branch = 'master'}: Args) { +async function handler ({ org, project, definition, branch = 'master'}: PathArgs) { // @ts-ignore const response = await got(`https://dev.azure.com/${org}/${project}/_apis/build/status/${definition}?branchName=${branch}`, { json: false }) const contentType = response.headers['content-type'] diff --git a/api/badge.ts b/api/badge.ts new file mode 100644 index 0000000..e62651a --- /dev/null +++ b/api/badge.ts @@ -0,0 +1,39 @@ +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' + +export default createBadgenHandler({ + title: 'Static', + examples: { + '/badge/Swift/4.2/orange': 'swift version', + '/badge/license/MIT/blue': 'license MIT', + '/badge/chat/on%20gitter/cyan': 'chat on gitter', + '/badge/stars/★★★★☆': 'star rating', + '/badge/become/a%20patron/F96854': 'patron', + '/badge/code%20style/standard/f2a': 'code style: standard' + }, + handlers: { + '/badge/:label/:status': handler, + '/badge/:label/:status/:color': handler + } +}) + +async function handler ({ label, status, color }: PathArgs) { + return { + subject: label, + status, + color + } +} + +// { +// title: 'With Options', +// examples: { +// '/badge/icon/github?icon=github': 'use builtin icon', +// '/badge/github/github?icon': 'use builtin icon (by subject)', +// '/badge/jQuery/powered?icon=https://simpleicons.now.sh/jquery/fff': 'use external icon', +// '/badge/icon/github?label=custom%20label': 'custom label', +// '/badge/icon/github?label': 'disable label', +// '/badge/github/github?icon&label': 'use icon, disable label', +// '/badge/platform/ios,macos,tvos?list=|': 'list (custom seprator)' +// } +// } + diff --git a/endpoints/badgesize.ts b/api/badgesize.ts similarity index 68% rename from endpoints/badgesize.ts rename to api/badgesize.ts index a68febd..5b51c2f 100644 --- a/endpoints/badgesize.ts +++ b/api/badgesize.ts @@ -1,28 +1,20 @@ import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Badgesize', examples: { '/badgesize/normal/amio/emoji.json/master/emoji-compact.json': 'normal size', '/badgesize/brotli/amio/emoji.json/master/emoji-compact.json': 'brotli size', '/badgesize/gzip/amio/emoji.json/master/emoji-compact.json': 'gzip size', '/badgesize/normal/https://unpkg.com/snarkdown/dist/snarkdown.js': 'arbitrary url', + }, + handlers: { + '/badgesize/:topic/:path+': handler } -} +}) -export const handlers: Handlers = { - '/badgesize/:topic/:path+': handler -} - -export default badgenServe(handlers) - -async function handler ({ topic, path }: Args) { +async function handler ({ topic, path }: PathArgs) { const endpoint = `https://img.badgesize.io/${path}.json` const { prettySize, color } = await got(endpoint, { query: { diff --git a/endpoints/bundlephobia.ts b/api/bundlephobia.ts similarity index 74% rename from endpoints/bundlephobia.ts rename to api/bundlephobia.ts index 9698e51..bd05087 100644 --- a/endpoints/bundlephobia.ts +++ b/api/bundlephobia.ts @@ -1,31 +1,23 @@ import byteSize from 'byte-size' import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Bundlephobia', examples: { '/bundlephobia/min/react': 'minified', '/bundlephobia/minzip/react': 'minified + gzip', '/bundlephobia/minzip/@material-ui/core': '(scoped pkg) minified + gzip', + }, + handlers: { + '/bundlephobia/:topic/:scope<@.*>/:name': handler, + '/bundlephobia/:topic/:name': handler, } -} - -export const handlers: Handlers = { - '/bundlephobia/:topic/:scope<@.*>/:name': handler, - '/bundlephobia/:topic/:name': handler, -} - -export default badgenServe(handlers) +}) // https://github.com/pastelsky/bundlephobia/issues/4 -async function handler ({ topic, scope, name }: Args) { +async function handler ({ topic, scope, name }: PathArgs) { const pkg = scope ? `${scope}/${name}` : name const endpoint = `https://bundlephobia.com/api/size?package=${pkg}` const resp = await got(endpoint).then(res => res.body) diff --git a/endpoints/chrome-web-store.ts b/api/chrome-web-store.ts similarity index 81% rename from endpoints/chrome-web-store.ts rename to api/chrome-web-store.ts index 2b9d233..7350aa4 100644 --- a/endpoints/chrome-web-store.ts +++ b/api/chrome-web-store.ts @@ -1,14 +1,9 @@ import millify from 'millify' import webstore from 'chrome-webstore' import { version, versionColor, stars } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Chrome Extensions', examples: { '/chrome-web-store/v/ckkdlimhmcjmikdlpkmbgfkaikojcbjk': 'version', @@ -17,17 +12,13 @@ export const meta: Meta = { '/chrome-web-store/stars/ckkdlimhmcjmikdlpkmbgfkaikojcbjk': 'stars', '/chrome-web-store/rating/ckkdlimhmcjmikdlpkmbgfkaikojcbjk': 'rating', '/chrome-web-store/rating-count/ckkdlimhmcjmikdlpkmbgfkaikojcbjk': 'rating count', + }, + handlers: { + '/chrome-web-store/:topic/:id': handler } -} +}) -export const handlers: Handlers = { - '/chrome-web-store/:topic/:id': handler -} - -export default badgenServe(handlers) - - -async function handler ({ topic, id }: Args) { +async function handler ({ topic, id }: PathArgs) { const meta = await webstore.detail({ id }) switch (topic) { case 'v': diff --git a/endpoints/circleci.ts b/api/circleci.ts similarity index 67% rename from endpoints/circleci.ts rename to api/circleci.ts index adf009a..a9c2e06 100644 --- a/endpoints/circleci.ts +++ b/api/circleci.ts @@ -1,27 +1,19 @@ import qs from 'querystring' import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'CircleCI', examples: { '/circleci/github/nuxt/nuxt.js': 'build', '/circleci/github/nuxt/nuxt.js/master': 'build (branch)', + }, + handlers: { + '/circleci/:vcs/:user/:project/:branch?': handler } -} +}) -export const handlers: Handlers = { - '/circleci/:vcs/:user/:project/:branch?': handler -} - -export default badgenServe(handlers) - -async function handler ({ vcs, user, project, branch }: Args) { +async function handler ({ vcs, user, project, branch }: PathArgs) { // https://circleci.com/docs/api/v1-reference/ branch = branch ? `/tree/${qs.escape(branch)}` : '' const endpoint = `https://circleci.com/api/v1.1/project/${vcs}/${user}/${project}${branch}?filter=completed&limit=1` diff --git a/endpoints/codacy.ts b/api/codacy.ts similarity index 79% rename from endpoints/codacy.ts rename to api/codacy.ts index 1d89472..9ad3668 100644 --- a/endpoints/codacy.ts +++ b/api/codacy.ts @@ -1,28 +1,19 @@ -import { - badgenServe, - BadgenServeHandlerArgs as Args, - BadgenServeHandlers as Handlers, - BadgenServeMeta as Meta -} from '../libs/badgen-serve' -// import { coverage as cov, coverageColor } from '../libs/utils' import got from '../libs/got' import { coverage as cov, coverageColor } from '../libs/utils' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Codacy', examples: { '/codacy/coverage/f0875490cea1497a9eca9c25f3f7774e': 'coverage', '/codacy/coverage/f0875490cea1497a9eca9c25f3f7774e/dev-master': 'branch coverage', '/codacy/grade/f0875490cea1497a9eca9c25f3f7774e': 'code quality', '/codacy/grade/f0875490cea1497a9eca9c25f3f7774e/dev-master': 'branch code quality' + }, + handlers: { + '/codacy/:type/:projectId/:branch?': handler } -} - -export const handlers: Handlers = { - '/codacy/:type/:projectId/:branch?': handler -} - -export default badgenServe(handlers) +}) const uriBase = 'https://api.codacy.com/project/badge' @@ -43,7 +34,7 @@ const SUBJECT_BY_TYPE = { grade: 'code quality' } -async function handler ({ type, projectId, branch }: Args) { +async function handler ({ type, projectId, branch }: PathArgs) { if (projectId) { const svg = await got(`${uriBase}/${type}/${projectId}`, // @ts-ignore diff --git a/endpoints/codeclimate.ts b/api/codeclimate.ts similarity index 90% rename from endpoints/codeclimate.ts rename to api/codeclimate.ts index 4a82a61..9589383 100644 --- a/endpoints/codeclimate.ts +++ b/api/codeclimate.ts @@ -1,13 +1,8 @@ import got from '../libs/got' import { coverage as cov, scale } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Code Climate', examples: { '/codeclimate/loc/codeclimate/codeclimate': 'lines of code', @@ -17,16 +12,13 @@ export const meta: Meta = { '/codeclimate/maintainability-percentage/codeclimate/codeclimate': 'maintainability (percentage)', '/codeclimate/coverage/codeclimate/codeclimate': 'coverage', '/codeclimate/coverage-letter/codeclimate/codeclimate': 'coverage (letter)', + }, + handlers: { + '/codeclimate/:topic/:owner/:repo': handler } -} +}) -export const handlers: Handlers = { - '/codeclimate/:topic/:owner/:repo': handler -} - -export default badgenServe(handlers) - -async function handler ({ topic, owner, repo }: Args) { +async function handler ({ topic, owner, repo }: PathArgs) { const api = `https://api.codeclimate.com/v1/repos?github_slug=${owner}/${repo}` const meta = await got(api).then(res => res.body.data[0]) diff --git a/endpoints/codecov.ts b/api/codecov.ts similarity index 74% rename from endpoints/codecov.ts rename to api/codecov.ts index 80cf227..25e913c 100644 --- a/endpoints/codecov.ts +++ b/api/codecov.ts @@ -1,13 +1,8 @@ import got from '../libs/got' import { coverage, coverageColor } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'CodeCov', examples: { '/codecov/c/github/babel/babel': 'coverage (github)', @@ -16,16 +11,13 @@ export const meta: Meta = { '/codecov/c/bitbucket/ignitionrobotics/ign-math/master': 'coverage (bitbucket, branch)', '/codecov/c/gitlab/gitlab-org/gitaly': 'coverage (gitlab)', '/codecov/c/gitlab/gitlab-org/gitaly/master': 'coverage (gitlab, branch)' + }, + handlers: { + '/codecov/c/:vcs/:owner/:repo/:branch?': handler } -} +}) -export const handlers: Handlers = { - '/codecov/c/:vcs/:owner/:repo/:branch?': handler -} - -export default badgenServe(handlers) - -async function handler ({ vcs, owner, repo, branch }: Args) { +async function handler ({ vcs, owner, repo, branch }: PathArgs) { const vcsType = { github: 'gh', bitbucket: 'bb', diff --git a/endpoints/coveralls.ts b/api/coveralls.ts similarity index 74% rename from endpoints/coveralls.ts rename to api/coveralls.ts index b789406..c23e3c1 100644 --- a/endpoints/coveralls.ts +++ b/api/coveralls.ts @@ -1,31 +1,23 @@ import got from '../libs/got' import { coverage as cov, coverageColor } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Coveralls', examples: { '/coveralls/c/github/jekyll/jekyll': 'coverage (github)', '/coveralls/c/github/jekyll/jekyll/master': 'coverage (github, branch)', '/coveralls/c/bitbucket/pyKLIP/pyklip': 'coverage (bitbucket)', '/coveralls/c/bitbucket/pyKLIP/pyklip/master': 'coverage (bitbucket, branch)', + }, + handlers: { + '/coveralls/c/:vcs/:owner/:repo/:branch?': handler } -} - -export const handlers: Handlers = { - '/coveralls/c/:vcs/:owner/:repo/:branch?': handler -} - -export default badgenServe(handlers) +}) // Detect coveralls.io's badge redirection instead of using it's api // See https://github.com/badgen/badgen.net/issues/96 -async function handler ({ vcs, owner, repo, branch }: Args) { +async function handler ({ vcs, owner, repo, branch }: PathArgs) { const endpoint = `https://coveralls.io/repos/${vcs}/${owner}/${repo}/badge.svg` const badgeURL = await got.head(endpoint, { // @ts-ignore diff --git a/endpoints/crates.ts b/api/crates.ts similarity index 71% rename from endpoints/crates.ts rename to api/crates.ts index 5053c61..a71f8c5 100644 --- a/endpoints/crates.ts +++ b/api/crates.ts @@ -1,28 +1,20 @@ import got from '../libs/got' import { millify, version, versionColor } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Rust Crates', examples: { '/crates/v/regex': 'version', '/crates/d/regex': 'downloads', '/crates/dl/regex': 'downloads (latest version)', + }, + handlers: { + '/crates/:topic/:pkg': handler } -} +}) -export const handlers: Handlers = { - '/crates/:topic/:pkg': handler -} - -export default badgenServe(handlers) - -async function handler ({topic, pkg}: Args) { +async function handler ({topic, pkg}: PathArgs) { const endpoint = `https://crates.io/api/v1/crates/${pkg}` const { crate } = await got(endpoint).then(res => res.body) diff --git a/endpoints/david.ts b/api/david.ts similarity index 80% rename from endpoints/david.ts rename to api/david.ts index 68d024c..2c8686a 100644 --- a/endpoints/david.ts +++ b/api/david.ts @@ -1,12 +1,7 @@ import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'David DM', examples: { '/david/dep/zeit/pkg': 'dependencies', @@ -14,12 +9,11 @@ export const meta: Meta = { '/david/peer/epoberezkin/ajv-keywords': 'peer dependencies', '/david/optional/epoberezkin/ajv-keywords': 'optional dependencies', '/david/dep/babel/babel/packages/babel-cli': 'dependencies (sub path)', + }, + handlers: { + '/david/:topic/:user/:repo/:path*': handler } -} - -export const handlers: Handlers = { - '/david/:topic/:user/:repo/:path*': handler -} +}) const statusInfo = { insecure: ['insecure', 'red'], @@ -29,7 +23,7 @@ const statusInfo = { none: ['none', 'green'] } -async function handler ({ topic, user, repo, path }: Args) { +async function handler ({ topic, user, repo, path }: PathArgs) { const prefix = { dep: '', dev: 'dev-', @@ -71,5 +65,3 @@ async function handler ({ topic, user, repo, path }: Args) { } } } - -export default badgenServe(handlers) diff --git a/endpoints/dependabot.ts b/api/dependabot.ts similarity index 86% rename from endpoints/dependabot.ts rename to api/dependabot.ts index 759f805..ffe0925 100644 --- a/endpoints/dependabot.ts +++ b/api/dependabot.ts @@ -1,10 +1,5 @@ import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' const help = ` ## Private repositories @@ -38,21 +33,18 @@ https://badgen.net/dependabot/badgen/example-private-repo/123456789?icon= ` -export const meta: Meta = { +export default createBadgenHandler({ title: 'Dependabot', + help, examples: { '/dependabot/dependabot/dependabot-core/?icon=dependabot': 'status' }, - help -} + handlers: { + '/dependabot/:owner/:repo/:identifier?': handler + } +}) -export const handlers: Handlers = { - '/dependabot/:owner/:repo/:identifier?': handler -} - -export default badgenServe(handlers) - -async function handler ({ owner, repo, identifier }: Args) { +async function handler ({ owner, repo, identifier }: PathArgs) { // https://github.com/dependabot/feedback/issues/6#issuecomment-503994253 let endpoint = `https://api.dependabot.com/badges/status?host=github&repo=${owner}/${repo}` if (identifier) { diff --git a/endpoints/docker.ts b/api/docker.ts similarity index 72% rename from endpoints/docker.ts rename to api/docker.ts index c329e7e..7c571ea 100644 --- a/endpoints/docker.ts +++ b/api/docker.ts @@ -1,29 +1,21 @@ import millify from 'millify' import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Docker', examples: { '/docker/pulls/library/ubuntu': 'pulls (library)', '/docker/stars/library/ubuntu': 'stars (library)', '/docker/pulls/amio/node-chrome': 'pulls (scoped)', '/docker/stars/library/mongo?icon=docker&label=stars': 'stars (icon & label)', + }, + handlers: { + '/docker/:topic/:scope/:name': handler } -} +}) -export const handlers: Handlers = { - '/docker/:topic/:scope/:name': handler -} - -export default badgenServe(handlers) - -async function handler ({ topic, scope, name }: Args) { +async function handler ({ topic, scope, name }: PathArgs) { if (!['stars', 'pulls'].includes(topic)) { return { subject: 'docker', diff --git a/endpoints/github.ts b/api/github.ts similarity index 89% rename from endpoints/github.ts rename to api/github.ts index a76cc60..1e5ad4c 100644 --- a/endpoints/github.ts +++ b/api/github.ts @@ -3,15 +3,9 @@ import distanceToNow from 'date-fns/formatDistanceToNow' import got from '../libs/got' import { version, millify } from '../libs/utils' -import { - badgenServe, - BadgenError, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, BadgenError, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'GitHub', examples: { '/github/release/babel/babel': 'latest release', @@ -55,24 +49,23 @@ export const meta: Meta = { '/github/assets-dl/electron/electron/v7.0.0': 'assets downloads for a tag', '/github/dependents-repo/micromatch/micromatch': 'repository depentents', '/github/dependents-pkg/micromatch/micromatch': 'package dependents', + }, + handlers: { + '/github/:topic/:owner/:repo': repoStats, + '/github/:topic/:owner/:repo': repoStats, + '/github/:topic/:owner/:repo': repoStats, + '/github/:topic/:owner/:repo/:label/:states?': repoStats, + '/github/:topic/:owner/:repo/:ref?': repoStats, + '/github/:topic/:owner/:repo/:tag?': downloads, // `dt` is deprecated + '/github/release/:owner/:repo/:channel?': release, + '/github/checks/:owner/:repo/:ref?': checks, + '/github/status/:owner/:repo/:ref?': status, + '/github/status/:owner/:repo/:ref/:context+': status, + '/github/contributors/:owner/:repo': contributors, + '/github/dependents-repo/:owner/:repo': dependents('REPOSITORY'), + '/github/dependents-pkg/:owner/:repo': dependents('PACKAGE'), } -} - -export const handlers: Handlers = { - '/github/:topic/:owner/:repo': repoStats, - '/github/:topic/:owner/:repo': repoStats, - '/github/:topic/:owner/:repo': repoStats, - '/github/:topic/:owner/:repo/:label/:states?': repoStats, - '/github/:topic/:owner/:repo/:ref?': repoStats, - '/github/:topic/:owner/:repo/:tag?': downloads, // `dt` is deprecated - '/github/release/:owner/:repo/:channel?': release, - '/github/checks/:owner/:repo/:ref?': checks, - '/github/status/:owner/:repo/:ref?': status, - '/github/status/:owner/:repo/:ref/:context+': status, - '/github/contributors/:owner/:repo': contributors, - '/github/dependents-repo/:owner/:repo': dependents('REPOSITORY'), - '/github/dependents-pkg/:owner/:repo': dependents('PACKAGE'), -} +}) const pickGithubToken = () => { const { GH_TOKENS } = process.env @@ -125,7 +118,7 @@ function combined (states: Array, stateKey: string = 'state') { throw new Error(`Unknown states: ${states.map(x => x.state).join()}`) } -async function checks ({ owner, repo, ref = 'master'}: Args) { +async function checks ({ owner, repo, ref = 'master'}: PathArgs) { const resp = await restGithub(`repos/${owner}/${repo}/commits/${ref}/check-runs`, 'antiope') const status = combined(resp.check_runs, 'conclusion') @@ -136,7 +129,7 @@ async function checks ({ owner, repo, ref = 'master'}: Args) { } } -async function status ({ owner, repo, ref = 'master', context }: Args) { +async function status ({ owner, repo, ref = 'master', context }: PathArgs) { const resp = await restGithub(`repos/${owner}/${repo}/commits/${ref}/status`) let state = typeof context === 'string' @@ -162,7 +155,7 @@ async function status ({ owner, repo, ref = 'master', context }: Args) { } } -async function release ({ owner, repo, channel }: Args) { +async function release ({ owner, repo, channel }: PathArgs) { const releases = await restGithub(`repos/${owner}/${repo}/releases`) if (!releases || !releases.length) { @@ -192,7 +185,7 @@ async function release ({ owner, repo, channel }: Args) { } } -async function contributors ({ owner, repo }: Args) { +async function contributors ({ owner, repo }: PathArgs) { const contributors = await restGithub(`repos/${owner}/${repo}/contributors`) return { @@ -202,7 +195,7 @@ async function contributors ({ owner, repo }: Args) { } } -async function downloads ({ owner, repo, tag }: Args) { +async function downloads ({ owner, repo, tag }: PathArgs) { const releaseSelection = tag ? `tags/${tag}` : 'latest' const release = await restGithub(`repos/${owner}/${repo}/releases/${releaseSelection}`) @@ -303,7 +296,7 @@ const makeRepoQuery = (topic, owner, repo, restArgs) => { } } -async function repoStats ({topic, owner, repo, ...restArgs}: Args) { +async function repoStats ({topic, owner, repo, ...restArgs}: PathArgs) { const result = await makeRepoQuery(topic, owner, repo, restArgs) if (!result) { @@ -419,7 +412,7 @@ async function repoStats ({topic, owner, repo, ...restArgs}: Args) { } function dependents (type: string) { - return async function ({ owner, repo }: Args) { + return async function ({ owner, repo }: PathArgs) { const html = await got(`https://github.com/${owner}/${repo}/network/dependents`, { // @ts-ignore json: false, @@ -446,5 +439,3 @@ const parseDependents = (html, type) => { return depLink.text().replace(/[^0-9,]/g, '') } - -export default badgenServe(handlers) diff --git a/endpoints/hackage.ts b/api/hackage.ts similarity index 73% rename from endpoints/hackage.ts rename to api/hackage.ts index a44ffac..3589f21 100644 --- a/endpoints/hackage.ts +++ b/api/hackage.ts @@ -1,28 +1,20 @@ import got from '../libs/got' import { version as v, versionColor } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Hackage', examples: { '/hackage/v/abt': 'version', '/hackage/v/Cabal': 'version', '/hackage/license/Cabal': 'license', + }, + handlers: { + '/hackage/:topic/:pkg': handler } -} +}) -export const handlers: Handlers = { - '/hackage/:topic/:pkg': handler -} - -export default badgenServe(handlers) - -async function handler ({ topic, pkg }: Args) { +async function handler ({ topic, pkg }: PathArgs) { const endpoint = `https://hackage.haskell.org/package/${pkg}/${pkg}.cabal` // @ts-ignore const cabal = await got(endpoint, { json: false }).then(res => res.body) diff --git a/endpoints/homebrew.ts b/api/homebrew.ts similarity index 57% rename from endpoints/homebrew.ts rename to api/homebrew.ts index 98cba8c..6e33e77 100644 --- a/endpoints/homebrew.ts +++ b/api/homebrew.ts @@ -1,25 +1,19 @@ import got from '../libs/got' import { version, versionColor } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Homebrew', examples: { '/homebrew/v/fish': 'version', '/homebrew/v/cake': 'version' + }, + handlers: { + '/homebrew/v/:pkg': handler } -} +}) -export const handlers: Handlers = { - '/homebrew/v/:pkg': handler -} - -async function handler ({ pkg }: Args) { +async function handler ({ pkg }: PathArgs) { const endpoint = `https://formulae.brew.sh/api/formula/${pkg}.json` const { versions } = await got(endpoint).then(res => res.body) @@ -29,5 +23,3 @@ async function handler ({ pkg }: Args) { color: versionColor(versions.stable) } } - -export default badgenServe(handlers) diff --git a/endpoints/https.ts b/api/https.ts similarity index 80% rename from endpoints/https.ts rename to api/https.ts index 83f11a8..5f53e96 100644 --- a/endpoints/https.ts +++ b/api/https.ts @@ -1,10 +1,5 @@ import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' const help = ` ## Use Badgen with HTTPS Endpoint @@ -50,23 +45,20 @@ Furthermore, you may append path args to it: ` -export const meta: Meta = { +export default createBadgenHandler({ title: 'With HTTPS Endpoint', + help, examples: { '/https/cal-badge-icd0onfvrxx6.runkit.sh': 'https endpoint', '/https/cal-badge-icd0onfvrxx6.runkit.sh/Asia/Shanghai': 'https endpoint (with path args)', '/https/cal-badge-icd0onfvrxx6.runkit.sh/America/Los_Angeles': 'https endpoint (with path args)', }, - help -} + handlers: { + '/https/:hostname/:path*': handler + } +}) -export const handlers: Handlers = { - '/https/:hostname/:path*': handler -} - -async function handler ({ hostname, path }: Args) { +async function handler ({ hostname, path }: PathArgs) { const endpoint = `https://${hostname}/${path || ''}` return await got(endpoint).then(res => res.body) } - -export default badgenServe(handlers) diff --git a/endpoints/jsdelivr.ts b/api/jsdelivr.ts similarity index 75% rename from endpoints/jsdelivr.ts rename to api/jsdelivr.ts index d707671..f17978f 100644 --- a/endpoints/jsdelivr.ts +++ b/api/jsdelivr.ts @@ -1,31 +1,23 @@ import millify from 'millify' import got from '../libs/got' import { versionColor } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'jsDelivr', examples: { '/jsdelivr/hits/gh/jquery/jquery': 'hits (per month)', '/jsdelivr/hits/npm/lodash': 'hits (per month)', '/jsdelivr/rank/npm/lodash': 'rank', '/jsdelivr/v/npm/lodash': 'version', + }, + handlers: { + '/jsdelivr/:topic/:platform/:pkg+': handler, + '/jsdelivr/:topic/npm/:pkg+': handler } -} +}) -export const handlers: Handlers = { - '/jsdelivr/:topic/:platform/:pkg+': handler, - '/jsdelivr/:topic/npm/:pkg+': handler -} - -export default badgenServe(handlers) - -async function handler ({ topic, platform, pkg }: Args) { +async function handler ({ topic, platform, pkg }: PathArgs) { switch (topic) { case 'hits': return stats('hits', platform, pkg) diff --git a/endpoints/keybase.ts b/api/keybase.ts similarity index 65% rename from endpoints/keybase.ts rename to api/keybase.ts index 89e46c6..2b7ed6d 100644 --- a/endpoints/keybase.ts +++ b/api/keybase.ts @@ -1,25 +1,17 @@ import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Keybase', examples: { '/keybase/pgp/lukechilds': 'pgp key', + }, + handlers: { + '/keybase/:topic/:username': handler } -} +}) -export const handlers: Handlers = { - '/keybase/:topic/:username': handler -} - -export default badgenServe(handlers) - -async function handler ({ topic, username }: Args) { +async function handler ({ topic, username }: PathArgs) { const endpoint = `https://keybase.io/_/api/1.0/user/lookup.json` const { body } = await got(endpoint, { query: { diff --git a/endpoints/lgtm.ts b/api/lgtm.ts similarity index 82% rename from endpoints/lgtm.ts rename to api/lgtm.ts index e5c2663..d70ea00 100644 --- a/endpoints/lgtm.ts +++ b/api/lgtm.ts @@ -1,13 +1,8 @@ import millify from 'millify' import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'LGTM', examples: { '/lgtm/langs/g/apache/cloudstack/java': 'langs', @@ -16,17 +11,14 @@ export const meta: Meta = { '/lgtm/grade/g/apache/cloudstack/java': 'grade (java)', '/lgtm/grade/g/apache/cloudstack': 'grade (auto)', '/lgtm/grade/g/systemd/systemd': 'grade (auto)', + }, + handlers: { + '/lgtm/:topic/g/:owner/:name/:lang?': handler, + '/lgtm/:topic/:lang/g/:owner/:name': handler, // deprecated } -} +}) -export const handlers: Handlers = { - '/lgtm/:topic/g/:owner/:name/:lang?': handler, - '/lgtm/:topic/:lang/g/:owner/:name': handler, // deprecated -} - -export default badgenServe(handlers) - -async function handler ({ topic, owner, name, lang }: Args) { +async function handler ({ topic, owner, name, lang }: PathArgs) { // https://lgtm.com/help/lgtm/api/api-v1#LGTM-API-specification-Projects const endpoint = `https://lgtm.com/api/v1.0/projects/g/${owner}/${name}` const data = await got(endpoint).then(res => res.body) diff --git a/endpoints/npm.ts b/api/npm.ts similarity index 92% rename from endpoints/npm.ts rename to api/npm.ts index 104ef80..e835264 100644 --- a/endpoints/npm.ts +++ b/api/npm.ts @@ -1,18 +1,9 @@ import cheerio from 'cheerio' import got from '../libs/got' import { millify, version, versionColor } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -// https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md -// https://github.com/npm/registry/blob/master/docs/download-counts.md -// https://unpkg.com/ - -export const meta: Meta = { +export default createBadgenHandler({ title: 'npm', examples: { '/npm/v/express': 'version', @@ -31,17 +22,18 @@ export const meta: Meta = { '/npm/types/tslib': 'types', '/npm/types/react': 'types', '/npm/types/queri': 'types', + }, + handlers: { + '/npm/:topic/:scope<@.+>/:pkg/:tag?': handler, + '/npm/:topic/:pkg/:tag?': handler } -} +}) -export const handlers: Handlers = { - '/npm/:topic/:scope<@.+>/:pkg/:tag?': handler, - '/npm/:topic/:pkg/:tag?': handler -} +// https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md +// https://github.com/npm/registry/blob/master/docs/download-counts.md +// https://unpkg.com/ -export default badgenServe(handlers) - -async function handler ({ topic, scope, pkg, tag }: Args) { +async function handler ({ topic, scope, pkg, tag }: PathArgs) { const npmName = scope ? `${scope}/${pkg}` : pkg switch (topic) { diff --git a/endpoints/nuget.ts b/api/nuget.ts similarity index 75% rename from endpoints/nuget.ts rename to api/nuget.ts index 8ede2a8..628349c 100644 --- a/endpoints/nuget.ts +++ b/api/nuget.ts @@ -1,32 +1,24 @@ import got from '../libs/got' import { version, versionColor } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Nuget', examples: { '/nuget/v/newtonsoft.json': 'version (stable channel)', '/nuget/v/newtonsoft.json/pre': 'version (pre channel)', '/nuget/v/newtonsoft.json/latest': 'version (latest channel)', + }, + handlers: { + '/nuget/v/:project/:channel?': handler } -} - -export const handlers: Handlers = { - '/nuget/v/:project/:channel?': handler -} - -export default badgenServe(handlers) +}) const pre = versions => versions.filter(v => v.includes('-')) const stable = versions => versions.filter(v => !v.includes('-')) const latest = versions => versions.length > 0 && versions.slice(-1)[0] -async function handler ({ project, channel }: Args) { +async function handler ({ project, channel }: PathArgs) { const endpoint = `https://api.nuget.org/v3-flatcontainer/${project}/index.json` const { versions } = await got(endpoint).then(res => res.body) diff --git a/endpoints/opencollective.ts b/api/opencollective.ts similarity index 76% rename from endpoints/opencollective.ts rename to api/opencollective.ts index 861229e..43a3afe 100644 --- a/endpoints/opencollective.ts +++ b/api/opencollective.ts @@ -1,30 +1,22 @@ import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Open Collective', examples: { '/opencollective/backers/webpack': 'backers', '/opencollective/contributors/webpack': 'contributors', '/opencollective/balance/webpack': 'balance', '/opencollective/yearly/webpack': 'yearly income', + }, + handlers: { + '/opencollective/:topic/:slug': handler } -} - -export const handlers: Handlers = { - '/opencollective/:topic/:slug': handler -} - -export default badgenServe(handlers) +}) // https://developer.opencollective.com/#/api/collectives -async function handler ({ topic, slug }: Args) { +async function handler ({ topic, slug }: PathArgs) { const endpoint = `https://opencollective.com/${slug}.json` const details = await got(endpoint).then(res => res.body) diff --git a/endpoints/packagephobia.ts b/api/packagephobia.ts similarity index 69% rename from endpoints/packagephobia.ts rename to api/packagephobia.ts index 1ab5814..58d7876 100644 --- a/endpoints/packagephobia.ts +++ b/api/packagephobia.ts @@ -1,28 +1,20 @@ import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Packagephobia', examples: { '/packagephobia/install/webpack': 'install size', '/packagephobia/publish/webpack': 'publish size', '/packagephobia/publish/@tusbar/cache-control': '(scoped pkg) publish size', + }, + handlers: { + '/packagephobia/:topic/:scope<@.*>/:name': handler, + '/packagephobia/:topic/:name': handler, } -} +}) -export const handlers: Handlers = { - '/packagephobia/:topic/:scope<@.*>/:name': handler, - '/packagephobia/:topic/:name': handler, -} - -export default badgenServe(handlers) - -async function handler ({ topic, scope, name}: Args) { +async function handler ({ topic, scope, name}: PathArgs) { const pkg = scope ? `${scope}/${name}` : name const endpoint = `https://packagephobia.now.sh/v2/api.json?p=${pkg}` const { install, publish } = await got(endpoint).then(res => res.body) diff --git a/endpoints/packagist.ts b/api/packagist.ts similarity index 89% rename from endpoints/packagist.ts rename to api/packagist.ts index 3323966..c96f79e 100644 --- a/endpoints/packagist.ts +++ b/api/packagist.ts @@ -1,14 +1,9 @@ import millify from 'millify' import got from '../libs/got' import { version as v, versionColor, versionCompare } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Packagist', examples: { '/packagist/v/monolog/monolog': 'version', @@ -28,16 +23,13 @@ export const meta: Meta = { '/packagist/lang/monolog/monolog': 'language', '/packagist/license/monolog/monolog': 'license', '/packagist/php/monolog/monolog': 'php', + }, + handlers: { + '/packagist/:topic/:vendor/:pkg/:channel?': handler, + '/packagist/:topic/:vendor/:pkg': handler, + '/packagist/:topic/:vendor/:pkg': handler } -} - -export const handlers: Handlers = { - '/packagist/:topic/:vendor/:pkg/:channel?': handler, - '/packagist/:topic/:vendor/:pkg': handler, - '/packagist/:topic/:vendor/:pkg': handler -} - -export default badgenServe(handlers) +}) const pre = versions => versions.filter(v => v.includes('-') && v.indexOf('dev') !== 0) const stable = versions => versions.filter(v => !v.includes('-')) @@ -65,7 +57,7 @@ const getVersion = (packageMeta, channel) => { return version || latest(versions) } -async function handler ({ topic, vendor, pkg, channel = 'latest' }: Args) { +async function handler ({ topic, vendor, pkg, channel = 'latest' }: PathArgs) { const endpoint = `https://packagist.org/packages/${vendor}/${pkg}.json` const { package: packageMeta } = await got(endpoint).then(res => res.body) diff --git a/endpoints/pypi.ts b/api/pypi.ts similarity index 64% rename from endpoints/pypi.ts rename to api/pypi.ts index 6b9113d..90ad6f1 100644 --- a/endpoints/pypi.ts +++ b/api/pypi.ts @@ -1,28 +1,20 @@ import got from '../libs/got' import { version, versionColor } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Pypi', examples: { '/pypi/v/pip': 'version', '/pypi/v/docutils': 'version', '/pypi/license/pip': 'license', + }, + handlers: { + '/pypi/:topic/:project': handler } -} +}) -export const handlers: Handlers = { - '/pypi/:topic/:project': handler -} - -export default badgenServe(handlers) - -async function handler ({ topic, project }: Args) { +async function handler ({ topic, project }: PathArgs) { const endpoint = `https://pypi.org/pypi/${project}/json` const { info } = await got(endpoint).then(res => res.body) diff --git a/endpoints/rubygems.ts b/api/rubygems.ts similarity index 83% rename from endpoints/rubygems.ts rename to api/rubygems.ts index ebb482a..65af211 100644 --- a/endpoints/rubygems.ts +++ b/api/rubygems.ts @@ -1,14 +1,9 @@ import millify from 'millify' import got from '../libs/got' import { version as v, versionColor } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Ruby Gems', examples: { '/rubygems/v/rails': 'version (stable)', @@ -18,15 +13,12 @@ export const meta: Meta = { '/rubygems/dv/rails': 'latest version downloads', '/rubygems/n/rails': 'name', '/rubygems/p/rails': 'platform', + }, + handlers: { + '/rubygems/v/:gem/:channel?': versionHandler, + '/rubygems/:topic/:gem': handler } -} - -export const handlers: Handlers = { - '/rubygems/v/:gem/:channel?': versionHandler, - '/rubygems/:topic/:gem': handler -} - -export default badgenServe(handlers) +}) const preConditions = ['.rc', '.beta', '-rc', '-beta'] @@ -52,7 +44,7 @@ const stable = versions => versions.filter(v => { const latest = versions => versions.length > 0 && versions.slice(-1)[0] -async function versionHandler ({ gem, channel = 'stable' }: Args) { +async function versionHandler ({ gem, channel = 'stable' }: PathArgs) { const endpoint = `https://rubygems.org/api/v1/versions/${gem}.json` const response = await got(endpoint).then(res => res.body) @@ -81,7 +73,7 @@ async function versionHandler ({ gem, channel = 'stable' }: Args) { } } -async function handler ({ topic, gem }: Args) { +async function handler ({ topic, gem }: PathArgs) { const endpoint = `https://rubygems.org/api/v1/gems/${gem}.json` const response = await got(endpoint).then(res => res.body) diff --git a/endpoints/runkit.ts b/api/runkit.ts similarity index 84% rename from endpoints/runkit.ts rename to api/runkit.ts index 387606d..7fb541c 100644 --- a/endpoints/runkit.ts +++ b/api/runkit.ts @@ -1,10 +1,5 @@ import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' const help = ` https://badgen.net/runkit/cal-badge-icd0onfvrxx6/Asia/Shanghai @@ -65,23 +60,20 @@ https://cal-badge-icd0onfvrxx6.runkit.sh/Asia/Shanghai \`\`\` ` -export const meta: Meta = { +export default createBadgenHandler({ title: 'With RunKit Endpoint', + help, examples: { '/runkit/satisfaction-flq08o9mm3ka/102909/topic': 'satisfaction (topic)', '/runkit/satisfaction-flq08o9mm3ka/102909/people': 'satisfaction (people)', '/runkit/satisfaction-flq08o9mm3ka/102909/employee': 'satisfaction (employ)', }, - help -} + handlers: { + '/runkit/:endpoint-id/:path*': handler + } +}) -export const handlers: Handlers = { - '/runkit/:endpoint-id/:path*': handler -} - -async function handler ({ 'endpoint-id': id, path }: Args) { +async function handler ({ 'endpoint-id': id, path }: PathArgs) { const endpoint = `https://${id}.runkit.sh/${path || ''}` return await got(endpoint).then(res => res.body) } - -export default badgenServe(handlers) diff --git a/endpoints/travis.ts b/api/travis.ts similarity index 75% rename from endpoints/travis.ts rename to api/travis.ts index 25d644c..bce87a5 100644 --- a/endpoints/travis.ts +++ b/api/travis.ts @@ -1,26 +1,18 @@ import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Travis CI', examples: { '/travis/babel/babel': 'build', '/travis/babel/babel/6.x': 'build (branch)', + }, + handlers: { + '/travis/:user/:repo/:branch?': handler } -} +}) -export const handlers: Handlers = { - '/travis/:user/:repo/:branch?': handler -} - -export default badgenServe(handlers) - -async function handler ({ user, repo, branch = 'master' }: Args) { +async function handler ({ user, repo, branch = 'master' }: PathArgs) { const com = `https://api.travis-ci.com/${user}/${repo}.svg?branch=${branch}` const org = `https://api.travis-ci.org/${user}/${repo}.svg?branch=${branch}` const [svg1, svg2] = await Promise.all([ diff --git a/endpoints/twitter.ts b/api/twitter.ts similarity index 60% rename from endpoints/twitter.ts rename to api/twitter.ts index ed9ee49..957824f 100644 --- a/endpoints/twitter.ts +++ b/api/twitter.ts @@ -1,27 +1,19 @@ import millify from 'millify' import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Twitter', examples: { '/twitter/follow/rustlang': 'followers count', '/twitter/follow/golang': 'followers count', + }, + handlers: { + '/twitter/:topic/:user': handler } -} +}) -export const handlers: Handlers = { - '/twitter/:topic/:user': handler -} - -export default badgenServe(handlers) - -async function handler ({ topic, user }: Args) { +async function handler ({ topic, user }: PathArgs) { const endpoint = `http://cdn.syndication.twimg.com/widgets/followbutton/info.json?screen_names=${user}` const [info] = await got(endpoint).then(res => res.body) diff --git a/endpoints/uptime-robot.ts b/api/uptime-robot.ts similarity index 88% rename from endpoints/uptime-robot.ts rename to api/uptime-robot.ts index c4d4e35..680b532 100644 --- a/endpoints/uptime-robot.ts +++ b/api/uptime-robot.ts @@ -1,11 +1,6 @@ import got from '../libs/got' import { scale } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' const help = `## Usage @@ -22,7 +17,7 @@ To use an \`/uptime-robot\` badge, you have to create or find an API key specifi From your UptimeRobot dashboard, go to [My Settings](https://uptimerobot.com/dashboard.php#mySettings) > API Settings > Monitor-Specific API Keys.` -export const meta: Meta = { +export default createBadgenHandler({ help, title: 'Uptime Robot', examples: { @@ -31,14 +26,11 @@ export const meta: Meta = { '/uptime-robot/week/m780862024-50db2c44c703e5c68d6b1ebb': '(past week) uptime', '/uptime-robot/month/m780862024-50db2c44c703e5c68d6b1ebb': '(past month) uptime', '/uptime-robot/response/m780862024-50db2c44c703e5c68d6b1ebb': '(last hour) response', + }, + handlers: { + '/uptime-robot/:topic/:apikey': handler } -} - -export const handlers: Handlers = { - '/uptime-robot/:topic/:apikey': handler -} - -export default badgenServe(handlers) +}) /** * DOCS @@ -48,7 +40,7 @@ export default badgenServe(handlers) * /uptime-robot/:topic/:api_key * :api_key are generated from uptimerobot settings page */ -async function handler ({ topic, apikey }: Args) { +async function handler ({ topic, apikey }: PathArgs) { const endpoint = `https://api.uptimerobot.com/v2/getMonitors` const { monitors } = await got.post(endpoint, { body: { diff --git a/endpoints/vs-marketplace.ts b/api/vs-marketplace.ts similarity index 84% rename from endpoints/vs-marketplace.ts rename to api/vs-marketplace.ts index 0329192..32816a1 100644 --- a/endpoints/vs-marketplace.ts +++ b/api/vs-marketplace.ts @@ -1,30 +1,22 @@ import millify from 'millify' import got from '../libs/got' import { version as v, versionColor } from '../libs/utils' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'Visual Studio Marketplace', examples: { '/vs-marketplace/v/vscodevim.vim': 'version', '/vs-marketplace/i/vscodevim.vim': 'installs', '/vs-marketplace/d/vscodevim.vim': 'downloads', '/vs-marketplace/rating/vscodevim.vim': 'rating', + }, + handlers: { + '/vs-marketplace/:topic/:pkg': handler } -} +}) -export const handlers: Handlers = { - '/vs-marketplace/:topic/:pkg': handler -} - -export default badgenServe(handlers) - -async function handler ({ topic, pkg }: Args) { +async function handler ({ topic, pkg }: PathArgs) { const { results } = await queryVSM(pkg) const extension = results[0].extensions[0] diff --git a/endpoints/xo.ts b/api/xo.ts similarity index 74% rename from endpoints/xo.ts rename to api/xo.ts index 5641b49..8e8f7d3 100644 --- a/endpoints/xo.ts +++ b/api/xo.ts @@ -1,27 +1,19 @@ import got from '../libs/got' -import { - badgenServe, - BadgenServeMeta as Meta, - BadgenServeHandlers as Handlers, - BadgenServeHandlerArgs as Args -} from '../libs/badgen-serve' +import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler' -export const meta: Meta = { +export default createBadgenHandler({ title: 'XO', examples: { '/xo/status/badgen': 'status', '/xo/status/chalk': 'status', '/xo/indent/@tusbar/cache-control': 'indent', '/xo/semi/got': 'semicolons', + }, + handlers: { + '/xo/:topic/:name': handler, + '/xo/:topic/:scope<@.+>/:name': handler } -} - -export const handlers: Handlers = { - '/xo/:topic/:name': handler, - '/xo/:topic/:scope<@.+>/:name': handler -} - -export default badgenServe(handlers) +}) const getIndent = space => { if (space === false) return 'tab' @@ -30,7 +22,7 @@ const getIndent = space => { return `${space} spaces` } -async function handler ({ topic, scope, name }: Args) { +async function handler ({ topic, scope, name }: PathArgs) { const pkg = scope ? `${scope}/${name}` : name const endpoint = `https://cdn.jsdelivr.net/npm/${pkg}/package.json` const data = await got(endpoint).then(res => res.body) diff --git a/components/home-intro.tsx b/components/home-intro.tsx index bd6a6d6..1aa6bb8 100644 --- a/components/home-intro.tsx +++ b/components/home-intro.tsx @@ -48,11 +48,11 @@ export default function HomeIntro ({ isFlat = false }) {

Advanced usage

  • - /runkit + /runkit create arbitrary live badge with RunKit's online IDE.
  • - /https + /https turn an api endpoint into a svg live badge.
diff --git a/endpoints/badge.ts b/endpoints/badge.ts deleted file mode 100644 index f0eba88..0000000 --- a/endpoints/badge.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { badgenServe } from '../libs/badgen-serve' - -export const examples = [ - { - title: 'General', - examples: { - '/badge/Swift/4.2/orange': 'swift version', - '/badge/license/MIT/blue': 'license MIT', - '/badge/chat/on%20gitter/cyan': 'chat on gitter', - '/badge/stars/★★★★☆': 'star rating', - '/badge/become/a%20patron/F96854': 'patron', - '/badge/code%20style/standard/f2a': 'code style: standard' - } - }, { - title: 'With Options', - examples: { - '/badge/icon/github?icon=github': 'use builtin icon', - '/badge/github/github?icon': 'use builtin icon (by subject)', - '/badge/jQuery/powered?icon=https://simpleicons.now.sh/jquery/fff': 'use external icon', - '/badge/icon/github?label=custom%20label': 'custom label', - '/badge/icon/github?label': 'disable label', - '/badge/github/github?icon&label': 'use icon, disable label', - '/badge/platform/ios,macos,tvos?list=|': 'list (custom seprator)' - } - } -] - -export const handlers = { - '/badge/:label/:status': handler, - '/badge/:label/:status/:color': handler -} - -async function handler (args) { - const { label, status, color } = args - return { - subject: label, - status, - color - } -} - -export default badgenServe(handlers) diff --git a/index.ts b/index.ts index f30ca5f..332c273 100644 --- a/index.ts +++ b/index.ts @@ -17,7 +17,7 @@ const sendRedirection = (res: http.ServerResponse, code: number, dest: string) = res.end() } -const badgeNames = fs.readdirSync(path.join(__dirname, 'endpoints')) +const badgeNames = fs.readdirSync(path.join(__dirname, 'api')) .filter(name => /\.[jt]s$/.test(name)) .map(name => name.replace(/\.[jt]s$/, '')) @@ -61,7 +61,7 @@ const server = http.createServer(async (req, res) => { try { if (handlerName) { - const handlerPath = path.join(__dirname, 'endpoints', handlerName) + const handlerPath = path.join(__dirname, 'api', handlerName) const { default: handler } = await import(handlerPath) return handler(req, res, handlerName) } diff --git a/libs/badge-list.ts b/libs/badge-list.ts index bd16fdb..b4b55c3 100644 --- a/libs/badge-list.ts +++ b/libs/badge-list.ts @@ -1,5 +1,5 @@ import path from 'path' -import { examples as staticBadgeExamples } from '../endpoints/badge' +import staticBadges from '../api/badge' const rel = (...args) => path.resolve(__dirname, ...args) @@ -50,20 +50,25 @@ export const liveBadgeList = [ export async function loadBadgeMeta () { const liveBadgeExamples = await Promise.all(liveBadgeList.map(async id => { - const { meta, handlers } = await import(rel('../endpoints', id)) - const { title, examples, help } = meta + const mod = await import(rel('../api', id)) + const { title, examples, handlers } = mod.default.meta return { id, title, examples, routes: Object.keys(handlers), - help } })) + const statics = { + title: staticBadges.meta.title, + examples: staticBadges.meta.examples, + routes: Object.keys(staticBadges.meta.handlers) + } + return { live: liveBadgeExamples, - static: staticBadgeExamples + static: [statics] } } diff --git a/libs/badgen-serve.ts b/libs/badgen-serve.ts deleted file mode 100644 index 20f6656..0000000 --- a/libs/badgen-serve.ts +++ /dev/null @@ -1,165 +0,0 @@ -import url from 'url' -import matchRoute from 'my-way' - -import fetchIcon from './fetch-icon' -import serveBadge from './serve-badge' -import serveDocs from './serve-docs' -import serve404 from './serve-404' -import sentry from './sentry' - -import { BadgenParams } from './types' - -export type BadgenServeMeta = { - title: string - examples: { [url: string]: string } - help?: string -} - -export type BadgenServeHandlerArgs = { [key: string]: string } -export type BadgenServeHandlerResult = Promise -export type BadgenServeHandler = (args: BadgenServeHandlerArgs) => BadgenServeHandlerResult -export type BadgenServeHandlers = { [key: string]: BadgenServeHandler } - -export function badgenServe (handlers: BadgenServeHandlers): Function { - return async function Handler (req, res, name) { - const { pathname = '/', query } = url.parse(req.url, true) - - // Serve favicon - if (pathname === '/favicon.ico' || pathname === null) { - return res.end() - } - - // Serve docs - if (matchRoute(`/${name}`, pathname)) { - return serveDocs(req, res, name) - } - - // Find handler - let matchedArgs - const matchedScheme = Object.keys(handlers).find(scheme => { - matchedArgs = matchRoute(scheme, decodeURI(pathname)) - return matchedArgs !== null - }) - - const defaultLabel = pathname.split('/')[1] - const defaultParams = { - subject: defaultLabel, - status: 'unknown', - color: 'grey' - } - - if (matchedScheme) { - try { - const paramsPromise = handlers[matchedScheme](matchedArgs) - - let iconPromise: Promise = Promise.resolve(undefined) - if (typeof query.icon === 'string') { - if (query.icon.startsWith('https://')) { - iconPromise = fetchIcon(query.icon).catch(e => undefined) - } else { - iconPromise = Promise.resolve(query.icon) - } - } - - const [ icon, params = defaultParams ] = await Promise.all([ - iconPromise, - paramsPromise - ]) - - params.subject = simpleDecode(params.subject) - params.status = simpleDecode(params.status) - - if (icon !== undefined) { - query.icon = icon === '' ? params.subject : icon - } - - if (query.style === undefined) { - const host = req.headers['x-forwarded-host'] || req.headers.host - if (host.startsWith('flat')) { - query.style = 'flat' - } - } - - return serveBadge(req, res, { params, query: query as any }) - } catch (error) { - if (error instanceof BadgenError) { - console.error(`BGE${error.code} "${error.status}" ${req.url}`) - return serveBadge(req, res, { - code: error.code, - sMaxAge: 5, - params: { - subject: defaultLabel, - status: error.status, - color: error.color - } - }) - } - - // Handle timeout for `got` requests - if (error.code === 'ETIMEDOUT') { - console.error(`APIE504 ${req.url}`) - return serveBadge(req, res, { - code: 504, - sMaxAge: 5, - params: { - subject: defaultLabel, - status: 'timeout', - color: 'grey' - } - }) - } - - // Handle requests errors from `got` - if (error.statusCode) { - const errorInfo = `${error.url} ${error.statusMessage}` - console.error(`APIE${error.statusCode} ${req.url} ${errorInfo}`) - return serveBadge(req, res, { - code: 502, - sMaxAge: 5, - params: { - subject: defaultLabel, - status: error.statusCode, - color: 'grey' - } - }) - } - - sentry.configureScope((scope) => { - scope.setTag('path', req.url) - scope.setTag('service', defaultLabel) - }) - sentry.captureException(error) - - // uncatched error - console.error(`UCE ${req.url}`, error.message, error) - return serveBadge(req, res, { - code: 500, - sMaxAge: 5, - params: { - subject: 'badgen', - status: 'error', - color: 'grey' - } - }) - } - } else { - return serve404(req, res) - } - } -} - -export class BadgenError { - public status: string // error badge param: status (required) - public color: string // error badge param: color - public code: number // status code for response - - constructor ({ status, color = 'grey', code = 500 }) { - this.status = status - this.color = color - this.code = code - } -} - -function simpleDecode (str: any): string { - return String(str).replace(/%2F/g, '/') -} diff --git a/libs/create-badgen-handler.ts b/libs/create-badgen-handler.ts index f651ffb..4f0c0d8 100644 --- a/libs/create-badgen-handler.ts +++ b/libs/create-badgen-handler.ts @@ -4,7 +4,7 @@ import urlParse from 'url-parse' import fetchIcon from './fetch-icon' import serveBadge from './serve-badge' -import serveDocs from './serve-docs' +import serveDoc from './serve-doc' import sentry from './sentry' import { BadgenParams } from './types' @@ -12,7 +12,7 @@ import { BadgenParams } from './types' export type PathArgs = NonNullable> export interface BadgeMaker { - (pathArgs: PathArgs) : Promise; + (pathArgs: PathArgs) : Promise; } export interface BadgenServeConfig { @@ -34,8 +34,12 @@ export class BadgenError { } } -export function createBadgenHandler (conf: BadgenServeConfig): http.RequestListener { - return async function badgenHandler (req, res) { +export interface BadgenHandler extends http.RequestListener { + meta: BadgenServeConfig; +} + +export function createBadgenHandler (conf: BadgenServeConfig): BadgenHandler { + async function badgenHandler (req, res) { const url = req.url ?? '/' const { pathname, query } = urlParse(url, true) @@ -158,6 +162,9 @@ export function createBadgenHandler (conf: BadgenServeConfig): http.RequestListe }) } } + + badgenHandler.meta = conf + return badgenHandler } function getBadgeStyle (req: http.IncomingMessage): string | undefined { @@ -184,10 +191,3 @@ function serve404 (req: http.IncomingMessage, res: http.ServerResponse) { serveBadge(req, res, { code: 404, params, query }) } - -function serveDoc (conf: BadgenServeConfig): http.RequestListener { - return (req, res) => { - // TODO: render docs - res.end('docs') - } -} diff --git a/libs/gen-help.ts b/libs/gen-help.ts deleted file mode 100644 index fc7a389..0000000 --- a/libs/gen-help.ts +++ /dev/null @@ -1,71 +0,0 @@ -import path from 'path' -import matchRoute from 'my-way' - -export default function genHelp (id) { - let badgeModule - - try { - badgeModule = require(path.resolve(__dirname, '../endpoints', id)) - } catch (e) { - return '' - } - - if (id === 'badge') { - return genStaticBadgeHelp(badgeModule.examples) - } - - const { meta, handlers } = badgeModule - const { examples, help = ''} = meta - const routes = Object.keys(handlers) - - let md = `# /${id}\n\n${help}\n\n` - - const egCats = routes.reduce((accu, curr) => { - accu[curr] = [] - return accu - }, {}) - - Object.entries(examples).forEach((eg) => { - const scheme = routes.find(r => matchRoute(r, eg[0])) - if (scheme) { - egCats[scheme].push(eg) - } - }) - - md += '## Examples\n\n' - - Object.entries(egCats).forEach(([cat, egs]) => { - // category title (scheme) - const hash = hashify(cat) - md += `\n\n

- ${cat.replace(/ -

\n\n` - - // category example list - // @ts-ignore - md += egs.map(egLine).join('\n') - }) - - return md -} - -// turn `/github/:topic/:owner/:repo/:ref?` -// into `github-topic-commits-last-commit-owner-repo-ref` -function hashify (str: string) { - // return str.replace(/[^\w]/g, '') - return str.split(/[^\w]+/).filter(Boolean).join('-') -} - -function egLine ([url, desc]) { - return `- ![${url}](${url}) [${url}](${url}) ${desc}` -} - -function genStaticBadgeHelp (staticExamples) { - let md = `# Static Badge\n\n` - - md += staticExamples.map(({ title, examples }) => { - return `### ${title}\n\n` + Object.entries(examples).map(egLine).join('\n') - }).join('\n\n') - - return md -} diff --git a/libs/serve-docs.ts b/libs/serve-doc.ts similarity index 58% rename from libs/serve-docs.ts rename to libs/serve-doc.ts index d7f627a..87b964c 100644 --- a/libs/serve-docs.ts +++ b/libs/serve-doc.ts @@ -1,28 +1,69 @@ +import http from 'http' +import matchRoute from 'my-way' import serveMarked from 'serve-marked' import serve404 from '../libs/serve-404' -import genHelp from '../libs/gen-help' +import { BadgenServeConfig } from '../libs/create-badgen-handler' -export default async function (req, res, name) { - const helpMarkdown = genHelp(name) +export default function serveDoc (conf: BadgenServeConfig): http.RequestListener { + return (req, res) => { + const helpMarkdown = generateHelpMarkdown(conf) - if (helpMarkdown) { - res.setHeader('Cache-Control', 'public, max-age=86400, s-maxage=604800, stale-while-revalidate=86400') + if (helpMarkdown) { + res.setHeader('Cache-Control', 'public, max-age=86400, s-maxage=604800, stale-while-revalidate=86400') - return serveMarked(helpMarkdown, { - title: `${name} badge | Badgen`, - inlineCSS, - beforeHeadEnd: '', - beforeBodyEnd: helpFooter, - trackingGA: process.env.TRACKING_GA - })(req, res) + return serveMarked(helpMarkdown, { + title: `${conf.title} badge | Badgen`, + inlineCSS, + beforeHeadEnd: '', + beforeBodyEnd: helpFooter, + trackingGA: process.env.TRACKING_GA + })(req, res) + } + + serve404(req, res) } +} - serve404(req, res) +function generateHelpMarkdown ({ title, help, examples, handlers }: BadgenServeConfig): string { + const mainTitle = `# ${title} Badge` + + const customHelp = help ?? '' + + const exampleTitle = `## Examples` + + const routes = Object.keys(handlers) + const categorizedExamples = Object.entries(examples).reduce((accu, [url, desc]) => { + const scheme = routes.find(route => matchRoute(route, url)) + if (scheme) { + accu[scheme] ? accu[scheme].push({ url, desc }) : accu[scheme] = [{ url, desc }] + } + return accu + }, {}) + + const examplesSection = Object.entries(categorizedExamples).reduce((accu, [header, list]) => { + const hash = hashify(header) + const h4 = `

${header.replace(/

` + const ul = (list as Array).reduce((acc, { url, desc }) => { + return `${acc}\n- ![${url}](${url}) [${url}](${url}) ${desc}` + }, '') + return `${accu}\n\n${h4}\n\n${ul}` + }, '') + + console.log(categorizedExamples, examplesSection) + + return [mainTitle, customHelp, exampleTitle, examplesSection].join('\n\n') +} + +// turn `/github/:topic/:owner/:repo/:ref?` +// into `github-topic-commits-last-commit-owner-repo-ref` +function hashify (str: string) { + // return str.replace(/[^\w]/g, '') + return str.split(/[^\w]+/).filter(Boolean).join('-') } const inlineCSS = ` html, body { scroll-behavior: smooth } - .markdown-body { max-width: 850px } + .markdown-body { max-width: 850px; min-height: calc(100vh - 348px) } .markdown-body h1 { margin-bottom: 42px } li > img { vertical-align: middle; margin: 0.2em 0; font-size: 12px; float: right } li > img + a { font-family: monospace; font-size: 0.9em } diff --git a/now-v1.json b/now-v1.json new file mode 100644 index 0000000..ec3a494 --- /dev/null +++ b/now-v1.json @@ -0,0 +1,34 @@ +{ + "version": 1, + "type": "docker", + "alias": [ + "badgen.net", + "flat.badgen.net" + ], + "files": [ + "package.json", + "package-lock.json", + "server.tsconfig.json", + "tsconfig.json", + "next-env.d.ts", + "next.config.js", + "index.ts", + "tools", + "libs", + "pages", + "static", + "endpoints", + "components" + ], + "env": { + "GH_TOKENS": "@badgen-gh-tokens", + "SENTRY_DSN": "@badgen-sentry-dsn", + "TRACKING_GA": "@badgen-tracking-ga" + }, + "engines": { + "node": "^10" + }, + "github": { + "autoAlias": false + } +} diff --git a/now-v2.json b/now-v2.json deleted file mode 100644 index bffbbd7..0000000 --- a/now-v2.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "version": 2, - "alias": [ - "v2.badgen.net" - ], - "regions": ["sfo", "lhr", "hnd"], - "builds": [ - { "src": "endpoints/*.ts", "use": "@now/node" }, - { "src": "package.json", "use": "@now/static-build" } - ], - "routes": [ - { "src": "/(?[^/]+)/.*", "dest": "/endpoints/$name.ts" }, - { "src": "/(\\w+)\\/?", "dest": "/endpoints/$1.ts" }, - { - "src": "/", - "headers": { - "cache-control": "public, s-maxage=604800, stale-while-revalidate: 86400" - } - } - ], - "env": { - "GH_TOKENS": "@badgen-gh-tokens", - "SENTRY_DSN": "@badgen-sentry-dsn", - "TRACKING_GA": "@badgen-tracking-ga" - }, - "github": { - "autoAlias": false - }, - "files": [ - "package.json", - "package-lock.json", - "server.tsconfig.json", - "tsconfig.json", - "next-env.d.ts", - "next.config.js", - "index.ts", - "tools", - "libs", - "pages", - "static", - "endpoints", - "components" - ] -} diff --git a/now.json b/now.json index ec3a494..edeaf80 100644 --- a/now.json +++ b/now.json @@ -1,33 +1,21 @@ { - "version": 1, - "type": "docker", - "alias": [ - "badgen.net", - "flat.badgen.net" + "version": 2, + "alias": ["badgen.net", "flat.badgen.net"], + "regions": ["sfo", "lhr", "hnd"], + "builds": [ + { "src": "package.json", "use": "@now/static-build" }, + { "src": "api/*.ts", "use": "@now/node" } ], - "files": [ - "package.json", - "package-lock.json", - "server.tsconfig.json", - "tsconfig.json", - "next-env.d.ts", - "next.config.js", - "index.ts", - "tools", - "libs", - "pages", - "static", - "endpoints", - "components" + "routes": [ + { "src": "/docs/(.*)", "status": 301, "headers": { "Location": "/$1" } }, + { "src": "/builder", "dest": "/builder.html" }, + { "src": "/(?[^/]+).*", "dest": "/api/$name.ts" } ], "env": { "GH_TOKENS": "@badgen-gh-tokens", "SENTRY_DSN": "@badgen-sentry-dsn", "TRACKING_GA": "@badgen-tracking-ga" }, - "engines": { - "node": "^10" - }, "github": { "autoAlias": false } diff --git a/package.json b/package.json index 66de6e7..b772566 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,6 @@ "dev:api": "nodemon --config nodemon.json index.ts", "dev:web": "next", "tools": "ts-node -TP server.tsconfig.json tools/gen-examples.ts", - "now-build": "npm run build", "start": "node dist/index.js" }, "standard": { diff --git a/pages/index.tsx b/pages/index.tsx index 5cf4d9a..db11de9 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,7 +1,7 @@ import { useState, useEffect } from 'react' import BadgeExamples from '../components/badge-examples' import BadgenTitle from '../components/badgen-title' -import TopBar from '../components/top-bar' +// import TopBar from '../components/top-bar' import Intro from '../components/home-intro' import Footer from '../components/footer' import examples from '../static/.meta/badges.json' @@ -17,7 +17,6 @@ const Index = () => { }) return <> -
diff --git a/server.tsconfig.json b/server.tsconfig.json index efb736f..49345d1 100644 --- a/server.tsconfig.json +++ b/server.tsconfig.json @@ -5,7 +5,7 @@ "allowJs": true, "skipLibCheck": true, "jsx": "preserve", - "target": "esnext", + "target": "es2018", "module": "commonjs", "moduleResolution": "node", "esModuleInterop": true, @@ -16,7 +16,6 @@ }, "include": [ "index.ts", - "endpoints", - "types" + "api" ] } diff --git a/tsconfig.json b/tsconfig.json index 2196caa..b962f2a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,7 @@ "allowJs": true, "skipLibCheck": true, "jsx": "preserve", - "target": "es2017", + "target": "es2018", "module": "esnext", "moduleResolution": "node", "esModuleInterop": true, @@ -23,11 +23,11 @@ "noEmit": false }, "include": [ + "api", + "libs", "index.ts", - "endpoints", "components", - "pages", - "static" + "pages" ], "exclude": [ "node_modules"