const usage = `\
USAGE:
GET /docs - HTML api version index
GET /docs/:api_version - HTML docs from api version
GET /tags - JSON {api_version: commit_id} map
GET /tags/:api_version - JSON "commit_id" sha hash
POST /load - 204 force reload
`;
const { fromJS, Seq, OrderedMap } = require("immutable");
const sh = require("shelljs");
const app = require("@runkit/runkit/express-endpoint/1.0.0")(exports);
const tagify = () => {
const revs = sh
.exec(
'\
rm -rf openapi \
&& git clone https://github.com/stripe/openapi.git \
&& cd openapi \
&& git rev-list --all \
| xargs -I% git --no-pager grep -F -e \' "version": "\' % -- openapi/spec3.json'
)
.split("\n");
const tags = fromJS(revs)
.butLast()
.map(x => ({
sha: x.substr(0, 40),
version: x.substr(76, 10)
}))
.reduce(
(acc, { sha, version }) =>
acc.has(version) ? acc : acc.set(version, sha),
OrderedMap()
);
return tags;
};
const attest = (obj, prop, func, reset = false) => {
if (reset || !(prop in obj)) obj[prop] = func();
return obj;
};
const tags = (req, reload = false) => {
attest(req.app.locals, "tags", tagify, reload);
return reload ? undefined : req.app.locals["tags"];
};
app.set("json spaces", 2);
app.post("/load", async (req, res) => {
tags(req, true);
res.status(204).end();
});
app.get("/tags/:version", async (req, res) => {
const sha = tags(req).get(req.params.version);
if (!sha) res.status(404).end();
else res.json(sha);
});
app.get("/tags", async (req, res) => {
res.json(tags(req));
});
app.get("/docs/:version", async (req, res) => {
const version = req.params.version;
const sha = tags(req).get(version);
if (!sha) res.status(404).end();
else res.send(docpage({ sha, version }));
});
app.get("/docs", async (req, res) => {
const seq = tags(req).toKeyedSeq();
const src = seq
.map(
(sha, version) =>
`- ${version}: ${sha}` +
` <a href="https://github.com/stripe/openapi/tree/${sha}/openapi">[git]</a>` +
` <a href="/docs/${version}">[docs]</a>`
)
.join("\n");
res.send(txtpage(src));
});
app.get("/", async (req, res) => {
res.send(txtpage(usage));
});
const docpage = ({ sha, version }) => `
<!doctype html>
<html lang="en">
<head>
<title>Stripe API – version ${version}</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
<script src="https://unpkg.com/rapidoc@7.1.0/dist/rapidoc-min.js"></script>
<style> rapi-doc { width:100%; } </style>
</head>
<body>
<rapi-doc spec-url="https://raw.githubusercontent.com/stripe/openapi/${sha}/openapi/spec3.json"
theme="dark"
primary-color="#444">
<img slot="logo" src="https://stripe.com/img/about/logos/logos/white.png"
style="width: 5em; margin-left: 1em"/>
</rapi-doc>
</body>
</html>`;
const txtpage = src => {
return `
<!doctype html>
<html lang="en">
<head>
<title>Stripe API – Versions</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes"/>
<style>
pre.index { font: 1.2em/1.62 monospace; margin-left: 3.2em; }
a { text-decoration: none; }
</style>
</head>
<body>
<pre>
_ _
___| |_ _ __(_)_ __ ___
/ __| __| '__| | '_ \\ / _ \\
\\__ \\ |_| | | | |_) | __/
|___/\\__|_| |_| .__/ \\___|
|_|
</pre>
<pre class="index">${src}</pre>
<pre>
___
source code: <a href="https://runkit.com/lxmedina/5d387d5352397a001f4e3bc1"
target="_blank">https://runkit.com/lxmedina/5d387d5352397a001f4e3bc1</a>
</pre>
</body>
</html>`;
};
process.env.RUNKIT_ENDPOINT_URL;