mirror of
https://github.com/Unleash/unleash.git
synced 2025-08-13 13:48:59 +02:00
feat: clean up old OAS and ability to add badges to descriptions (#10038)
## About the changes This removes some old and unused files from an initial test of setting up openapi that's currently not working:  Also, adds the ability of marking endpoints as (note, the endpoints are made up just for illustration purposes): - Enterprise only  - Beta:  - Both:  --------- Co-authored-by: Thomas Heartman <thomas@getunleash.io>
This commit is contained in:
parent
1f4aa0ed34
commit
ff83f934d5
Binary file not shown.
Before Width: | Height: | Size: 665 B |
Binary file not shown.
Before Width: | Height: | Size: 628 B |
@ -1,43 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>ReDoc</title>
|
||||
<!-- needed for adaptive design -->
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
||||
|
||||
<!--
|
||||
ReDoc doesn't change outer page styles
|
||||
-->
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- ### DEFAULT REDOC - NO 'TRY' FEATURE -->
|
||||
<!-- <redoc spec-url='openapi.yaml'></redoc> -->
|
||||
<!-- <script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script> -->
|
||||
<!-- ### REDOC WITH SWAGGER UI'S 'TRY' FEATURE WITHIN REDOC -->
|
||||
<!-- From https://github.com/wll8/redoc-try -->
|
||||
<div id="redoc-container"></div>
|
||||
<script src="//cdn.jsdelivr.net/npm/redoc@2.0.0-rc.28/bundles/redoc.standalone.min.js"> </script>
|
||||
<script src="//cdn.jsdelivr.net/gh/wll8/redoc-try/dist/try.js"></script>
|
||||
<script>
|
||||
var unleashRedoc = {
|
||||
openApi: `openapi.yaml`,
|
||||
onlySwagger: false, // Set to true to switch to Swagger UI output
|
||||
tryText: `Try it out`, // Try button text
|
||||
trySwaggerInApi: false, // Do not display Swagger debugging window under API
|
||||
redocOptions: {hideDownloadButton: true, noAutoAuth: true, sortPropsAlphabetically: true, theme: {spacing: {sectionVertical: '5px',}},},
|
||||
swaggerOptions: {dom_id: `#swagger-ui`},
|
||||
}
|
||||
initTry(unleashRedoc);
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,74 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<title>Swagger UI: OAuth2 Redirect</title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
<script>
|
||||
'use strict';
|
||||
function run () {
|
||||
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||
var sentState = oauth2.state;
|
||||
var redirectUrl = oauth2.redirectUrl;
|
||||
var isValid, qp, arr;
|
||||
|
||||
if (/code|token|error/.test(window.location.hash)) {
|
||||
qp = window.location.hash.substring(1);
|
||||
} else {
|
||||
qp = location.search.substring(1);
|
||||
}
|
||||
|
||||
arr = qp.split("&")
|
||||
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
|
||||
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
||||
function (key, value) {
|
||||
return key === "" ? value : decodeURIComponent(value)
|
||||
}
|
||||
) : {}
|
||||
|
||||
isValid = qp.state === sentState
|
||||
|
||||
if ((
|
||||
oauth2.auth.schema.get("flow") === "accessCode"||
|
||||
oauth2.auth.schema.get("flow") === "authorizationCode"
|
||||
) && !oauth2.auth.code) {
|
||||
if (!isValid) {
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "warning",
|
||||
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
|
||||
});
|
||||
}
|
||||
|
||||
if (qp.code) {
|
||||
delete oauth2.state;
|
||||
oauth2.auth.code = qp.code;
|
||||
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
||||
} else {
|
||||
let oauthErrorMsg
|
||||
if (qp.error) {
|
||||
oauthErrorMsg = "["+qp.error+"]: " +
|
||||
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
||||
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
||||
}
|
||||
|
||||
oauth2.errCb({
|
||||
authId: oauth2.auth.name,
|
||||
source: "auth",
|
||||
level: "error",
|
||||
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
|
||||
});
|
||||
}
|
||||
} else {
|
||||
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
||||
}
|
||||
window.close();
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', function () {
|
||||
run();
|
||||
});
|
||||
</script>
|
1
openapi-static/Beta.svg
Normal file
1
openapi-static/Beta.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="35" height="20" role="img" aria-label="Beta"><title>Beta</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="35" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="0" height="20" fill="#6c65e5"/><rect x="0" width="35" height="20" fill="#6c65e5"/><rect width="35" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="250">Beta</text><text x="175" y="140" transform="scale(.1)" fill="#fff" textLength="250">Beta</text></g></svg>
|
After Width: | Height: | Size: 860 B |
7
openapi-static/Enterprise.svg
Normal file
7
openapi-static/Enterprise.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M11.2608 0.811331C11.6574 0.375976 12.3426 0.375977 12.7392 0.811332L14.0529 2.25322C14.316 2.54202 14.7233 2.65114 15.0955 2.53259L16.9542 1.94073C17.5154 1.76203 18.1087 2.10458 18.2345 2.67993L18.6513 4.58549C18.7347 4.96716 19.0328 5.26527 19.4145 5.34875L21.3201 5.7655C21.8954 5.89133 22.238 6.48465 22.0593 7.04583L21.4674 8.90447C21.3489 9.27675 21.458 9.68397 21.7468 9.9471L23.1887 11.2608C23.624 11.6574 23.624 12.3426 23.1887 12.7392L21.7468 14.0529C21.458 14.316 21.3489 14.7233 21.4674 15.0955L22.0593 16.9542C22.238 17.5154 21.8954 18.1087 21.3201 18.2345L19.4145 18.6513C19.0328 18.7347 18.7347 19.0328 18.6513 19.4145L18.2345 21.3201C18.1087 21.8954 17.5154 22.238 16.9542 22.0593L15.0955 21.4674C14.7233 21.3489 14.316 21.458 14.0529 21.7468L12.7392 23.1887C12.3426 23.624 11.6574 23.624 11.2608 23.1887L9.9471 21.7468C9.68397 21.458 9.27675 21.3489 8.90447 21.4674L7.04583 22.0593C6.48465 22.238 5.89133 21.8954 5.7655 21.3201L5.34875 19.4145C5.26527 19.0328 4.96716 18.7347 4.58549 18.6513L2.67993 18.2345C2.10458 18.1087 1.76203 17.5154 1.94073 16.9542L2.53259 15.0955C2.65114 14.7233 2.54202 14.316 2.25322 14.0529L0.811331 12.7392C0.375976 12.3426 0.375977 11.6574 0.811332 11.2608L2.25322 9.9471C2.54202 9.68397 2.65114 9.27675 2.53259 8.90447L1.94073 7.04583C1.76203 6.48465 2.10458 5.89133 2.67993 5.7655L4.58549 5.34875C4.96716 5.26527 5.26527 4.96716 5.34875 4.58549L5.7655 2.67993C5.89133 2.10458 6.48465 1.76203 7.04583 1.94073L8.90447 2.53259C9.27675 2.65114 9.68397 2.54202 9.9471 2.25322L11.2608 0.811331Z"
|
||||
fill="#1A4049" />
|
||||
<path d="M10.4351 7.3042H7.30469V16.6955H16.696V7.3042H13.5656V13.5651H10.4351V7.3042Z" fill="white" />
|
||||
<path d="M13.5664 13.5649H16.6968V16.6954H13.5664V13.5649Z" fill="#817AFE" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
@ -100,10 +100,6 @@ export default async function getApp(
|
||||
app.use(baseUriPath, favicon(path.join(publicFolder, 'favicon.ico')));
|
||||
app.use(baseUriPath, express.static(publicFolder, { index: false }));
|
||||
|
||||
if (config.enableOAS) {
|
||||
app.use(`${baseUriPath}/oas`, express.static('docs/api/oas'));
|
||||
}
|
||||
|
||||
if (config.enableOAS && services.openApiService) {
|
||||
services.openApiService.useDocs(app);
|
||||
}
|
||||
|
@ -14,4 +14,6 @@ export interface ApiOperation<Tag = OpenApiTag | DeprecatedOpenAPITag>
|
||||
extends Omit<OpenAPIV3.OperationObject, 'tags'> {
|
||||
operationId: string;
|
||||
tags: [Tag];
|
||||
beta?: boolean;
|
||||
enterpriseOnly?: boolean;
|
||||
}
|
||||
|
@ -1,5 +1,10 @@
|
||||
import openapi, { type IExpressOpenApi } from '@wesleytodd/openapi';
|
||||
import type { Express, RequestHandler, Response } from 'express';
|
||||
import {
|
||||
type Express,
|
||||
type RequestHandler,
|
||||
type Response,
|
||||
static as expressStatic,
|
||||
} from 'express';
|
||||
import type { IUnleashConfig } from '../types/option.js';
|
||||
import {
|
||||
createOpenApiSchema,
|
||||
@ -38,12 +43,40 @@ export class OpenApiService {
|
||||
}
|
||||
|
||||
validPath(op: ApiOperation): RequestHandler {
|
||||
return this.api.validPath(op);
|
||||
const { beta, enterpriseOnly, ...rest } = op;
|
||||
|
||||
const betaBadge = beta
|
||||
? `}/Beta.svg) This is a beta endpoint and it may change or be removed in the future.
|
||||
|
||||
`
|
||||
: '';
|
||||
const enterpriseBadge = enterpriseOnly
|
||||
? `}/Enterprise.svg) **Enterprise feature**
|
||||
|
||||
`
|
||||
: '';
|
||||
return this.api.validPath({
|
||||
...rest,
|
||||
description:
|
||||
`${enterpriseBadge}${betaBadge}${op.description}`.replaceAll(
|
||||
/\n\s*/g,
|
||||
'\n\n',
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
useDocs(app: Express): void {
|
||||
app.use(this.api);
|
||||
app.use(this.docsPath(), this.api.swaggerui());
|
||||
app.use(
|
||||
this.docsStaticsPath(),
|
||||
expressStatic('openapi-static', { index: false }),
|
||||
);
|
||||
}
|
||||
|
||||
docsStaticsPath(): string {
|
||||
const { baseUriPath = '' } = this.config.server ?? {};
|
||||
return `${baseUriPath}/docs/static`;
|
||||
}
|
||||
|
||||
docsPath(): string {
|
||||
|
Loading…
Reference in New Issue
Block a user