From 0117a6b47eeb782e33acb4b271714e7db19c534d Mon Sep 17 00:00:00 2001 From: Mauricio Martinez Date: Thu, 17 Aug 2023 12:09:20 -0600 Subject: [PATCH 01/10] Adding requestInterceptor Signed-off-by: Mauricio Martinez --- .changeset/purple-chefs-wait.md | 5 +++ .github/vale/Vocab/Backstage/accept.txt | 1 + plugins/api-docs/README.md | 39 +++++++++++++++++++ plugins/api-docs/api-report.md | 2 +- .../OpenApiDefinition.test.tsx | 8 +++- .../OpenApiDefinition.tsx | 14 ++++++- .../OpenApiDefinitionWidget.tsx | 2 + .../OpenApiDefinitionWidget/index.ts | 4 ++ 8 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 .changeset/purple-chefs-wait.md diff --git a/.changeset/purple-chefs-wait.md b/.changeset/purple-chefs-wait.md new file mode 100644 index 0000000000..d8489e0275 --- /dev/null +++ b/.changeset/purple-chefs-wait.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': minor +--- + +Adding requestInterceptor option to `api-docs` and pass it to SwaggerUI. This will enable to configure a proxy or headers to be sent to all the request made through the `Try it out` button on SwaggerUI. diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index c61c6bdf46..1706556ce8 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -296,6 +296,7 @@ readonly rebase Recharts Redash +requestInterceptor replicasets repo Repo diff --git a/plugins/api-docs/README.md b/plugins/api-docs/README.md index 27e19b218d..f74fc19e92 100644 --- a/plugins/api-docs/README.md +++ b/plugins/api-docs/README.md @@ -222,3 +222,42 @@ security: ## Links - [The Backstage homepage](https://backstage.io) + +### Adding requestInterceptor to Swagger UI + +To configure a [requestInterceptor for Swagger UI](https://github.com/swagger-api/swagger-ui/tree/master/flavors/swagger-ui-react#requestinterceptor-proptypesfunc) you'll need to add the following to your `api.tsx`: + +```tsx +... +import { OpenApiDefinitionWidget, apiDocsConfigRef, defaultDefinitionWidgets } from '@backstage/plugin-api-docs'; +import { ApiEntity } from '@backstage/catalog-model'; + +export const apis: AnyApiFactory[] = [ +... +createApiFactory({ + api: apiDocsConfigRef, + deps: {}, + factory: () => { + // Overriding openapi definition widget to add cors-anywhere proxy + const requestInterceptor = (req: any) => { + // Adding cors-anywhere proxy to the request url + console.log(req); + req.url = "https://cors-anywhere.herokuapp.com/" + req.url; + return req; + }; + const definitionWidgets = defaultDefinitionWidgets(); + definitionWidgets[definitionWidgets.findIndex(obj => obj.type === 'openapi')] = { + type: 'openapi', + title: 'OpenAPI', + rawLanguage: 'yaml', + component: (definition) => , + }; + + return { + getApiDefinitionWidget: (apiEntity: ApiEntity) => { + return definitionWidgets.find(d => d.type === apiEntity.spec.type); + }, + }; + }, + }) +``` diff --git a/plugins/api-docs/api-report.md b/plugins/api-docs/api-report.md index a9b21664c3..783e2bdecb 100644 --- a/plugins/api-docs/api-report.md +++ b/plugins/api-docs/api-report.md @@ -54,7 +54,7 @@ const apiDocsPlugin: BackstagePlugin< { registerApi: ExternalRouteRef; }, - {} + ApiDocsInputPluginOptions >; export { apiDocsPlugin }; export { apiDocsPlugin as plugin }; diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.test.tsx b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.test.tsx index 735fba86f7..adbd069908 100644 --- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.test.tsx +++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.test.tsx @@ -38,8 +38,14 @@ paths: "200": description: Success `; + + const requestInterceptor = (req: any) => req; + const { getByText } = await renderInTestApp( - , + , ); // swagger-ui loads the documentation asynchronously diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx index 5d5988399a..624f99e4a1 100644 --- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx +++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx @@ -18,6 +18,7 @@ import { makeStyles } from '@material-ui/core/styles'; import React, { useEffect, useState } from 'react'; import SwaggerUI from 'swagger-ui-react'; import 'swagger-ui-react/swagger-ui.css'; +import { Request } from './'; const useStyles = makeStyles(theme => ({ root: { @@ -136,9 +137,13 @@ const useStyles = makeStyles(theme => ({ export type OpenApiDefinitionProps = { definition: string; + requestInterceptor?: (req: Request) => Request | Promise; }; -export const OpenApiDefinition = ({ definition }: OpenApiDefinitionProps) => { +export const OpenApiDefinition = ({ + definition, + requestInterceptor, +}: OpenApiDefinitionProps) => { const classes = useStyles(); // Due to a bug in the swagger-ui-react component, the component needs @@ -152,7 +157,12 @@ export const OpenApiDefinition = ({ definition }: OpenApiDefinitionProps) => { return (
- +
); }; diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx index 424a52136b..809934ee11 100644 --- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx +++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx @@ -16,6 +16,7 @@ import { Progress } from '@backstage/core-components'; import React, { Suspense } from 'react'; +import { Request } from './'; // The swagger-ui component and related CSS has a significant size, only load it // if the element is actually used. @@ -28,6 +29,7 @@ const LazyOpenApiDefinition = React.lazy(() => /** @public */ export type OpenApiDefinitionWidgetProps = { definition: string; + requestInterceptor?: (req: Request) => Request | Promise; }; /** @public */ diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts b/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts index e317d42a59..f23f560347 100644 --- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts +++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts @@ -16,3 +16,7 @@ export { OpenApiDefinitionWidget } from './OpenApiDefinitionWidget'; export type { OpenApiDefinitionWidgetProps } from './OpenApiDefinitionWidget'; + +export interface Request { + [k: string]: any; +} From d4217138351f4e3fbb89089def6467c230e99f82 Mon Sep 17 00:00:00 2001 From: Mauricio Martinez Date: Fri, 18 Aug 2023 11:01:39 -0600 Subject: [PATCH 02/10] Building api docs Signed-off-by: Mauricio Martinez --- plugins/api-docs/api-report.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/plugins/api-docs/api-report.md b/plugins/api-docs/api-report.md index 783e2bdecb..a04b3350f1 100644 --- a/plugins/api-docs/api-report.md +++ b/plugins/api-docs/api-report.md @@ -54,7 +54,7 @@ const apiDocsPlugin: BackstagePlugin< { registerApi: ExternalRouteRef; }, - ApiDocsInputPluginOptions + {} >; export { apiDocsPlugin }; export { apiDocsPlugin as plugin }; @@ -163,6 +163,7 @@ export const OpenApiDefinitionWidget: ( // @public (undocumented) export type OpenApiDefinitionWidgetProps = { definition: string; + requestInterceptor?: (req: Request_2) => Request_2 | Promise; }; // @public (undocumented) @@ -187,6 +188,15 @@ export const ProvidingComponentsCard: (props: { variant?: InfoCardVariants; }) => JSX.Element; +// Warning: (ae-missing-release-tag) "Request" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +interface Request_2 { + // (undocumented) + [k: string]: any; +} +export { Request_2 as Request }; + // @public (undocumented) export const TrpcApiDefinitionWidget: ( props: TrpcApiDefinitionWidgetProps, From 915b6ba4affeb153211cb1014ed4997e060ed6d3 Mon Sep 17 00:00:00 2001 From: Mauricio Martinez Date: Mon, 21 Aug 2023 09:35:03 -0600 Subject: [PATCH 03/10] Building api docs Signed-off-by: Mauricio Martinez --- plugins/api-docs/api-report.md | 2 -- .../api-docs/src/components/OpenApiDefinitionWidget/index.ts | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/api-docs/api-report.md b/plugins/api-docs/api-report.md index a04b3350f1..fb9fe48621 100644 --- a/plugins/api-docs/api-report.md +++ b/plugins/api-docs/api-report.md @@ -188,8 +188,6 @@ export const ProvidingComponentsCard: (props: { variant?: InfoCardVariants; }) => JSX.Element; -// Warning: (ae-missing-release-tag) "Request" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) interface Request_2 { // (undocumented) diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts b/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts index f23f560347..631a96c047 100644 --- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts +++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts @@ -17,6 +17,7 @@ export { OpenApiDefinitionWidget } from './OpenApiDefinitionWidget'; export type { OpenApiDefinitionWidgetProps } from './OpenApiDefinitionWidget'; +/** @public */ export interface Request { [k: string]: any; } From d457253de9139f866cfacebd0bb11a56f881f0af Mon Sep 17 00:00:00 2001 From: Mauricio Martinez Date: Mon, 4 Sep 2023 10:57:23 -0600 Subject: [PATCH 04/10] Comments Signed-off-by: Mauricio Martinez --- plugins/api-docs/README.md | 15 +++++++++------ plugins/api-docs/api-report.md | 9 +-------- .../OpenApiDefinitionWidget/OpenApiDefinition.tsx | 3 +-- .../OpenApiDefinitionWidget.tsx | 3 +-- .../components/OpenApiDefinitionWidget/index.ts | 5 ----- 5 files changed, 12 insertions(+), 23 deletions(-) diff --git a/plugins/api-docs/README.md b/plugins/api-docs/README.md index f74fc19e92..30c09ec483 100644 --- a/plugins/api-docs/README.md +++ b/plugins/api-docs/README.md @@ -246,12 +246,15 @@ createApiFactory({ return req; }; const definitionWidgets = defaultDefinitionWidgets(); - definitionWidgets[definitionWidgets.findIndex(obj => obj.type === 'openapi')] = { - type: 'openapi', - title: 'OpenAPI', - rawLanguage: 'yaml', - component: (definition) => , - }; + definitionWidgets.map(obj => { + if (obj.type === 'openapi') { + return { + ...obj, + component: (definition) => , + } + } + return obj; + }); return { getApiDefinitionWidget: (apiEntity: ApiEntity) => { diff --git a/plugins/api-docs/api-report.md b/plugins/api-docs/api-report.md index fb9fe48621..84e6344325 100644 --- a/plugins/api-docs/api-report.md +++ b/plugins/api-docs/api-report.md @@ -163,7 +163,7 @@ export const OpenApiDefinitionWidget: ( // @public (undocumented) export type OpenApiDefinitionWidgetProps = { definition: string; - requestInterceptor?: (req: Request_2) => Request_2 | Promise; + requestInterceptor?: (req: any) => any | Promise; }; // @public (undocumented) @@ -188,13 +188,6 @@ export const ProvidingComponentsCard: (props: { variant?: InfoCardVariants; }) => JSX.Element; -// @public (undocumented) -interface Request_2 { - // (undocumented) - [k: string]: any; -} -export { Request_2 as Request }; - // @public (undocumented) export const TrpcApiDefinitionWidget: ( props: TrpcApiDefinitionWidgetProps, diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx index 624f99e4a1..a2ebbbc7e3 100644 --- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx +++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinition.tsx @@ -18,7 +18,6 @@ import { makeStyles } from '@material-ui/core/styles'; import React, { useEffect, useState } from 'react'; import SwaggerUI from 'swagger-ui-react'; import 'swagger-ui-react/swagger-ui.css'; -import { Request } from './'; const useStyles = makeStyles(theme => ({ root: { @@ -137,7 +136,7 @@ const useStyles = makeStyles(theme => ({ export type OpenApiDefinitionProps = { definition: string; - requestInterceptor?: (req: Request) => Request | Promise; + requestInterceptor?: (req: any) => any | Promise; }; export const OpenApiDefinition = ({ diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx index 809934ee11..152f1fd089 100644 --- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx +++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/OpenApiDefinitionWidget.tsx @@ -16,7 +16,6 @@ import { Progress } from '@backstage/core-components'; import React, { Suspense } from 'react'; -import { Request } from './'; // The swagger-ui component and related CSS has a significant size, only load it // if the element is actually used. @@ -29,7 +28,7 @@ const LazyOpenApiDefinition = React.lazy(() => /** @public */ export type OpenApiDefinitionWidgetProps = { definition: string; - requestInterceptor?: (req: Request) => Request | Promise; + requestInterceptor?: (req: any) => any | Promise; }; /** @public */ diff --git a/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts b/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts index 631a96c047..e317d42a59 100644 --- a/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts +++ b/plugins/api-docs/src/components/OpenApiDefinitionWidget/index.ts @@ -16,8 +16,3 @@ export { OpenApiDefinitionWidget } from './OpenApiDefinitionWidget'; export type { OpenApiDefinitionWidgetProps } from './OpenApiDefinitionWidget'; - -/** @public */ -export interface Request { - [k: string]: any; -} From aad197a601e9ba981452d86068af5cf944ec9c76 Mon Sep 17 00:00:00 2001 From: Mauricio Martinez Date: Mon, 11 Sep 2023 17:42:51 -0600 Subject: [PATCH 05/10] Update definitionWidgets to map instead of forEach loop Signed-off-by: Mauricio Martinez --- plugins/api-docs/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/api-docs/README.md b/plugins/api-docs/README.md index 30c09ec483..1f8a9b8db3 100644 --- a/plugins/api-docs/README.md +++ b/plugins/api-docs/README.md @@ -245,8 +245,7 @@ createApiFactory({ req.url = "https://cors-anywhere.herokuapp.com/" + req.url; return req; }; - const definitionWidgets = defaultDefinitionWidgets(); - definitionWidgets.map(obj => { + const definitionWidgets = defaultDefinitionWidgets().map(obj => { if (obj.type === 'openapi') { return { ...obj, From 05880e8c0a3c9c5b7315d306ab357e428bfaab4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mauricio=20Alejandro=20Mart=C3=ADnez=20Pacheco?= Date: Tue, 12 Sep 2023 12:31:03 -0600 Subject: [PATCH 06/10] Update .changeset/purple-chefs-wait.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patrik Oldsberg Signed-off-by: Mauricio Alejandro Martínez Pacheco --- .changeset/purple-chefs-wait.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/purple-chefs-wait.md b/.changeset/purple-chefs-wait.md index d8489e0275..36cbe99095 100644 --- a/.changeset/purple-chefs-wait.md +++ b/.changeset/purple-chefs-wait.md @@ -2,4 +2,4 @@ '@backstage/plugin-api-docs': minor --- -Adding requestInterceptor option to `api-docs` and pass it to SwaggerUI. This will enable to configure a proxy or headers to be sent to all the request made through the `Try it out` button on SwaggerUI. +Adding `requestInterceptor` option to `api-docs` and pass it to SwaggerUI. This will enable to configure a proxy or headers to be sent to all the request made through the `Try it out` button on SwaggerUI. From 902ea9cb266c1ce89a92e3771b8e8a435af1807b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mauricio=20Alejandro=20Mart=C3=ADnez=20Pacheco?= Date: Tue, 12 Sep 2023 14:09:15 -0600 Subject: [PATCH 07/10] Update .github/vale/Vocab/Backstage/accept.txt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patrik Oldsberg Signed-off-by: Mauricio Alejandro Martínez Pacheco --- .github/vale/Vocab/Backstage/accept.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index 1706556ce8..c61c6bdf46 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -296,7 +296,6 @@ readonly rebase Recharts Redash -requestInterceptor replicasets repo Repo From 03c9e4c5704d0d64794d117e2fb362fa90d3b351 Mon Sep 17 00:00:00 2001 From: Mauricio Martinez Date: Tue, 12 Sep 2023 14:17:06 -0600 Subject: [PATCH 08/10] Remove cors-anywhere example in favor of simple header change Signed-off-by: Mauricio Martinez --- plugins/api-docs/README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/api-docs/README.md b/plugins/api-docs/README.md index 1f8a9b8db3..ceddab540a 100644 --- a/plugins/api-docs/README.md +++ b/plugins/api-docs/README.md @@ -238,11 +238,9 @@ createApiFactory({ api: apiDocsConfigRef, deps: {}, factory: () => { - // Overriding openapi definition widget to add cors-anywhere proxy + // Overriding openapi definition widget to add header const requestInterceptor = (req: any) => { - // Adding cors-anywhere proxy to the request url - console.log(req); - req.url = "https://cors-anywhere.herokuapp.com/" + req.url; + req.headers.append('myheader', 'wombats'); return req; }; const definitionWidgets = defaultDefinitionWidgets().map(obj => { From e3993a0f3ba96b9ec1f12fcbbd98aff12d52c100 Mon Sep 17 00:00:00 2001 From: Mauricio Martinez Date: Tue, 12 Sep 2023 14:19:22 -0600 Subject: [PATCH 09/10] Adding ticks to requestInterceptor on docs to avoid spell change Signed-off-by: Mauricio Martinez --- plugins/api-docs/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/api-docs/README.md b/plugins/api-docs/README.md index ceddab540a..792a7fb0b7 100644 --- a/plugins/api-docs/README.md +++ b/plugins/api-docs/README.md @@ -223,9 +223,9 @@ security: - [The Backstage homepage](https://backstage.io) -### Adding requestInterceptor to Swagger UI +### Adding `requestInterceptor` to Swagger UI -To configure a [requestInterceptor for Swagger UI](https://github.com/swagger-api/swagger-ui/tree/master/flavors/swagger-ui-react#requestinterceptor-proptypesfunc) you'll need to add the following to your `api.tsx`: +To configure a [`requestInterceptor` for Swagger UI](https://github.com/swagger-api/swagger-ui/tree/master/flavors/swagger-ui-react#requestinterceptor-proptypesfunc) you'll need to add the following to your `api.tsx`: ```tsx ... From 3bbb80be45c9f1e58de16942ea3b212be3648d94 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 26 Sep 2023 13:26:44 +0200 Subject: [PATCH 10/10] Apply suggestions from code review Signed-off-by: Patrik Oldsberg --- .changeset/purple-chefs-wait.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/purple-chefs-wait.md b/.changeset/purple-chefs-wait.md index 36cbe99095..9a8b1f9799 100644 --- a/.changeset/purple-chefs-wait.md +++ b/.changeset/purple-chefs-wait.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-api-docs': minor +'@backstage/plugin-api-docs': patch --- Adding `requestInterceptor` option to `api-docs` and pass it to SwaggerUI. This will enable to configure a proxy or headers to be sent to all the request made through the `Try it out` button on SwaggerUI.