This commit is contained in:
Tim Hansen
2020-09-11 13:42:06 -06:00
47 changed files with 305 additions and 239 deletions
+4 -2
View File
@@ -93,9 +93,11 @@ jobs:
if: ${{ steps.yarn-lock.outcome == 'success' }}
run: yarn lerna -- run test --since origin/master -- --coverage
- name: test all packages
- name: test all packages (and upload coverage)
if: ${{ steps.yarn-lock.outcome == 'failure' }}
run: yarn lerna -- run test -- --coverage
run: |
yarn lerna -- run test -- --coverage
bash <(curl -s https://codecov.io/bash)
- name: verify plugin template
run: yarn lerna -- run diff -- --check
+4 -2
View File
@@ -59,8 +59,10 @@ jobs:
- name: verify type dependencies
run: yarn lint:type-deps
- name: test
run: yarn lerna -- run test -- --coverage
- name: test (and upload coverage)
run: |
yarn lerna -- run test -- --coverage
bash <(curl -s https://codecov.io/bash)
# Publishes current version of packages that are not already present in the registry
- name: publish
+1 -29
View File
@@ -62,35 +62,7 @@ Have you started using Backstage? Adding your company to [ADOPTERS](ADOPTERS.md)
So...feel ready to jump in? Let's do this. 👏🏻💯
To run a Backstage app, you will need to have the following installed:
- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
- [NodeJS](https://nodejs.org/en/download/) - Active LTS Release, currently v12
- [yarn](https://classic.yarnpkg.com/en/docs/install)
After cloning this repo, open a terminal window and start the example app using the following commands from the project root:
```bash
yarn install # Install dependencies
yarn start # Start dev server, use --check to enable linting and type-checks
```
The final `yarn start` command should open a local instance of Backstage in your browser, otherwise open one of the URLs printed in the terminal.
Depending on the work you're doing, you often also want to run the example backend. Start the backend in a separate terminal session using the following:
```bash
cd packages/backend
yarn start
yarn lerna run mock-data # Populate the backend with mock data
```
And that's it! You are good to go 👍
If you need help, just jump into our [Discord chatroom](https://discord.gg/MUpMjP2).
Start by reading our [Getting Started](https://backstage.io/docs/getting-started/) page. If you need help, just jump into our [Discord chatroom](https://discord.gg/MUpMjP2).
# Coding Guidelines
+2 -27
View File
@@ -6,6 +6,7 @@
![](https://github.com/spotify/backstage/workflows/Frontend%20CI/badge.svg)
[![Discord](https://img.shields.io/discord/687207715902193673)](https://discord.gg/EBHEGzX)
![Code style](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)
[![Codecov](https://img.shields.io/codecov/c/github/spotify/backstage)](https://codecov.io/gh/spotify/backstage)
[![](https://img.shields.io/npm/v/@backstage/core?label=Version)](https://github.com/spotify/backstage/releases)
## What is Backstage?
@@ -31,33 +32,7 @@ A detailed project roadmap, including already delivered milestones, is available
## Getting Started
There are two different ways to get started with Backstage, either by creating a standalone app, or by cloning this repo. Which method you use depends on what you're planning to do.
Creating a standalone instance makes it simpler to customize the application for your needs whilst staying up to date with the project. You will also depend on `@backstage` packages from NPM, making the project much smaller. This is the recommended approach if you want to kick the tyres of Backstage or setup your own instance.
On the other hand, if you want to contribute plugins or to the project in general, it's easier to fork and clone this project. That will let you stay up to date with the latest changes, and gives you an easier path to make Pull Requests towards this repo.
### Creating a Standalone App
Backstage provides the `@backstage/create-app` package to scaffold standalone instances of Backstage. You will need to have
[NodeJS](https://nodejs.org/en/download/) Active LTS Release installed
(currently v12), and [yarn](https://classic.yarnpkg.com/en/docs/install). You will also need to have [Docker](https://docs.docker.com/engine/install/) installed to use some features like Software Templates and TechDocs.
Using `npx` you can then run the following to create an app in a chosen subdirectory of your current working directory:
```bash
npx @backstage/create-app
```
You will be taken through a wizard to create your app, and the output should look something like this. You can read more about this process [here](https://backstage.io/docs/getting-started/create-an-app)
### Contributing to Backstage
You can read more in our [CONTRIBUTING.md](./CONTRIBUTING.md#get-started) guide, which can help you get setup with a Backstage development environment.
### Next steps
Take a look at the [Getting Started](https://backstage.io/docs/getting-started/index) guide to learn how to set up Backstage, and how to develop on the platform.
Check out [the documentation](https://backstage.io/docs/getting-started) on how to start using Backstage.
## Documentation
+2 -2
View File
@@ -12,8 +12,8 @@ to? Edit this file
## Technology
- [What static site generator is TechDocs using?](./#what-static-site-generator-is-techdocs-using)
- [What is the mkdocs-techdocs-core plugin?](./#what-is-the-mkdocs-techdocs-core-plugin)
- [What static site generator is TechDocs using?](#what-static-site-generator-is-techdocs-using)
- [What is the mkdocs-techdocs-core plugin?](#what-is-the-mkdocs-techdocs-core-plugin)
#### What static site generator is TechDocs using?
+6 -6
View File
@@ -26,12 +26,12 @@ Spotifys developer experience offering with 2,400+ documentation sites and
## Project roadmap
| Version | Description |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| [TechDocs V.0 ✅][v0] | Read docs in Backstage - Enable anyone to get a reader experience working in Backstage. [See V.0 Use Cases.](./#techdocs-v0) |
| [TechDocs V.1 🚧][v1] | TechDocs end to end (alpha) - Alpha of TechDocs that you can use end to end - and contribute to. [See V.1 Use Cases.](./#techdocs-v1) |
| [TechDocs V.2 🔮⌛][v2] | Platform stability and compatibility improvements. [See V.2 Use Cases.](./#techdocs-v2) |
| TechDocs V.3 🔮⌛ | Widget Architecture - TechDocs widget architecture available, so the community can create their own customized features. |
| Version | Description |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| [TechDocs V.0 ✅][v0] | Read docs in Backstage - Enable anyone to get a reader experience working in Backstage. [See V.0 Use Cases.](#techdocs-v0) |
| [TechDocs V.1 ][v1] | TechDocs end to end (alpha) - Alpha of TechDocs that you can use end to end - and contribute to. [See V.1 Use Cases.](#techdocs-v1) |
| [TechDocs V.2 🔮⌛][v2] | Platform stability and compatibility improvements. [See V.2 Use Cases.](#techdocs-v2) |
| TechDocs V.3 🔮⌛ | Widget Architecture - TechDocs widget architecture available, so the community can create their own customized features. |
[v0]: https://github.com/spotify/backstage/milestone/15
[v1]: https://github.com/spotify/backstage/milestone/16
+38 -72
View File
@@ -1,84 +1,50 @@
---
id: index
title: Running Backstage Locally
title: Getting Started
---
First make sure you are using NodeJS with an Active LTS Release, currently v12.
This is made easy with a version manager such as nvm which allows for version
switching.
There are two different ways to get started with Backstage, either by creating a
standalone app, or by cloning this repo. Which method you use depends on what
you're planning to do.
Creating a standalone instance makes it simpler to customize the application for
your needs whilst staying up to date with the project. You will also depend on
`@backstage` packages from NPM, making the project much smaller. This is the
recommended approach if you want to kick the tyres of Backstage or setup your
own instance.
On the other hand, if you want to contribute plugins or to the project in
general, it's easier to fork and clone this project. That will let you stay up
to date with the latest changes, and gives you an easier path to make Pull
Requests towards this repo.
### Creating a Standalone App
Backstage provides the `@backstage/create-app` package to scaffold standalone
instances of Backstage. You will need to have
[NodeJS](https://nodejs.org/en/download/) Active LTS Release installed
(currently v12), and [yarn](https://classic.yarnpkg.com/en/docs/install). You
will also need to have [Docker](https://docs.docker.com/engine/install/)
installed to use some features like Software Templates and TechDocs.
Using `npx` you can then run the following to create an app in a chosen
subdirectory of your current working directory:
```bash
# Checking your version
node --version
> v14.7.0
# Adding a second node version
nvm install 12
> Downloading and installing node v12.18.3...
> Now using node v12.18.3 (npm v6.14.6)
npx @backstage/create-app
```
To get up and running with a local Backstage to evaluate it, let's clone it off
of GitHub and run an initial build.
You will be taken through a wizard to create your app, and the output should
look something like this. You can read more about this process
[here](https://backstage.io/docs/getting-started/create-an-app).
```bash
# Start from your local development folder
git clone git@github.com:spotify/backstage.git
cd backstage
### Contributing to Backstage
# Fetch our dependencies and run an initial build
yarn install
yarn tsc
yarn build
```
You can read more in our
[CONTRIBUTING](https://github.com/spotify/backstage/blob/master/CONTRIBUTING.md)
guide, which can help you get setup with a Backstage development environment.
Phew! Now you have a local repository that's ready to run and to add any open
source contributions into.
### Next steps
We are now going to launch two things: an example Backstage frontend app, and an
example Backstage backend that the frontend talks to. You are going to need two
terminal windows, both starting from the Backstage project root.
In the first window, run
```bash
cd packages/backend
yarn start
```
That starts up a backend instance on port 7000.
In the other window, we will first populate the catalog with some nice mock data
to look at, and then launch the frontend. These commands are run from the
project root, not inside the backend directory.
```bash
yarn lerna run mock-data
yarn start
```
That starts up the frontend on port 3000, and should automatically open a
browser window showing it.
Congratulations! That should be it. Let us know how it went
[on discord](https://discord.gg/EBHEGzX), file issues for any
[feature](https://github.com/spotify/backstage/issues/new?labels=help+wanted&template=feature_template.md)
or
[plugin suggestions](https://github.com/spotify/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME),
or
[bugs](https://github.com/spotify/backstage/issues/new?labels=bug&template=bug_template.md)
you have, and feel free to
[contribute](https://github.com/spotify/backstage/blob/master/CONTRIBUTING.md)!
## Creating a Plugin
The value of Backstage grows with every new plugin that gets added. Here is a
collection of tutorials that will guide you through setting up and extending an
instance of Backstage with your own plugins.
- [Development Environment](development-environment.md)
- [Create a Backstage Plugin](../plugins/create-a-plugin.md)
- [Structure of a Plugin](../plugins/structure-of-a-plugin.md)
- [Utility APIs](../api/utility-apis.md)
[Back to Docs](../README.md)
Take a look at the [Running Backstage Locally](./running-backstage-locally.md)
guide to learn how to set up Backstage, and how to develop on the platform.
@@ -0,0 +1,84 @@
---
id: running-backstage-locally
title: Running Backstage Locally
---
First make sure you are using NodeJS with an Active LTS Release, currently v12.
This is made easy with a version manager such as nvm which allows for version
switching.
```bash
# Checking your version
node --version
> v14.7.0
# Adding a second node version
nvm install 12
> Downloading and installing node v12.18.3...
> Now using node v12.18.3 (npm v6.14.6)
```
To get up and running with a local Backstage to evaluate it, let's clone it off
of GitHub and run an initial build.
```bash
# Start from your local development folder
git clone git@github.com:spotify/backstage.git
cd backstage
# Fetch our dependencies and run an initial build
yarn install
yarn tsc
yarn build
```
Phew! Now you have a local repository that's ready to run and to add any open
source contributions into.
We are now going to launch two things: an example Backstage frontend app, and an
example Backstage backend that the frontend talks to. You are going to need two
terminal windows, both starting from the Backstage project root.
In the first window, run
```bash
cd packages/backend
yarn start
```
That starts up a backend instance on port 7000.
In the other window, we will first populate the catalog with some nice mock data
to look at, and then launch the frontend. These commands are run from the
project root, not inside the backend directory.
```bash
yarn lerna run mock-data
yarn start
```
That starts up the frontend on port 3000, and should automatically open a
browser window showing it.
Congratulations! That should be it. Let us know how it went
[on discord](https://discord.gg/EBHEGzX), file issues for any
[feature](https://github.com/spotify/backstage/issues/new?labels=help+wanted&template=feature_template.md)
or
[plugin suggestions](https://github.com/spotify/backstage/issues/new?labels=plugin&template=plugin_template.md&title=%5BPlugin%5D+THE+PLUGIN+NAME),
or
[bugs](https://github.com/spotify/backstage/issues/new?labels=bug&template=bug_template.md)
you have, and feel free to
[contribute](https://github.com/spotify/backstage/blob/master/CONTRIBUTING.md)!
## Creating a Plugin
The value of Backstage grows with every new plugin that gets added. Here is a
collection of tutorials that will guide you through setting up and extending an
instance of Backstage with your own plugins.
- [Development Environment](development-environment.md)
- [Create a Backstage Plugin](../plugins/create-a-plugin.md)
- [Structure of a Plugin](../plugins/structure-of-a-plugin.md)
- [Utility APIs](../api/utility-apis.md)
[Back to Docs](../README.md)
+4 -1
View File
@@ -52,7 +52,10 @@ configuration will lead to the proxy acting on backend requests to
The value inside each route is either a simple URL string, or an object on the
format accepted by
[http-proxy-middleware](https://www.npmjs.com/package/http-proxy-middleware).
[http-proxy-middleware](https://www.npmjs.com/package/http-proxy-middleware). It
is also possible to limit the forwarded HTTP methods with the configuration
`allowedMethods`, for example `allowedMethods: ['GET']` to enforce read-only
access.
If the value is a string, it is assumed to correspond to:
+1
View File
@@ -12,6 +12,7 @@
],
"Getting Started": [
"getting-started/index",
"getting-started/running-backstage-locally",
"getting-started/installation",
"getting-started/development-environment",
"getting-started/create-an-app",
+4 -2
View File
@@ -93,8 +93,10 @@ const siteConfig = {
cleanUrl: true,
// Open Graph and Twitter card images.
ogImage: 'img/logo-gradient-on-dark.svg',
twitterImage: 'img/logo-gradient-on-dark.svg',
ogImage:
'logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_04_Icon_Teal.png',
twitterImage:
'logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_04_Icon_Teal.png',
// For sites with a sizable amount of content, set collapsible to true.
// Expand/collapse the links and subcategories under categories.
+2 -1
View File
@@ -12,7 +12,8 @@ nav:
- Strategies for adopting: 'overview/adopting.md'
- Logo assets: 'overview/logos.md'
- Getting started:
- Running Backstage locally: 'getting-started/index.md'
- Getting Started: 'getting-started/index.md'
- Running Backstage locally: 'getting-started/running-backstage-locally.md'
- Installation: 'getting-started/installation.md'
- Local development: 'getting-started/development-environment.md'
- Demo deployment: https://backstage-demo.roadie.io
@@ -86,3 +86,9 @@ export const Languages = () => (
<CodeSnippet text={PYTHON} language="python" showLineNumbers />
</InfoCard>
);
export const CopyCode = () => (
<InfoCard title="Copy Code">
<CodeSnippet text={JAVASCRIPT} language="javascript" showCopyCodeButton />
</InfoCard>
);
@@ -15,7 +15,7 @@
*/
import React from 'react';
import { render } from '@testing-library/react';
import { render, fireEvent } from '@testing-library/react';
import { wrapInTestApp } from '@backstage/test-utils';
import { CodeSnippet } from './CodeSnippet';
@@ -55,4 +55,14 @@ describe('<CodeSnippet />', () => {
expect(queryByText(/2/)).toBeInTheDocument();
expect(queryByText(/3/)).toBeInTheDocument();
});
it('copy code using button', async () => {
document.execCommand = jest.fn();
const rendered = render(
wrapInTestApp(<CodeSnippet {...minProps} showCopyCodeButton />),
);
const button = rendered.getByTitle('Text copied to clipboard');
fireEvent.click(button);
expect(document.execCommand).toHaveBeenCalled();
});
});
@@ -20,19 +20,22 @@ import SyntaxHighlighter from 'react-syntax-highlighter';
import { docco, dark } from 'react-syntax-highlighter/dist/cjs/styles/hljs';
import { useTheme } from '@material-ui/core';
import { BackstageTheme } from '@backstage/theme';
import { CopyTextButton } from '../CopyTextButton';
type Props = {
text: string;
language: string;
showLineNumbers?: boolean;
showCopyCodeButton?: boolean;
};
const defaultProps = {
showLineNumbers: false,
showCopyCodeButton: false,
};
export const CodeSnippet: FC<Props> = props => {
const { text, language, showLineNumbers } = {
const { text, language, showLineNumbers, showCopyCodeButton } = {
...defaultProps,
...props,
};
@@ -41,13 +44,20 @@ export const CodeSnippet: FC<Props> = props => {
const mode = theme.palette.type === 'dark' ? dark : docco;
return (
<SyntaxHighlighter
language={language}
style={mode}
showLineNumbers={showLineNumbers}
>
{text}
</SyntaxHighlighter>
<div style={{ position: 'relative' }}>
<SyntaxHighlighter
language={language}
style={mode}
showLineNumbers={showLineNumbers}
>
{text}
</SyntaxHighlighter>
{showCopyCodeButton && (
<div style={{ position: 'absolute', top: 0, right: 0 }}>
<CopyTextButton text={text} />
</div>
)}
</div>
);
};
@@ -56,4 +66,5 @@ CodeSnippet.propTypes = {
text: PropTypes.string.isRequired,
language: PropTypes.string.isRequired,
showLineNumbers: PropTypes.bool,
showCopyCodeButton: PropTypes.bool,
};
@@ -15,7 +15,7 @@
*/
import React from 'react';
import { render } from '@testing-library/react';
import { render, fireEvent } from '@testing-library/react';
import { wrapInTestApp } from '@backstage/test-utils';
import { CopyTextButton } from './CopyTextButton';
import {
@@ -76,7 +76,7 @@ describe('<CopyTextButton />', () => {
),
);
const button = rendered.getByTitle('mockTooltip');
button.click();
fireEvent.click(button);
expect(document.execCommand).toHaveBeenCalled();
rendered.getByText('mockTooltip');
});
@@ -63,7 +63,7 @@ export const CopyTextButton: FC<Props> = props => {
};
const classes = useStyles(props);
const errorApi = useApi(errorApiRef);
const inputRef = useRef<HTMLInputElement>(null);
const inputRef = useRef<HTMLTextAreaElement>(null);
const [open, setOpen] = useState(false);
const handleCopyClick: MouseEventHandler = e => {
@@ -82,9 +82,8 @@ export const CopyTextButton: FC<Props> = props => {
return (
<>
<input
<textarea
ref={inputRef}
type="text"
style={{ position: 'absolute', top: -9999, left: 9999 }}
defaultValue={text}
/>
@@ -2,8 +2,15 @@ FROM node:12
WORKDIR /usr/src/app
COPY . .
# Copy repo skeleton first, to avoid unnecessary docker cache invalidation.
# The skeleton contains the package.json of each package in the monorepo,
# and along with yarn.lock and the root package.json, that's enough to run yarn install.
ADD yarn.lock package.json skeleton.tar ./
RUN yarn install --frozen-lockfile --production
# This will copy the contents of the dist-workspace when running the build-image command.
# Do not use this Dockerfile outside of that command, as it will copy in the source code instead.
COPY . .
CMD ["node", "packages/backend"]
@@ -39,7 +39,7 @@ export const EntityPageApi: FC<{ entity: Entity }> = ({ entity }) => {
<Grid container spacing={3}>
{apiNames.map(api => (
<Grid item xs={12} key={api}>
<ApiDefinitionCard title={api} apiEntity={apiEntities!.get(api)} />
<ApiDefinitionCard apiEntity={apiEntities!.get(api)} />
</Grid>
))}
</Grid>
@@ -15,31 +15,92 @@
*/
import { ApiEntity } from '@backstage/catalog-model';
import { InfoCard } from '@backstage/core';
import { TabbedCard, CardTab } from '@backstage/core';
import React from 'react';
import { ApiDefinitionWidget } from '../ApiDefinitionWidget';
import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget';
import { Alert } from '@material-ui/lab';
import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget';
import { AsyncApiDefinitionWidget } from '../AsyncApiDefinitionWidget';
type Props = {
title?: string;
apiEntity?: ApiEntity;
type ApiDefinitionWidget = {
type: string;
title: string;
component: (definition: string) => React.ReactElement;
rawLanguage?: string;
};
export const ApiDefinitionCard = ({ title, apiEntity }: Props) => {
export function defaultDefinitionWidgets(): ApiDefinitionWidget[] {
return [
{
type: 'openapi',
title: 'OpenAPI',
rawLanguage: 'yaml',
component: definition => (
<OpenApiDefinitionWidget definition={definition} />
),
},
{
type: 'asyncapi',
title: 'AsyncAPI',
rawLanguage: 'yaml',
component: definition => (
<AsyncApiDefinitionWidget definition={definition} />
),
},
];
}
type Props = {
apiEntity?: ApiEntity;
definitionWidgets?: ApiDefinitionWidget[];
};
const defaultProps = {
definitionWidgets: defaultDefinitionWidgets(),
};
export const ApiDefinitionCard = (props: Props) => {
const { apiEntity, definitionWidgets } = {
...defaultProps,
...props,
};
if (!apiEntity) {
return <Alert severity="error">Could not fetch the API</Alert>;
}
const definitionWidget = definitionWidgets.find(
d => d.type === apiEntity.spec.type,
);
if (definitionWidget) {
return (
<InfoCard title={title}>
<Alert severity="error">Could not fetch the API</Alert>
</InfoCard>
<TabbedCard title={apiEntity.metadata.name}>
<CardTab label={definitionWidget.title}>
{definitionWidget.component(apiEntity.spec.definition)}
</CardTab>
<CardTab label="Raw">
<PlainApiDefinitionWidget
definition={apiEntity.spec.definition}
language={definitionWidget.rawLanguage || apiEntity.spec.type}
/>
</CardTab>
</TabbedCard>
);
}
return (
<InfoCard title={title} subheader={apiEntity.spec.type}>
<ApiDefinitionWidget
type={apiEntity.spec.type}
definition={apiEntity.spec.definition}
/>
</InfoCard>
<TabbedCard
title={apiEntity.metadata.name}
children={[
// Has to be an array, otherwise typescript doesn't like that this has only a single child
<CardTab label={apiEntity.spec.type}>
<PlainApiDefinitionWidget
definition={apiEntity.spec.definition}
language={apiEntity.spec.type}
/>
</CardTab>,
]}
/>
);
};
@@ -1,40 +0,0 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { AsyncApiDefinitionWidget } from '../AsyncApiDefinitionWidget';
import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget';
import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget';
type Props = {
type: string;
definition: string;
};
export const ApiDefinitionWidget = ({ type, definition }: Props) => {
switch (type) {
case 'openapi':
return <OpenApiDefinitionWidget definition={definition} />;
case 'asyncapi':
return <AsyncApiDefinitionWidget definition={definition} />;
default:
return (
<PlainApiDefinitionWidget definition={definition} language={type} />
);
}
};
@@ -1,17 +0,0 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { ApiDefinitionWidget } from './ApiDefinitionWidget';
@@ -136,7 +136,7 @@ const useStyles = makeStyles(theme => ({
}));
type Props = {
definition: any;
definition: string;
};
export const AsyncApiDefinitionWidget = ({ definition }: Props) => {
@@ -66,7 +66,7 @@ const useStyles = makeStyles(theme => ({
}));
type Props = {
definition: any;
definition: string;
};
export const OpenApiDefinitionWidget = ({ definition }: Props) => {
@@ -23,5 +23,7 @@ type Props = {
};
export const PlainApiDefinitionWidget = ({ definition, language }: Props) => {
return <CodeSnippet text={definition} language={language} />;
return (
<CodeSnippet text={definition} language={language} showCopyCodeButton />
);
};
+3
View File
@@ -15,5 +15,8 @@
*/
export { ApiDefinitionCard } from './ApiDefinitionCard';
export { AsyncApiDefinitionWidget } from './AsyncApiDefinitionWidget';
export { OpenApiDefinitionWidget } from './OpenApiDefinitionWidget';
export { PlainApiDefinitionWidget } from './PlainApiDefinitionWidget';
export { useComponentApiNames } from './useComponentApiNames';
export { useComponentApiEntities } from './useComponentApiEntities';
+1
View File
@@ -22,6 +22,7 @@
"@backstage/backend-common": "^0.1.1-alpha.21",
"@backstage/config": "^0.1.1-alpha.21",
"@types/express": "^4.17.6",
"@types/http-proxy-middleware": "^0.19.3",
"express": "^4.17.1",
"express-promise-router": "^3.0.3",
"http-proxy-middleware": "^0.19.1",
+12 -2
View File
@@ -18,10 +18,11 @@ import { Config } from '@backstage/config';
import express from 'express';
import Router from 'express-promise-router';
import createProxyMiddleware, {
Config as ProxyConfig,
Config as ProxyMiddlewareConfig,
Proxy,
} from 'http-proxy-middleware';
import { Logger } from 'winston';
import http from 'http';
export interface RouterOptions {
logger: Logger;
@@ -30,6 +31,10 @@ export interface RouterOptions {
pathPrefix: string;
}
export interface ProxyConfig extends ProxyMiddlewareConfig {
allowedMethods?: string[];
}
// Creates a proxy middleware, possibly with defaults added on top of the
// given config.
function buildMiddleware(
@@ -58,7 +63,12 @@ function buildMiddleware(
// Attach the logger to the proxy config
fullConfig.logProvider = () => logger;
return createProxyMiddleware(fullConfig);
// Only permit the allowed HTTP methods if configured
const filter = (_pathname: string, req: http.IncomingMessage): boolean => {
return fullConfig?.allowedMethods?.includes(req.method!) ?? true;
};
return createProxyMiddleware(filter, fullConfig);
}
export async function createRouter(
+7 -2
View File
@@ -4209,7 +4209,7 @@
resolved "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.0.tgz#682477dbbbd07cd032731cb3b0e7eaee3d026b69"
integrity sha512-2aoSC4UUbHDj2uCsCxcG/vRMXey/m17bC7UwitVm5hn22nI8O8Y9iDpA76Orc+DWkQ4zZrOKEshCqR/jSuXAHA==
"@types/http-proxy-middleware@*":
"@types/http-proxy-middleware@*", "@types/http-proxy-middleware@^0.19.3":
version "0.19.3"
resolved "https://registry.npmjs.org/@types/http-proxy-middleware/-/http-proxy-middleware-0.19.3.tgz#b2eb96fbc0f9ac7250b5d9c4c53aade049497d03"
integrity sha512-lnBTx6HCOUeIJMLbI/LaL5EmdKLhczJY5oeXZpX/cXE4rRqb3RmV7VcMpiEfYkmTjipv3h7IAyIINe4plEv7cA==
@@ -14876,11 +14876,16 @@ node-fetch-npm@^2.0.2:
json-parse-better-errors "^1.0.0"
safe-buffer "^5.1.1"
node-fetch@2.6.0, node-fetch@^2.1.2, node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.5.0, node-fetch@^2.6.0:
node-fetch@2.6.0:
version "2.6.0"
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
node-fetch@^2.1.2, node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.5.0, node-fetch@^2.6.0:
version "2.6.1"
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
node-forge@0.9.0:
version "0.9.0"
resolved "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"