Merge branch 'master' of https://github.com/backstage/backstage into pr-draft
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-auth-backend': patch
|
||||
---
|
||||
|
||||
Fix a bug preventing an access token to be refreshed a second time with the GitLab provider.
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Change the styling of the `<DependencyGraph>` to have more contrast in light
|
||||
mode. Nodes now have a design similar to material UI buttons.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
---
|
||||
|
||||
Action needed: If you are using the templates located at https://github.com/backstage/backstage/tree/master/ in your Backstage app directly using the URL via the `app-config.yaml`, you should copy over the templates inside your org and import from there. The templates have now been moved to https://github.com/backstage/software-templates. See https://github.com/backstage/backstage/issues/6415 for explanation.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
replace the deprecated file-loader for fonts with assets module
|
||||
@@ -1,16 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-auth-backend': minor
|
||||
---
|
||||
|
||||
Bump `passport-saml` to version 3. This is a breaking change, in that it [now requires](https://github.com/node-saml/passport-saml/pull/548) the `auth.saml.cert` parameter to be set. If you are not using SAML auth, you can ignore this.
|
||||
|
||||
To update your settings, add something similar to the following to your app-config:
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
saml:
|
||||
# ... other settings ...
|
||||
cert: 'MIICizCCAfQCCQCY8tKaMc0BMjANBgkqh ... W=='
|
||||
```
|
||||
|
||||
For more information, see the [library README](https://github.com/node-saml/passport-saml#security-and-signatures).
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Set the default TZ (Timezone) env for the test command to be UTC so any date related tests are consistent across timezones.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-user-settings': patch
|
||||
---
|
||||
|
||||
Fix import for `createPlugin` in example snippet
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-newrelic': patch
|
||||
---
|
||||
|
||||
Added pagination and searching to the table
|
||||
@@ -1,28 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-home': minor
|
||||
---
|
||||
|
||||
The homepage `<Header />` is now part of the composable canvas (allowing you to add the <HomepageTimer />, for example).
|
||||
|
||||
You will need to wrap your existing composed `<HomePage />` component in `<Page />`, `<Header />`, and `<Content />` components, like this:
|
||||
|
||||
```diff
|
||||
// app/src/components/home/HomePage.tsx
|
||||
|
||||
+ import { Content, Header, Page, HomePageTimer } from '@backstage/core-components';
|
||||
|
||||
export const HomePage = () => (
|
||||
+ <Page themeId="home">
|
||||
+ <Header title="Home">
|
||||
+ <HomepageTimer />
|
||||
+ </Header>
|
||||
+ <Content>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12}>
|
||||
<HomePageSearchBar />
|
||||
</Grid>
|
||||
// ...
|
||||
+ </Content>
|
||||
+ </Page>
|
||||
);
|
||||
```
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
This change adds an API endpoint for requesting a catalog refresh at `/refresh`, which is activated if a `RefreshService` is passed to `createRouter`.
|
||||
The creation of the router has been abstracted behind the `CatalogBuilder` to simplify usage and future changes. The following **changes are required** to your `catalog.ts` for the refresh endpoint to function.
|
||||
|
||||
```diff
|
||||
- import {
|
||||
- CatalogBuilder,
|
||||
- createRouter,
|
||||
- } from '@backstage/plugin-catalog-backend';
|
||||
+ import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
|
||||
|
||||
export default async function createPlugin(
|
||||
env: PluginEnvironment,
|
||||
): Promise<Router> {
|
||||
const builder = await CatalogBuilder.create(env);
|
||||
- const {
|
||||
- entitiesCatalog,
|
||||
- locationAnalyzer,
|
||||
- processingEngine,
|
||||
- locationService,
|
||||
- } = await builder.build();
|
||||
+ const { processingEngine, router } = await builder.build();
|
||||
await processingEngine.start();
|
||||
|
||||
- return await createRouter({
|
||||
- entitiesCatalog,
|
||||
- locationAnalyzer,
|
||||
- locationService,
|
||||
- logger: env.logger,
|
||||
- config: env.config,
|
||||
- });
|
||||
+ return router;
|
||||
}
|
||||
```
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
'@backstage/integration': patch
|
||||
---
|
||||
|
||||
Fix Azure URL handling to properly support both repo shorthand (`/owner/_git/project`) and full URLs (`/owner/project/_git/repo`).
|
||||
|
||||
Fix Azure DevOps Server URL handling by being able to parse URLs with hosts other than `dev.azure.com`. Note that the `api-version` used for API requests is currently `6.0`, meaning you need to support at least this version in your Azure DevOps Server instance.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
---
|
||||
|
||||
Fill in most missing type exports.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-auth-backend': patch
|
||||
---
|
||||
|
||||
Use a more informative error message if the configured OIDC identity provider does not provide a `userinfo_endpoint` in its metadata.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
---
|
||||
|
||||
Change the Categories filter to a dropdown component
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/backend-common': patch
|
||||
---
|
||||
|
||||
Fix Azure `readTree` and `search` handling to properly support paths.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend': minor
|
||||
---
|
||||
|
||||
Add API endpoint for requesting a catalog refresh at `/refresh`, which is activated if a `RefreshService` is passed to `createRouter`.
|
||||
|
||||
The new method is used to trigger a refresh of an entity in an as localized was as possible, usually by refreshing the parent location.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Improve UX for Login pop-up
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-circleci': patch
|
||||
---
|
||||
|
||||
Swapped over to using Luxon as opposed to DayJS in the CircleCI plugin as part of the single Date library improvements.
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
'@backstage/core-app-api': patch
|
||||
'@backstage/core-plugin-api': patch
|
||||
---
|
||||
|
||||
Switch to using utilities from `@backstage/version-bridge'.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
remove hard coded min height in page header
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/plugin-api-docs': patch
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
---
|
||||
|
||||
This makes Type and Lifecycle columns consistent for all table cases and adds a new line in Description column for better readability
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
'@backstage/backend-common': patch
|
||||
'@backstage/integration': patch
|
||||
'@backstage/techdocs-common': patch
|
||||
'@backstage/plugin-catalog': patch
|
||||
'@backstage/plugin-catalog-backend': patch
|
||||
'@backstage/plugin-catalog-import': patch
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
'@backstage/plugin-techdocs': patch
|
||||
---
|
||||
|
||||
Upgrade git-parse-url to v11.6.0
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-home': patch
|
||||
---
|
||||
|
||||
Adjust dependencies to `@types/react` and `react-router` to follow the pattern
|
||||
used by all other Backstage packages.
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-explore': patch
|
||||
---
|
||||
|
||||
Make styling of groups tab in the explore page use the Backstage theme instead
|
||||
of hard coded colors. Change the layout to be full screen.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/integration': patch
|
||||
---
|
||||
|
||||
Handle pagination on return results when fetch GitHub API to list selected repos
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-catalog': patch
|
||||
---
|
||||
|
||||
Display entity titles on `EntityLayout` if defined
|
||||
@@ -1,6 +0,0 @@
|
||||
---
|
||||
'@backstage/plugin-cloudbuild': patch
|
||||
---
|
||||
|
||||
- Swaps over the plugin CloudBuild from using MomentJS to using Luxon for date formatting.
|
||||
- Fixes some React warnings generated by nested <p> elements.
|
||||
@@ -97,6 +97,7 @@ GraphQL
|
||||
graphviz
|
||||
Hackathons
|
||||
haproxy
|
||||
hardcoded
|
||||
Helidon
|
||||
Heroku
|
||||
hoc
|
||||
|
||||
@@ -45,3 +45,4 @@
|
||||
| [Powerspike](https://powerspike.tv/) | [@trelore](https://github.com/trelore) | Developer portal for documentation of core libraries and repositories. |
|
||||
| [2U](https://2u.com) | [Andrew Thal](https://github.com/athal7) | Development team home-base, promoting service discoverability, resource dependencies, and tech radar |
|
||||
| [Taxfix](https://taxfix.de/) | [Sami Ur Rehman](https://github.com/samiurrehman92) | Developer's portal with software catalog at it's core. Hosts API Specs, Tech Docs, Tech Radar and some custom plugins. |
|
||||
| [Busuu](https://busuu.com/) | [Adam Tester](https://github.com/adamtester) | Developer portal with service catalog, API docs, Event docs, service templating, and cost insights. |
|
||||
|
||||
+12
-20
@@ -13,27 +13,19 @@ can authenticate users using Okta OpenID Connect.
|
||||
To add Okta authentication, you must create an Application from Okta:
|
||||
|
||||
1. Log into Okta (generally company.okta.com)
|
||||
2. Navigation to Applications > Applications
|
||||
3. Click `Add Application`
|
||||
4. Click `Create New App` and select Web + OpenID Connect
|
||||
5. Fill out the OpenID Connect App Integration form:
|
||||
- `Application name`: Backstage (or your custom app name)
|
||||
- `Login redirect URIs`: `Add URI` >
|
||||
2. Navigate to Menu >> Applications >> Applications >> `Create App Integration`
|
||||
3. Fill out the Create a new app integration form:
|
||||
- `Sign-in method`: `OIDC - OpenID Connect`
|
||||
- `Application type`: `Web Application`
|
||||
- Click Next
|
||||
4. Fill out the New Web App Integration form:
|
||||
- `App integration name`: `Backstage` (or your custom app name)
|
||||
- `Grant type`: `Authorization Code` & `Refresh Token`
|
||||
- `Sign-in redirect URIs`:
|
||||
`http://localhost:7000/api/auth/okta/handler/frame`
|
||||
6. Click Save
|
||||
7. Under `General Settings`, click Edit and check the `Refresh Token` box
|
||||
8. Click Save
|
||||
|
||||
## Assign the Application
|
||||
|
||||
Okta login is only permitted to those people or groups that have this new
|
||||
Application **assigned**. This can be done from Okta's Directory.
|
||||
|
||||
These are the steps to assign Backstage login permission to **everyone**:
|
||||
|
||||
1. Navigate to Directory > Groups on Okta
|
||||
2. Click on the `Everyone` group
|
||||
3. Click `Manage Apps` and then `Assign` next to Backstage
|
||||
- `Sign-out redirect URIs`: `http://localhost:7000`
|
||||
- `Controlled access`: (select as appropriate)
|
||||
- Click Save
|
||||
|
||||
# Configuration
|
||||
|
||||
|
||||
@@ -122,12 +122,12 @@ sometimes desired because Docker in Docker is not available in the build
|
||||
environment, or due to other requirements.
|
||||
|
||||
The build is split into three different stages, where the first stage finds all
|
||||
of the `package.json`s that are relevant for the initial install step enabling
|
||||
us to cache the initial `yarn install` that installs all dependencies. The
|
||||
second stage executes the build itself, and is similar to the steps we execute
|
||||
on the host in the host build. The third and final stage then packages it all
|
||||
together into the final image, and is similar to the `Dockerfile` of the host
|
||||
build.
|
||||
of the `package.json` files that are relevant for the initial install step
|
||||
enabling us to cache the initial `yarn install` that installs all dependencies.
|
||||
The second stage executes the build itself, and is similar to the steps we
|
||||
execute on the host in the host build. The third and final stage then packages
|
||||
it all together into the final image, and is similar to the `Dockerfile` of the
|
||||
host build.
|
||||
|
||||
The following `Dockerfile` executes the multi-stage build and should be added to
|
||||
the repo root:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: index
|
||||
title: Deploying Backstage
|
||||
sidebar_title: Overview
|
||||
sidebar_label: Overview
|
||||
description: Packaging Backstage and deploying to production
|
||||
---
|
||||
|
||||
@@ -32,7 +32,7 @@ requires the first two steps.
|
||||
An example of deploying Backstage with a [Helm chart](helm.md), a common pattern
|
||||
in AWS, is also available. There is also a contrib guide to deploying Backstage
|
||||
with
|
||||
[AWS Fargate and Aurora PostgreSQL](https://github.com/backstage/backstage/blob/master/contrib/docs/tutorials/aws-fargate-deployment.md)
|
||||
[AWS Fargate and Aurora PostgreSQL](https://github.com/backstage/backstage/blob/master/contrib/docs/tutorials/aws-fargate-deployment.md).
|
||||
|
||||
Please consider contributing other deployment guides if you get Backstage set up
|
||||
on common infrastructure, it would be a great benefit to the community.
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
id: migrating-from-v1alpha1-to-v1beta2
|
||||
title: Migrating to v1beta2 templates
|
||||
# prettier-ignore
|
||||
description:
|
||||
How to move your old templates from v1alpha1 to the more declarative v1beta2
|
||||
description: How to move your old templates from v1alpha1 to the more declarative v1beta2
|
||||
---
|
||||
|
||||
# What's new?
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
---
|
||||
id: writing-custom-field-extensions
|
||||
title: Writing Custom Field Extensions
|
||||
description: How to write your own field extensions
|
||||
---
|
||||
|
||||
Collecting input from the user is a very large part of the scaffolding process
|
||||
and Software Templates as a whole. Sometimes the built in components and fields
|
||||
just aren't good enough, and sometimes you want to enrich the form that the
|
||||
users sees with better inputs that fit better.
|
||||
|
||||
This is where `Custom Field Extensions` come in.
|
||||
|
||||
With them you can show your own `React` Components and use them to control the
|
||||
state of the JSON schema, as well as provide your own validation functions to
|
||||
validate the data too.
|
||||
|
||||
## Creating a Field Extension
|
||||
|
||||
Field extensions are a way to combine an ID, a `React` Component and a
|
||||
`validation` function together in a modular way that you can then use to pass to
|
||||
the `Scaffolder` frontend plugin in your own `App.tsx`.
|
||||
|
||||
You can create your own Field Extension by using the
|
||||
[`createScaffolderFieldExtension`](https://backstage.io/docs/reference/plugin-scaffolder.createscaffolderfieldextension)
|
||||
`API` like below:
|
||||
|
||||
```tsx
|
||||
//packages/app/scaffolder/MyCustomExtension/MyCustomExtension.tsx
|
||||
import { FieldProps, FieldValidation } from '@rjsf/core';
|
||||
import { KubernetesValidatorFunctions } from '@backstage/catalog-model';
|
||||
/*
|
||||
This is the actual component that will get rendered in the form
|
||||
*/
|
||||
export const MyCustomExtension = ({ onChange, required }: FieldProps<string>) => {
|
||||
return (
|
||||
<FormControl
|
||||
margin="normal"
|
||||
required={required}
|
||||
error={rawErrors?.length > 0 && !formData}
|
||||
onChange={onChange}
|
||||
>
|
||||
)
|
||||
};
|
||||
|
||||
/*
|
||||
This is a validation function that will run when the form is submitted.
|
||||
You will get the value from the `onChange` handler before as the value here to make sure that the types are aligned\
|
||||
*/
|
||||
|
||||
export const myCustomValidation = (
|
||||
value: string,
|
||||
validation: FieldValidation,
|
||||
) => {
|
||||
if (!KubernetesValidatorFunctions.isValidObjectName(value)) {
|
||||
validation.addError(
|
||||
'must start and end with an alphanumeric character, and contain only alphanumeric characters, hyphens, underscores, and periods. Maximum length is 63 characters.',
|
||||
);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
```tsx
|
||||
// packages/app/scaffolder/MyCustomExtension/extensions.ts
|
||||
|
||||
/*
|
||||
This is where the magic happens and creates the custom field extension.
|
||||
|
||||
Note that if you're writing extensions part of a separate plugin,
|
||||
then please use `plugin.provide` from there instead and export it part of your `plugin.ts` rather than re-using the `scaffolder.plugin`.
|
||||
*/
|
||||
|
||||
import {
|
||||
plugin,
|
||||
createScaffolderFieldExtension,
|
||||
} from '@backstage/plugin-scaffolder';
|
||||
import { MyCustomExtension } from './MyCustomExtension';
|
||||
import { myCustomValidation } from './validation';
|
||||
|
||||
export const MyCustomFieldExtension = plugin.provide(
|
||||
createScaffolderFieldExtension({
|
||||
name: 'MyCustomExtension',
|
||||
component: MyCustomExtension,
|
||||
validation: myCustomValidation,
|
||||
}),
|
||||
);
|
||||
```
|
||||
|
||||
```tsx
|
||||
// packages/app/scaffolder/MyCustomExtension/index.ts
|
||||
|
||||
export { MyCustomFieldExtension } from './extension';
|
||||
```
|
||||
|
||||
Once all these files are in place, you then need to provide your custom
|
||||
extension to the `scaffolder` plugin.
|
||||
|
||||
You do this in `packages/app/App.tsx`. You need to provide the
|
||||
`customFieldExtensions` as children to the `ScaffolderPage`.
|
||||
|
||||
```tsx
|
||||
const routes = (
|
||||
<FlatRoutes>
|
||||
...
|
||||
<Route path="/create" element={<ScaffolderPage />} />
|
||||
...
|
||||
</FlatRoutes>
|
||||
);
|
||||
```
|
||||
|
||||
Should look something like this instead:
|
||||
|
||||
```tsx
|
||||
import { MyCustomFieldExtension } from './scafffolder/MyCustomExtension';
|
||||
const routes = (
|
||||
<FlatRoutes>
|
||||
...
|
||||
<Route path="/create" element={<ScaffolderPage />}>
|
||||
<ScaffolderFieldExtensions>
|
||||
<MyCustomFieldExtension />
|
||||
</ScaffolderFieldExtensions>
|
||||
</Route>
|
||||
...
|
||||
</FlatRoutes>
|
||||
);
|
||||
```
|
||||
|
||||
## Using the Custom Field Extension
|
||||
|
||||
Once it's been passed to the `ScaffolderPage` you should now be able to use the
|
||||
`ui:field` property in your templates to point it to the name of the
|
||||
`customFieldExtension` that you registered.
|
||||
|
||||
Something like this:
|
||||
|
||||
```yaml
|
||||
apiVersion: backstage.io/v1beta2
|
||||
kind: Template
|
||||
metadata:
|
||||
name: Test template
|
||||
title: Test template with custom extension
|
||||
description: Test template
|
||||
spec:
|
||||
parameters:
|
||||
- title: Fill in some steps
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
name:
|
||||
title: Name
|
||||
type: string
|
||||
description: My custom name for the component
|
||||
ui:field: MyCustomExtension
|
||||
```
|
||||
@@ -60,6 +60,20 @@ providers are used.
|
||||
|
||||
## Project roadmap
|
||||
|
||||
### **Published versions**
|
||||
|
||||
**Alpha release** ✅ -
|
||||
[Milestone](https://github.com/backstage/backstage/milestone/16)
|
||||
|
||||
- Alpha of TechDocs that you can use end to end - and contribute to.
|
||||
|
||||
**Beta release** ✅ -
|
||||
[Milestone](https://github.com/backstage/backstage/milestone/29)
|
||||
|
||||
- TechDocs' recommended setup supports most environments (CI systems, cloud
|
||||
storage solutions, source control systems).
|
||||
- [Instructions for upgrading from Alpha to Beta](how-to-guides.md#how-to-migrate-from-techdocs-alpha-to-beta)
|
||||
|
||||
### **Future work 🔮**
|
||||
|
||||
**General Availability (GA) release** -
|
||||
|
||||
@@ -88,7 +88,7 @@ const themeOptions = createThemeOptions({
|
||||
main: '#123456',
|
||||
},
|
||||
error: {
|
||||
main: '#123456'
|
||||
main: '#123456',
|
||||
},
|
||||
warning: {
|
||||
main: '#123456',
|
||||
@@ -105,17 +105,17 @@ const themeOptions = createThemeOptions({
|
||||
},
|
||||
banner: {
|
||||
info: '#123456',
|
||||
error: '#123456'
|
||||
text: '#123456'
|
||||
error: '#123456',
|
||||
text: '#123456',
|
||||
link: '#123456',
|
||||
},
|
||||
errorBackground: '#123456'
|
||||
warningBackground: '#123456'
|
||||
infoBackground: '#123456'
|
||||
errorBackground: '#123456',
|
||||
warningBackground: '#123456',
|
||||
infoBackground: '#123456',
|
||||
navigation: {
|
||||
background: '#123456',
|
||||
indicator: '#123456'
|
||||
color: '#123456'
|
||||
indicator: '#123456',
|
||||
color: '#123456',
|
||||
selectedColor: '#123456',
|
||||
},
|
||||
},
|
||||
@@ -123,15 +123,15 @@ const themeOptions = createThemeOptions({
|
||||
fontFamily: 'Comic Sans',
|
||||
/* below drives the header colors */
|
||||
pageTheme: {
|
||||
home: genPageTheme(['#123456','#123456'], shapes.wave),
|
||||
documentation: genPageTheme(['#123456','#123456'], shapes.wave2),
|
||||
tool: genPageTheme(['#123456','#123456'], shapes.round),
|
||||
service: genPageTheme(['#123456','#123456'], shapes.wave),
|
||||
website: genPageTheme(['#123456','#123456'], shapes.wave),
|
||||
library: genPageTheme(['#123456','#123456'], shapes.wave),
|
||||
other: genPageTheme(['#123456','#123456'], shapes.wave),
|
||||
app: genPageTheme(['#123456','#123456'], shapes.wave),
|
||||
apis: genPageTheme(['#123456','#123456'], shapes.wave),
|
||||
home: genPageTheme(['#123456', '#123456'], shapes.wave),
|
||||
documentation: genPageTheme(['#123456', '#123456'], shapes.wave2),
|
||||
tool: genPageTheme(['#123456', '#123456'], shapes.round),
|
||||
service: genPageTheme(['#123456', '#123456'], shapes.wave),
|
||||
website: genPageTheme(['#123456', '#123456'], shapes.wave),
|
||||
library: genPageTheme(['#123456', '#123456'], shapes.wave),
|
||||
other: genPageTheme(['#123456', '#123456'], shapes.wave),
|
||||
app: genPageTheme(['#123456', '#123456'], shapes.wave),
|
||||
apis: genPageTheme(['#123456', '#123456'], shapes.wave),
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
id: discovery
|
||||
title: AWS S3 Discovery
|
||||
sidebar_label: Discovery
|
||||
# prettier-ignore
|
||||
description: Automatically discovering catalog entities from an AWS S3 Bucket
|
||||
---
|
||||
|
||||
The AWS S3 integration has a special discovery processor for discovering catalog
|
||||
entities located in an S3 Bucket. If you have a bucket that contains multiple
|
||||
catalog-info files and want to automatically discover them, you can use this
|
||||
processor. The processor will crawl your S3 bucket and register entities
|
||||
matching the configured path. This can be useful as an alternative to static
|
||||
locations or manually adding things to the catalog.
|
||||
|
||||
To use the discovery processor, you'll need an AWS S3 integration
|
||||
[set up](locations.md) with an `AWS_ACCESS_KEY`, `AWS_SECRET_ACCESS_KEY`, and
|
||||
optionally a `roleArn`. Then you can add a location target to the catalog
|
||||
configuration:
|
||||
|
||||
```yaml
|
||||
catalog:
|
||||
locations:
|
||||
- type: s3-discovery
|
||||
target: https://sample-bucket.s3.us-east-2.amazonaws.com/
|
||||
```
|
||||
|
||||
Note the `s3-discovery` type, as this is not a regular `url` processor.
|
||||
@@ -19,13 +19,23 @@ to the catalog configuration:
|
||||
```yaml
|
||||
catalog:
|
||||
locations:
|
||||
# (since 0.13.5) Scan all repositories for a catalog-info.yaml in the root of the default branch
|
||||
- type: github-discovery
|
||||
target: https://github.com/myorg/service-*/blob/main/catalog-info.yaml
|
||||
target: https://github.com/myorg
|
||||
# Or use a custom pattern for a subset of all repositories with default repository
|
||||
- type: github-discovery
|
||||
target: https://github.com/myorg/service-*/blob/-/catalog-info.yaml
|
||||
# Or use a custom file format and location
|
||||
- type: github-discovery
|
||||
target: https://github.com/*/blob/-/docs/your-own-format.yaml
|
||||
# Or use a specific branch-name
|
||||
- type: github-discovery
|
||||
target: https://github.com/*/blob/backstage-docs/catalog-info.yaml
|
||||
```
|
||||
|
||||
Note the `github-discovery` type, as this is not a regular `url` processor.
|
||||
|
||||
The target is composed of three parts:
|
||||
When using a custom pattern, the target is composed of three parts:
|
||||
|
||||
- The base organization URL, `https://github.com/myorg` in this case
|
||||
- The repository blob to scan, which accepts \* wildcard tokens. This can simply
|
||||
@@ -34,7 +44,8 @@ The target is composed of three parts:
|
||||
- The path within each repository to find the catalog YAML file. This will
|
||||
usually be `/blob/main/catalog-info.yaml`, `/blob/master/catalog-info.yaml` or
|
||||
a similar variation for catalog files stored in the root directory of each
|
||||
repository.
|
||||
repository. You could also use a dash (`-`) for referring to the default
|
||||
branch.
|
||||
|
||||
## GitHub API Rate Limits
|
||||
|
||||
|
||||
@@ -442,14 +442,14 @@ component, you would do the following:
|
||||
</EntitySwitch.Case>
|
||||
|
||||
<EntitySwitch.Case>
|
||||
<MyTemplate />
|
||||
<MyOther />
|
||||
</EntitySwitch.Case>
|
||||
</EntitySwitch>
|
||||
|
||||
// Shorter form if desired:
|
||||
<EntitySwitch>
|
||||
<EntitySwitch.Case if={isKind('template')} children={<MyTemplate />}/>
|
||||
<EntitySwitch.Case children={<MyTemplate />}/>
|
||||
<EntitySwitch.Case children={<MyOther />}/>
|
||||
</EntitySwitch>
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
title: The TechDocs Beta has landed
|
||||
author: Eric Peterson, Spotify
|
||||
authorURL: https://github.com/iamEAP
|
||||
authorImageURL: https://avatars.githubusercontent.com/u/3496491?v=4
|
||||
---
|
||||
|
||||

|
||||
|
||||
**TLDR:** Another beta has landed! We continue to focus on improving the stability and scalability of Backstage while enhancing its functionality. Thanks to focused efforts from the TechDocs core team and community, we're happy to say that TechDocs — [our docs-like-code solution](https://backstage.io/blog/2020/09/08/announcing-tech-docs) for all the software in your catalog — is now, after [Software Templates](https://backstage.io/blog/2021/07/26/software-templates-are-now-in-beta), the second core feature to graduate to beta.
|
||||
|
||||
<!--truncate-->
|
||||
|
||||
In addition to new features and improvements, we made numerous compatibility updates ahead of this feature release. You'll find support for a variety of CI systems, cloud storage solutions, and source control systems — so that TechDocs works for most orgs, right out of box. But there's much more to explore in this beta, thanks to contributions from the community.
|
||||
|
||||
When we set out to define what beta looked like, we combed through GitHub issues, Discord discussions, and other media to identify common pain points and challenges encountered by those around the world who consume and author TechDocs documentation in their organization's Backstage instance. Based on this research, we put together a user-focused milestone and got to work. For an issue-by-issue breakdown, check out the milestone [on GitHub](https://github.com/backstage/backstage/milestone/29?closed=1) — or, just read on to get the highlights.
|
||||
|
||||
## Real-time builds and feedback
|
||||
|
||||

|
||||
|
||||
TechDocs can be transformational once fully up and running (update your code and your docs with the same pull request!). But for first-time users and especially those unfamiliar with the MkDocs ecosystem upon which TechDocs is built, there are often many small, obtuse hurdles that can get in the way of success. Leading up to the beta release, we worked to surface and improve relevant errors and other details during the documentation generation process. Better still, all of this detail is now provided to users _in real-time_, as docs are generated and refreshed.
|
||||
|
||||
<!-- vale off -->
|
||||
<p>🙌 Shout out to <a href="https://github.com/dhenneke">Dominik Henneke</a> for implementing the interactive experience.</p>
|
||||
<!-- vale on -->
|
||||
|
||||
## Custom homepages: Make TechDocs yours
|
||||
|
||||

|
||||
|
||||
We strive to make it so that you can mold Backstage into the shape that best fits your organization. With this beta release, just as you can with the Catalog entities and [Search](https://backstage.io/blog/2021/06/24/announcing-backstage-search-platform#composable-search-page-experiences), you can now customize and compose your own TechDocs homepage. Use it to level up the front page of your Backstage documentation by highlighting golden documentation at your company, or use the new and improved (and Catalog-inspired) experience. Read more about [how to customize the TechDocs homepage](https://backstage.io/docs/features/techdocs/how-to-guides#how-to-customize-the-techdocs-home-page).
|
||||
|
||||
<!-- vale off -->
|
||||
<p>🙏 Thanks to <a href="https://github.com/kuangp">Phil Kuang</a> for the improved default TechDocs home experience.</p>
|
||||
<!-- vale on -->
|
||||
|
||||
## Simpler YAML annotations: What's in a ref?
|
||||
|
||||

|
||||
|
||||
We often forget that in order to enable TechDocs on a Catalog entity, documentation authors have to sprinkle a little ref annotation voodoo into their catalog-info.yaml file. The form of this magic — the `backstage.io/techdocs-ref` annotation — has evolved over TechDocs' life. But unless you're a real Backstage aficionado, the specifics of what the value meant and how to construct it could be somewhat of a mystery.
|
||||
|
||||
In the beta, we've simplified this annotation dramatically for documentation authors, aligning its value with TechDocs' docs-like-code philosophy itself. In the vast majority of cases, its value will simply be `dir:.` — which means this catalog entity contains documentation and the mkdocs.yml file describing this documentation lives in the current directory. We continue to support edge cases for [other techdocs-ref annotation values](https://backstage.io/docs/features/techdocs/how-to-guides#how-to-understand-techdocs-ref-annotation-values), as well.
|
||||
|
||||
<!-- vale off -->
|
||||
<p>👏 Another round of applause for Dominik for driving this improvement through.</p>
|
||||
<!-- vale on -->
|
||||
|
||||
## Everything neat and tidy
|
||||
|
||||
If you've ever twitched a little looking at the address bar as you navigated through your TechDocs, because the "C" in "Component" was capitalized, or cringed whilst perusing through your TechDocs storage bucket, only to see assets you definitely remember deleting from a documentation site cluttering up the place…twitch and cringe no more!
|
||||
|
||||
TechDocs base paths are now case-insensitive, stale files are automatically cleaned up by the TechDocs publishing process — and even though [I say _.yaml_ and you say _.yml_](https://open.spotify.com/track/6NDaYWg85ZnJ3Ae0WkILWh) — TechDocs will now happily accept either file extension for your MkDocs YAML file.
|
||||
|
||||
## What should I do to upgrade?
|
||||
|
||||
If you've been waiting for the beta to give TechDocs a shot, good news! You'll get all of the above, plus all of TechDocs' existing features, right out of the box. Newly created Backstage apps come ready-to-go. You'll know you're on beta if you're using the following versions:
|
||||
|
||||
- TechDocs Plugin version >= 0.11.0
|
||||
- TechDocs Backend Plugin version >= 0.10.0
|
||||
- TechDocs CLI version >= 0.7.0
|
||||
|
||||
If you're upgrading from a prior, alpha version of TechDocs, be aware that there are some breaking changes that you will need to account for. Most importantly:
|
||||
|
||||
- Be sure your app's instance of TechDocs is wired up to use the composability API. [See full migration instructions here](https://backstage.io/docs/features/techdocs/how-to-guides#how-to-migrate-from-techdocs-alpha-to-beta).
|
||||
- If you've configured TechDocs to publish generated content to a remote storage solution provider like AWS S3, Google Cloud Storage, or Azure Blob Storage, you will need to use the TechDocs CLI to migrate the contents of your storage bucket. [See full migration instructions here](https://backstage.io/docs/features/techdocs/how-to-guides#how-to-migrate-from-techdocs-alpha-to-beta).
|
||||
- In order to take advantage of the stale file deletion functionality, you may need to add some permissions to the account or role used by your TechDocs backend to publish contents to your storage provider. [See "Using Cloud Storage docs"](https://backstage.io/docs/features/techdocs/using-cloud-storage) for updated permissions recommendations.
|
||||
|
||||
Thanks again to the whole community for hitting this milestone with us! Catch us in [Discord](https://discord.gg/MUpMjP2) or an [upcoming community session](https://github.com/backstage/community) if you have any questions.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 703 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 222 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 93 KiB |
@@ -70,6 +70,7 @@
|
||||
"features/software-templates/writing-templates",
|
||||
"features/software-templates/builtin-actions",
|
||||
"features/software-templates/writing-custom-actions",
|
||||
"features/software-templates/writing-custom-field-extensions",
|
||||
"features/software-templates/template-legacy",
|
||||
"features/software-templates/migrating-from-v1alpha1-to-v1beta2"
|
||||
]
|
||||
@@ -108,7 +109,10 @@
|
||||
{
|
||||
"type": "subcategory",
|
||||
"label": "AWS S3",
|
||||
"ids": ["integrations/aws-s3/locations"]
|
||||
"ids": [
|
||||
"integrations/aws-s3/locations",
|
||||
"integrations/aws-s3/discovery"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "subcategory",
|
||||
|
||||
@@ -82,6 +82,7 @@ nav:
|
||||
- Overview: 'integrations/index.md'
|
||||
- AWS S3:
|
||||
- Locations: 'integrations/aws-s3/locations.md'
|
||||
- Discovery: 'integrations/aws-s3/discovery.md'
|
||||
- Azure:
|
||||
- Locations: 'integrations/azure/locations.md'
|
||||
- Org Data: 'integrations/azure/org.md'
|
||||
|
||||
@@ -1,5 +1,46 @@
|
||||
# example-app
|
||||
|
||||
## 0.2.46
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.4.2
|
||||
- @backstage/cli@0.7.12
|
||||
- @backstage/plugin-techdocs@0.11.2
|
||||
- @backstage/plugin-user-settings@0.3.5
|
||||
- @backstage/plugin-newrelic@0.3.4
|
||||
- @backstage/plugin-home@0.4.0
|
||||
- @backstage/integration-react@0.1.9
|
||||
- @backstage/plugin-api-docs@0.6.8
|
||||
- @backstage/plugin-badges@0.2.9
|
||||
- @backstage/plugin-catalog@0.6.15
|
||||
- @backstage/plugin-catalog-import@0.5.21
|
||||
- @backstage/plugin-catalog-react@0.4.6
|
||||
- @backstage/plugin-circleci@0.2.23
|
||||
- @backstage/plugin-cloudbuild@0.2.23
|
||||
- @backstage/plugin-code-coverage@0.1.11
|
||||
- @backstage/plugin-cost-insights@0.11.6
|
||||
- @backstage/plugin-explore@0.3.16
|
||||
- @backstage/plugin-gcp-projects@0.3.4
|
||||
- @backstage/plugin-github-actions@0.4.18
|
||||
- @backstage/plugin-graphiql@0.2.16
|
||||
- @backstage/plugin-jenkins@0.5.6
|
||||
- @backstage/plugin-kafka@0.2.15
|
||||
- @backstage/plugin-kubernetes@0.4.13
|
||||
- @backstage/plugin-lighthouse@0.2.25
|
||||
- @backstage/plugin-org@0.3.23
|
||||
- @backstage/plugin-pagerduty@0.3.13
|
||||
- @backstage/plugin-rollbar@0.3.14
|
||||
- @backstage/plugin-scaffolder@0.11.4
|
||||
- @backstage/plugin-search@0.4.11
|
||||
- @backstage/plugin-sentry@0.3.21
|
||||
- @backstage/plugin-shortcuts@0.1.8
|
||||
- @backstage/plugin-tech-radar@0.4.7
|
||||
- @backstage/plugin-todo@0.1.10
|
||||
- @backstage/core-app-api@0.1.13
|
||||
- @backstage/core-plugin-api@0.1.8
|
||||
|
||||
## 0.2.45
|
||||
|
||||
### Patch Changes
|
||||
|
||||
+37
-37
@@ -1,50 +1,50 @@
|
||||
{
|
||||
"name": "example-app",
|
||||
"version": "0.2.45",
|
||||
"version": "0.2.46",
|
||||
"private": true,
|
||||
"bundled": true,
|
||||
"dependencies": {
|
||||
"@backstage/catalog-model": "^0.9.2",
|
||||
"@backstage/cli": "^0.7.11",
|
||||
"@backstage/core-app-api": "^0.1.12",
|
||||
"@backstage/core-components": "^0.4.1",
|
||||
"@backstage/core-plugin-api": "^0.1.7",
|
||||
"@backstage/integration-react": "^0.1.8",
|
||||
"@backstage/plugin-api-docs": "^0.6.7",
|
||||
"@backstage/plugin-badges": "^0.2.8",
|
||||
"@backstage/plugin-catalog": "^0.6.14",
|
||||
"@backstage/plugin-catalog-import": "^0.5.20",
|
||||
"@backstage/plugin-catalog-react": "^0.4.5",
|
||||
"@backstage/plugin-circleci": "^0.2.22",
|
||||
"@backstage/plugin-cloudbuild": "^0.2.22",
|
||||
"@backstage/plugin-code-coverage": "^0.1.10",
|
||||
"@backstage/plugin-cost-insights": "^0.11.5",
|
||||
"@backstage/plugin-explore": "^0.3.15",
|
||||
"@backstage/plugin-gcp-projects": "^0.3.3",
|
||||
"@backstage/plugin-github-actions": "^0.4.17",
|
||||
"@backstage/plugin-graphiql": "^0.2.15",
|
||||
"@backstage/plugin-home": "^0.3.0",
|
||||
"@backstage/plugin-jenkins": "^0.5.5",
|
||||
"@backstage/plugin-kafka": "^0.2.14",
|
||||
"@backstage/plugin-kubernetes": "^0.4.12",
|
||||
"@backstage/plugin-lighthouse": "^0.2.24",
|
||||
"@backstage/plugin-newrelic": "^0.3.3",
|
||||
"@backstage/plugin-org": "^0.3.22",
|
||||
"@backstage/plugin-pagerduty": "0.3.12",
|
||||
"@backstage/plugin-rollbar": "^0.3.13",
|
||||
"@backstage/plugin-scaffolder": "^0.11.3",
|
||||
"@backstage/plugin-search": "^0.4.10",
|
||||
"@backstage/plugin-sentry": "^0.3.20",
|
||||
"@backstage/plugin-shortcuts": "^0.1.7",
|
||||
"@backstage/plugin-tech-radar": "^0.4.6",
|
||||
"@backstage/plugin-techdocs": "^0.11.1",
|
||||
"@backstage/plugin-todo": "^0.1.9",
|
||||
"@backstage/plugin-user-settings": "^0.3.4",
|
||||
"@backstage/cli": "^0.7.12",
|
||||
"@backstage/core-app-api": "^0.1.13",
|
||||
"@backstage/core-components": "^0.4.2",
|
||||
"@backstage/core-plugin-api": "^0.1.8",
|
||||
"@backstage/integration-react": "^0.1.9",
|
||||
"@backstage/plugin-api-docs": "^0.6.8",
|
||||
"@backstage/plugin-badges": "^0.2.9",
|
||||
"@backstage/plugin-catalog": "^0.6.15",
|
||||
"@backstage/plugin-catalog-import": "^0.5.21",
|
||||
"@backstage/plugin-catalog-react": "^0.4.6",
|
||||
"@backstage/plugin-circleci": "^0.2.23",
|
||||
"@backstage/plugin-cloudbuild": "^0.2.23",
|
||||
"@backstage/plugin-code-coverage": "^0.1.11",
|
||||
"@backstage/plugin-cost-insights": "^0.11.6",
|
||||
"@backstage/plugin-explore": "^0.3.16",
|
||||
"@backstage/plugin-gcp-projects": "^0.3.4",
|
||||
"@backstage/plugin-github-actions": "^0.4.18",
|
||||
"@backstage/plugin-graphiql": "^0.2.16",
|
||||
"@backstage/plugin-home": "^0.4.0",
|
||||
"@backstage/plugin-jenkins": "^0.5.6",
|
||||
"@backstage/plugin-kafka": "^0.2.15",
|
||||
"@backstage/plugin-kubernetes": "^0.4.13",
|
||||
"@backstage/plugin-lighthouse": "^0.2.25",
|
||||
"@backstage/plugin-newrelic": "^0.3.4",
|
||||
"@backstage/plugin-org": "^0.3.23",
|
||||
"@backstage/plugin-pagerduty": "0.3.13",
|
||||
"@backstage/plugin-rollbar": "^0.3.14",
|
||||
"@backstage/plugin-scaffolder": "^0.11.4",
|
||||
"@backstage/plugin-search": "^0.4.11",
|
||||
"@backstage/plugin-sentry": "^0.3.21",
|
||||
"@backstage/plugin-shortcuts": "^0.1.8",
|
||||
"@backstage/plugin-tech-radar": "^0.4.7",
|
||||
"@backstage/plugin-techdocs": "^0.11.2",
|
||||
"@backstage/plugin-todo": "^0.1.10",
|
||||
"@backstage/plugin-user-settings": "^0.3.5",
|
||||
"@backstage/search-common": "^0.2.0",
|
||||
"@backstage/theme": "^0.2.10",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
"@material-ui/lab": "4.0.0-alpha.57",
|
||||
"@octokit/rest": "^18.5.3",
|
||||
"@roadiehq/backstage-plugin-buildkite": "^1.0.8",
|
||||
"@roadiehq/backstage-plugin-github-insights": "^1.1.23",
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @backstage/backend-common
|
||||
|
||||
## 0.9.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fab79adde1: Add AWS S3 Discovery Processor. Add readTree() to AwsS3UrlReader. Add ReadableArrayResponse type that implements ReadTreeResponse to use in AwsS3UrlReader's readTree()
|
||||
- f7ad3a8925: Fix Azure `readTree` and `search` handling to properly support paths.
|
||||
- 96fef17a18: Upgrade git-parse-url to v11.6.0
|
||||
- Updated dependencies
|
||||
- @backstage/integration@0.6.4
|
||||
|
||||
## 0.9.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
/// <reference types="node" />
|
||||
/// <reference types="webpack-env" />
|
||||
|
||||
import { AwsS3Integration } from '@backstage/integration';
|
||||
import { AzureIntegration } from '@backstage/integration';
|
||||
import { BitbucketIntegration } from '@backstage/integration';
|
||||
import { Config } from '@backstage/config';
|
||||
@@ -26,10 +27,36 @@ import { Readable } from 'stream';
|
||||
import { ReadCommitResult } from 'isomorphic-git';
|
||||
import { RequestHandler } from 'express';
|
||||
import { Router } from 'express';
|
||||
import { S3 } from 'aws-sdk';
|
||||
import { Server } from 'http';
|
||||
import * as winston from 'winston';
|
||||
import { Writable } from 'stream';
|
||||
|
||||
// Warning: (ae-missing-release-tag) "AwsS3UrlReader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export class AwsS3UrlReader implements UrlReader {
|
||||
constructor(
|
||||
integration: AwsS3Integration,
|
||||
deps: {
|
||||
s3: S3;
|
||||
treeResponseFactory: ReadTreeResponseFactory;
|
||||
},
|
||||
);
|
||||
// (undocumented)
|
||||
static factory: ReaderFactory;
|
||||
// (undocumented)
|
||||
read(url: string): Promise<Buffer>;
|
||||
// (undocumented)
|
||||
readTree(url: string): Promise<ReadTreeResponse>;
|
||||
// (undocumented)
|
||||
readUrl(url: string, options?: ReadUrlOptions): Promise<ReadUrlResponse>;
|
||||
// (undocumented)
|
||||
search(): Promise<SearchResponse>;
|
||||
// (undocumented)
|
||||
toString(): string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export class AzureUrlReader implements UrlReader {
|
||||
constructor(
|
||||
@@ -399,6 +426,12 @@ export type ReadTreeResponseDirOptions = {
|
||||
|
||||
// @public (undocumented)
|
||||
export interface ReadTreeResponseFactory {
|
||||
// Warning: (ae-forgotten-export) The symbol "FromReadableArrayOptions" needs to be exported by the entry point index.d.ts
|
||||
//
|
||||
// (undocumented)
|
||||
fromReadableArray(
|
||||
options: FromReadableArrayOptions,
|
||||
): Promise<ReadTreeResponse>;
|
||||
// (undocumented)
|
||||
fromTarArchive(
|
||||
options: ReadTreeResponseFactoryOptions,
|
||||
@@ -574,6 +607,4 @@ export function useHotCleanup(
|
||||
|
||||
// @public
|
||||
export function useHotMemoize<T>(_module: NodeModule, valueFactory: () => T): T;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/backend-common",
|
||||
"description": "Common functionality library for Backstage backends",
|
||||
"version": "0.9.2",
|
||||
"version": "0.9.3",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"private": false,
|
||||
@@ -33,7 +33,7 @@
|
||||
"@backstage/config": "^0.1.9",
|
||||
"@backstage/config-loader": "^0.6.8",
|
||||
"@backstage/errors": "^0.1.2",
|
||||
"@backstage/integration": "^0.6.3",
|
||||
"@backstage/integration": "^0.6.4",
|
||||
"@google-cloud/storage": "^5.8.0",
|
||||
"@octokit/rest": "^18.5.3",
|
||||
"@types/cors": "^2.8.6",
|
||||
@@ -77,7 +77,7 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.11",
|
||||
"@backstage/cli": "^0.7.12",
|
||||
"@backstage/test-utils": "^0.1.17",
|
||||
"@types/archiver": "^5.1.0",
|
||||
"@types/compression": "^1.7.0",
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Common functionality library for Backstage backends
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export * from './cache';
|
||||
export * from './config';
|
||||
export * from './database';
|
||||
|
||||
@@ -26,14 +26,16 @@ import AWSMock from 'aws-sdk-mock';
|
||||
import aws from 'aws-sdk';
|
||||
import path from 'path';
|
||||
|
||||
const treeResponseFactory = DefaultReadTreeResponseFactory.create({
|
||||
config: new ConfigReader({}),
|
||||
});
|
||||
|
||||
describe('AwsS3UrlReader', () => {
|
||||
const createReader = (config: JsonObject): UrlReaderPredicateTuple[] => {
|
||||
return AwsS3UrlReader.factory({
|
||||
config: new ConfigReader(config),
|
||||
logger: getVoidLogger(),
|
||||
treeResponseFactory: DefaultReadTreeResponseFactory.create({
|
||||
config: new ConfigReader({}),
|
||||
}),
|
||||
treeResponseFactory,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -137,6 +139,7 @@ describe('AwsS3UrlReader', () => {
|
||||
'src',
|
||||
'reading',
|
||||
'__fixtures__',
|
||||
'awsS3',
|
||||
'awsS3-mock-object.yaml',
|
||||
),
|
||||
),
|
||||
@@ -153,7 +156,7 @@ describe('AwsS3UrlReader', () => {
|
||||
}),
|
||||
),
|
||||
),
|
||||
s3,
|
||||
{ s3, treeResponseFactory },
|
||||
);
|
||||
|
||||
it('returns contents of an object in a bucket', async () => {
|
||||
@@ -188,6 +191,7 @@ describe('AwsS3UrlReader', () => {
|
||||
'src',
|
||||
'reading',
|
||||
'__fixtures__',
|
||||
'awsS3',
|
||||
'awsS3-mock-object.yaml',
|
||||
),
|
||||
),
|
||||
@@ -206,7 +210,7 @@ describe('AwsS3UrlReader', () => {
|
||||
}),
|
||||
),
|
||||
),
|
||||
s3,
|
||||
{ s3, treeResponseFactory },
|
||||
);
|
||||
|
||||
it('returns contents of an object in a bucket', async () => {
|
||||
@@ -229,4 +233,54 @@ describe('AwsS3UrlReader', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('readTree', () => {
|
||||
const object: aws.S3.Types.Object = {
|
||||
Key: 'awsS3-mock-object.yaml',
|
||||
};
|
||||
const objectList: aws.S3.ObjectList = [object];
|
||||
const output: aws.S3.Types.ListObjectsV2Output = {
|
||||
Contents: objectList,
|
||||
};
|
||||
AWSMock.setSDKInstance(aws);
|
||||
AWSMock.mock('S3', 'listObjectsV2', output);
|
||||
|
||||
AWSMock.mock(
|
||||
'S3',
|
||||
'getObject',
|
||||
Buffer.from(
|
||||
require('fs').readFileSync(
|
||||
path.resolve(
|
||||
'src',
|
||||
'reading',
|
||||
'__fixtures__',
|
||||
'awsS3',
|
||||
'awsS3-mock-object.yaml',
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
const s3 = new aws.S3();
|
||||
const awsS3UrlReader = new AwsS3UrlReader(
|
||||
new AwsS3Integration(
|
||||
readAwsS3IntegrationConfig(
|
||||
new ConfigReader({
|
||||
host: '.amazonaws.com',
|
||||
accessKeyId: 'fake-access-key',
|
||||
secretAccessKey: 'fake-secret-key',
|
||||
}),
|
||||
),
|
||||
),
|
||||
{ s3, treeResponseFactory },
|
||||
);
|
||||
it('returns contents of an object in a bucket', async () => {
|
||||
const response = await awsS3UrlReader.readTree(
|
||||
'https://test.s3.us-east-2.amazonaws.com',
|
||||
);
|
||||
const files = await response.files();
|
||||
const body = await files[0].content();
|
||||
|
||||
expect(body.toString().trim()).toBe('site_name: Test');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,6 +19,7 @@ import { CredentialsOptions } from 'aws-sdk/lib/credentials';
|
||||
import {
|
||||
ReaderFactory,
|
||||
ReadTreeResponse,
|
||||
ReadTreeResponseFactory,
|
||||
ReadUrlOptions,
|
||||
ReadUrlResponse,
|
||||
SearchResponse,
|
||||
@@ -26,6 +27,7 @@ import {
|
||||
} from './types';
|
||||
import getRawBody from 'raw-body';
|
||||
import { AwsS3Integration, ScmIntegrations } from '@backstage/integration';
|
||||
import { ListObjectsV2Output, ObjectList } from 'aws-sdk/clients/s3';
|
||||
|
||||
const parseURL = (
|
||||
url: string,
|
||||
@@ -61,7 +63,7 @@ const parseURL = (
|
||||
};
|
||||
|
||||
export class AwsS3UrlReader implements UrlReader {
|
||||
static factory: ReaderFactory = ({ config }) => {
|
||||
static factory: ReaderFactory = ({ config, treeResponseFactory }) => {
|
||||
const integrations = ScmIntegrations.fromConfig(config);
|
||||
|
||||
return integrations.awsS3.list().map(integration => {
|
||||
@@ -70,7 +72,10 @@ export class AwsS3UrlReader implements UrlReader {
|
||||
apiVersion: '2006-03-01',
|
||||
credentials: creds,
|
||||
});
|
||||
const reader = new AwsS3UrlReader(integration, s3);
|
||||
const reader = new AwsS3UrlReader(integration, {
|
||||
s3,
|
||||
treeResponseFactory,
|
||||
});
|
||||
const predicate = (url: URL) =>
|
||||
url.host.endsWith(integration.config.host);
|
||||
return { reader, predicate };
|
||||
@@ -79,7 +84,10 @@ export class AwsS3UrlReader implements UrlReader {
|
||||
|
||||
constructor(
|
||||
private readonly integration: AwsS3Integration,
|
||||
private readonly s3: S3,
|
||||
private readonly deps: {
|
||||
s3: S3;
|
||||
treeResponseFactory: ReadTreeResponseFactory;
|
||||
},
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -145,7 +153,7 @@ export class AwsS3UrlReader implements UrlReader {
|
||||
};
|
||||
}
|
||||
|
||||
const response = this.s3.getObject(params);
|
||||
const response = this.deps.s3.getObject(params);
|
||||
const buffer = await getRawBody(response.createReadStream());
|
||||
const etag = (await response.promise()).ETag;
|
||||
|
||||
@@ -158,8 +166,45 @@ export class AwsS3UrlReader implements UrlReader {
|
||||
}
|
||||
}
|
||||
|
||||
async readTree(): Promise<ReadTreeResponse> {
|
||||
throw new Error('AwsS3Reader does not implement readTree');
|
||||
async readTree(url: string): Promise<ReadTreeResponse> {
|
||||
try {
|
||||
const { path, bucket, region } = parseURL(url);
|
||||
const allObjects: ObjectList = [];
|
||||
const responses = [];
|
||||
let continuationToken: string | undefined;
|
||||
let output: ListObjectsV2Output;
|
||||
do {
|
||||
aws.config.update({ region: region });
|
||||
output = await this.deps.s3
|
||||
.listObjectsV2({
|
||||
Bucket: bucket,
|
||||
ContinuationToken: continuationToken,
|
||||
Prefix: path,
|
||||
})
|
||||
.promise();
|
||||
if (output.Contents) {
|
||||
output.Contents.forEach(contents => {
|
||||
allObjects.push(contents);
|
||||
});
|
||||
}
|
||||
continuationToken = output.NextContinuationToken;
|
||||
} while (continuationToken);
|
||||
|
||||
for (let i = 0; i < allObjects.length; i++) {
|
||||
const object = this.deps.s3.getObject({
|
||||
Bucket: bucket,
|
||||
Key: String(allObjects[i].Key),
|
||||
});
|
||||
responses.push({
|
||||
data: object.createReadStream(),
|
||||
path: String(allObjects[i].Key),
|
||||
});
|
||||
}
|
||||
|
||||
return await this.deps.treeResponseFactory.fromReadableArray(responses);
|
||||
} catch (e) {
|
||||
throw new Error(`Could not retrieve file tree from S3: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async search(): Promise<SearchResponse> {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
site_name: Test2
|
||||
@@ -18,6 +18,7 @@ export { AzureUrlReader } from './AzureUrlReader';
|
||||
export { BitbucketUrlReader } from './BitbucketUrlReader';
|
||||
export { GithubUrlReader } from './GithubUrlReader';
|
||||
export { GitlabUrlReader } from './GitlabUrlReader';
|
||||
export { AwsS3UrlReader } from './AwsS3UrlReader';
|
||||
export type {
|
||||
ReaderFactory,
|
||||
ReadTreeOptions,
|
||||
|
||||
@@ -20,9 +20,11 @@ import {
|
||||
ReadTreeResponse,
|
||||
ReadTreeResponseFactoryOptions,
|
||||
ReadTreeResponseFactory,
|
||||
FromReadableArrayOptions,
|
||||
} from '../types';
|
||||
import { TarArchiveResponse } from './TarArchiveResponse';
|
||||
import { ZipArchiveResponse } from './ZipArchiveResponse';
|
||||
import { ReadableArrayResponse } from './ReadableArrayResponse';
|
||||
|
||||
export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory {
|
||||
static create(options: { config: Config }): DefaultReadTreeResponseFactory {
|
||||
@@ -57,4 +59,10 @@ export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory {
|
||||
options.filter,
|
||||
);
|
||||
}
|
||||
|
||||
async fromReadableArray(
|
||||
options: FromReadableArrayOptions,
|
||||
): Promise<ReadTreeResponse> {
|
||||
return new ReadableArrayResponse(options, this.workDir, '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2021 The Backstage Authors
|
||||
*
|
||||
* 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 fs from 'fs-extra';
|
||||
import mockFs from 'mock-fs';
|
||||
import path, { resolve as resolvePath } from 'path';
|
||||
import { FromReadableArrayOptions } from '../types';
|
||||
import { ReadableArrayResponse } from './ReadableArrayResponse';
|
||||
|
||||
const path1 = '/file1.yaml';
|
||||
const file1 = fs.readFileSync(
|
||||
path.resolve(__filename, '../../__fixtures__/awsS3/awsS3-mock-object.yaml'),
|
||||
);
|
||||
|
||||
const path2 = '/file2.yaml';
|
||||
const file2 = fs.readFileSync(
|
||||
path.resolve(__filename, '../../__fixtures__/awsS3/awsS3-mock-object2.yaml'),
|
||||
);
|
||||
|
||||
describe('ReadableArrayResponse', () => {
|
||||
beforeEach(() => {
|
||||
mockFs({
|
||||
[path1]: file1,
|
||||
[path2]: file2,
|
||||
'/tmp': mockFs.directory(),
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mockFs.restore();
|
||||
});
|
||||
|
||||
it('should read files', async () => {
|
||||
const arr: FromReadableArrayOptions = [
|
||||
{ data: fs.createReadStream(path1), path: path1 },
|
||||
{ data: fs.createReadStream(path2), path: path2 },
|
||||
];
|
||||
|
||||
const res = new ReadableArrayResponse(arr, '/tmp', 'etag');
|
||||
const files = await res.files();
|
||||
|
||||
expect(files).toEqual([
|
||||
{ path: path1, content: expect.any(Function) },
|
||||
{ path: path2, content: expect.any(Function) },
|
||||
]);
|
||||
const contents = await Promise.all(files.map(f => f.content()));
|
||||
expect(contents.map(c => c.toString('utf8').trim())).toEqual([
|
||||
'site_name: Test',
|
||||
'site_name: Test2',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should extract entire archive into directory', async () => {
|
||||
const arr: FromReadableArrayOptions = [
|
||||
{ data: fs.createReadStream(path1), path: path1 },
|
||||
{ data: fs.createReadStream(path2), path: path2 },
|
||||
];
|
||||
|
||||
const res = new ReadableArrayResponse(arr, '/tmp', 'etag');
|
||||
const dir = await res.dir();
|
||||
|
||||
expect(fs.readFileSync(resolvePath(dir, 'file1.yaml'), 'utf8').trim()).toBe(
|
||||
'site_name: Test',
|
||||
);
|
||||
expect(fs.readFileSync(resolvePath(dir, 'file2.yaml'), 'utf8').trim()).toBe(
|
||||
'site_name: Test2',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* 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 concatStream from 'concat-stream';
|
||||
import platformPath, { basename } from 'path';
|
||||
|
||||
import getRawBody from 'raw-body';
|
||||
import fs from 'fs-extra';
|
||||
import { promisify } from 'util';
|
||||
import tar from 'tar';
|
||||
import { pipeline as pipelineCb, Readable } from 'stream';
|
||||
import {
|
||||
ReadTreeResponse,
|
||||
ReadTreeResponseFile,
|
||||
ReadTreeResponseDirOptions,
|
||||
FromReadableArrayOptions,
|
||||
} from '../types';
|
||||
|
||||
const pipeline = promisify(pipelineCb);
|
||||
|
||||
/**
|
||||
* Wraps a array of Readable objects into a tree response reader.
|
||||
*/
|
||||
export class ReadableArrayResponse implements ReadTreeResponse {
|
||||
private read = false;
|
||||
|
||||
constructor(
|
||||
private readonly stream: FromReadableArrayOptions,
|
||||
private readonly workDir: string,
|
||||
public readonly etag: string,
|
||||
) {
|
||||
this.etag = etag;
|
||||
}
|
||||
|
||||
// Make sure the input stream is only read once
|
||||
private onlyOnce() {
|
||||
if (this.read) {
|
||||
throw new Error('Response has already been read');
|
||||
}
|
||||
this.read = true;
|
||||
}
|
||||
|
||||
async files(): Promise<ReadTreeResponseFile[]> {
|
||||
this.onlyOnce();
|
||||
|
||||
const files = Array<ReadTreeResponseFile>();
|
||||
|
||||
for (let i = 0; i < this.stream.length; i++) {
|
||||
if (!this.stream[i].path.endsWith('/')) {
|
||||
files.push({
|
||||
path: this.stream[i].path,
|
||||
content: () => getRawBody(this.stream[i].data),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
async archive(): Promise<NodeJS.ReadableStream> {
|
||||
const tmpDir = await this.dir();
|
||||
|
||||
try {
|
||||
const data = await new Promise<Buffer>(async resolve => {
|
||||
await pipeline(
|
||||
tar.create({ cwd: tmpDir }, ['']),
|
||||
concatStream(resolve),
|
||||
);
|
||||
});
|
||||
return Readable.from(data);
|
||||
} finally {
|
||||
await fs.remove(tmpDir);
|
||||
}
|
||||
}
|
||||
|
||||
async dir(options?: ReadTreeResponseDirOptions): Promise<string> {
|
||||
this.onlyOnce();
|
||||
|
||||
const dir =
|
||||
options?.targetDir ??
|
||||
(await fs.mkdtemp(platformPath.join(this.workDir, 'backstage-')));
|
||||
|
||||
for (let i = 0; i < this.stream.length; i++) {
|
||||
if (!this.stream[i].path.endsWith('/')) {
|
||||
await pipeline(
|
||||
this.stream[i].data,
|
||||
fs.createWriteStream(
|
||||
platformPath.join(dir, basename(this.stream[i].path)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
@@ -183,6 +183,13 @@ export type ReadTreeResponseFactoryOptions = {
|
||||
// Filter passed on from the ReadTreeOptions
|
||||
filter?: (path: string, info?: { size: number }) => boolean;
|
||||
};
|
||||
/** @public */
|
||||
export type FromReadableArrayOptions = Array<{
|
||||
// Data in the form of a readable
|
||||
data: Readable;
|
||||
// A string containing the filepath of the data
|
||||
path: string;
|
||||
}>;
|
||||
|
||||
/** @public */
|
||||
export interface ReadTreeResponseFactory {
|
||||
@@ -192,6 +199,9 @@ export interface ReadTreeResponseFactory {
|
||||
fromZipArchive(
|
||||
options: ReadTreeResponseFactoryOptions,
|
||||
): Promise<ReadTreeResponse>;
|
||||
fromReadableArray(
|
||||
options: FromReadableArrayOptions,
|
||||
): Promise<ReadTreeResponse>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,6 +27,4 @@ export class TestDatabases {
|
||||
// (undocumented)
|
||||
supports(id: TestDatabaseId): boolean;
|
||||
}
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
|
||||
@@ -14,5 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test helpers library for Backstage backends
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export * from './database';
|
||||
export * from './util';
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# example-backend
|
||||
|
||||
## 0.2.46
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/plugin-auth-backend@0.4.0
|
||||
- @backstage/plugin-scaffolder-backend@0.15.5
|
||||
- @backstage/backend-common@0.9.3
|
||||
- @backstage/plugin-catalog-backend@0.13.8
|
||||
- @backstage/plugin-techdocs-backend@0.10.2
|
||||
- @backstage/integration@0.6.4
|
||||
- @backstage/plugin-search-backend-module-elasticsearch@0.0.4
|
||||
- example-app@0.2.46
|
||||
|
||||
## 0.2.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "example-backend",
|
||||
"version": "0.2.44",
|
||||
"version": "0.2.46",
|
||||
"main": "dist/index.cjs.js",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
@@ -27,15 +27,15 @@
|
||||
"migrate:create": "knex migrate:make -x ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/backend-common": "^0.9.1",
|
||||
"@backstage/backend-common": "^0.9.3",
|
||||
"@backstage/catalog-client": "^0.3.17",
|
||||
"@backstage/catalog-model": "^0.9.1",
|
||||
"@backstage/config": "^0.1.8",
|
||||
"@backstage/integration": "^0.6.3",
|
||||
"@backstage/integration": "^0.6.4",
|
||||
"@backstage/plugin-app-backend": "^0.3.16",
|
||||
"@backstage/plugin-auth-backend": "^0.3.24",
|
||||
"@backstage/plugin-auth-backend": "^0.4.0",
|
||||
"@backstage/plugin-badges-backend": "^0.1.9",
|
||||
"@backstage/plugin-catalog-backend": "^0.13.6",
|
||||
"@backstage/plugin-catalog-backend": "^0.13.8",
|
||||
"@backstage/plugin-code-coverage-backend": "^0.1.10",
|
||||
"@backstage/plugin-graphql-backend": "^0.1.9",
|
||||
"@backstage/plugin-jenkins-backend": "^0.1.4",
|
||||
@@ -43,19 +43,19 @@
|
||||
"@backstage/plugin-kafka-backend": "^0.2.9",
|
||||
"@backstage/plugin-proxy-backend": "^0.2.12",
|
||||
"@backstage/plugin-rollbar-backend": "^0.1.14",
|
||||
"@backstage/plugin-scaffolder-backend": "^0.15.3",
|
||||
"@backstage/plugin-scaffolder-backend": "^0.15.5",
|
||||
"@backstage/plugin-scaffolder-backend-module-rails": "^0.1.5",
|
||||
"@backstage/plugin-search-backend": "^0.2.6",
|
||||
"@backstage/plugin-search-backend-node": "^0.4.2",
|
||||
"@backstage/plugin-search-backend-module-elasticsearch": "^0.0.3",
|
||||
"@backstage/plugin-search-backend-module-elasticsearch": "^0.0.4",
|
||||
"@backstage/plugin-search-backend-module-pg": "^0.2.0",
|
||||
"@backstage/plugin-techdocs-backend": "^0.10.1",
|
||||
"@backstage/plugin-techdocs-backend": "^0.10.2",
|
||||
"@backstage/plugin-todo-backend": "^0.1.11",
|
||||
"@gitbeaker/node": "^30.2.0",
|
||||
"@octokit/rest": "^18.5.3",
|
||||
"azure-devops-node-api": "^11.0.1",
|
||||
"dockerode": "^3.2.1",
|
||||
"example-app": "^0.2.44",
|
||||
"example-app": "^0.2.46",
|
||||
"express": "^4.17.1",
|
||||
"express-promise-router": "^4.1.0",
|
||||
"express-prom-bundle": "^6.3.6",
|
||||
@@ -67,7 +67,7 @@
|
||||
"winston": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.10",
|
||||
"@backstage/cli": "^0.7.12",
|
||||
"@types/dockerode": "^3.2.1",
|
||||
"@types/express": "^4.17.6",
|
||||
"@types/express-serve-static-core": "^4.17.5"
|
||||
|
||||
@@ -14,10 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
CatalogBuilder,
|
||||
createRouter,
|
||||
} from '@backstage/plugin-catalog-backend';
|
||||
import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
|
||||
import { Router } from 'express';
|
||||
import { PluginEnvironment } from '../types';
|
||||
|
||||
@@ -25,20 +22,7 @@ export default async function createPlugin(
|
||||
env: PluginEnvironment,
|
||||
): Promise<Router> {
|
||||
const builder = await CatalogBuilder.create(env);
|
||||
const {
|
||||
entitiesCatalog,
|
||||
locationAnalyzer,
|
||||
processingEngine,
|
||||
locationService,
|
||||
} = await builder.build();
|
||||
|
||||
const { processingEngine, router } = await builder.build();
|
||||
await processingEngine.start();
|
||||
|
||||
return await createRouter({
|
||||
entitiesCatalog,
|
||||
locationAnalyzer,
|
||||
locationService,
|
||||
logger: env.logger,
|
||||
config: env.config,
|
||||
});
|
||||
return router;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,10 @@ export default async function createPlugin({
|
||||
|
||||
indexBuilder.addCollator({
|
||||
defaultRefreshIntervalSeconds: 600,
|
||||
collator: new DefaultTechDocsCollator({ discovery, logger }),
|
||||
collator: DefaultTechDocsCollator.fromConfig(config, {
|
||||
discovery,
|
||||
logger,
|
||||
}),
|
||||
});
|
||||
|
||||
// The scheduler controls when documents are gathered from collators and sent
|
||||
|
||||
@@ -140,6 +140,4 @@ export type DiscoveryApi = {
|
||||
// @public
|
||||
export const ENTITY_STATUS_CATALOG_PROCESSING_TYPE =
|
||||
'backstage.io/catalog-processing';
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/catalog-client",
|
||||
"description": "An isomorphic client for the catalog backend",
|
||||
"version": "0.3.19",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
|
||||
@@ -14,5 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An isomorphic client for the catalog backend
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export { CatalogClient } from './CatalogClient';
|
||||
export * from './types';
|
||||
|
||||
@@ -278,10 +278,9 @@ export { GroupEntityV1alpha1 };
|
||||
export const groupEntityV1alpha1Validator: KindValidator;
|
||||
|
||||
// @public (undocumented)
|
||||
export type JSONSchema = JSONSchema7 &
|
||||
{
|
||||
[key in string]?: JsonValue;
|
||||
};
|
||||
export type JSONSchema = JSONSchema7 & {
|
||||
[key in string]?: JsonValue;
|
||||
};
|
||||
|
||||
// @public
|
||||
export type KindValidator = {
|
||||
@@ -613,6 +612,4 @@ export const VIEW_URL_ANNOTATION = 'backstage.io/view-url';
|
||||
// Warnings were encountered during analysis:
|
||||
//
|
||||
// src/entity/Entity.d.ts:38:5 - (ae-incompatible-release-tags) The symbol "status" is marked as @public, but its signature references "UNSTABLE_EntityStatus" which is marked as @alpha
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/catalog-model",
|
||||
"description": "Types and validators that help describe the model of a Backstage Catalog",
|
||||
"version": "0.9.2",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Types and validators that help describe the model of a Backstage Catalog
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export * from './entity';
|
||||
export { EntityPolicies } from './EntityPolicies';
|
||||
export * from './kinds';
|
||||
|
||||
@@ -23,6 +23,4 @@ export type Paths = {
|
||||
|
||||
// @public (undocumented)
|
||||
export type ResolveFunc = (...paths: string[]) => string;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Common functionality used by cli, backend, and create-app
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export { findPaths } from './paths';
|
||||
export { isChildPath } from './isChildPath';
|
||||
export type { Paths, ResolveFunc } from './paths';
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @backstage/cli
|
||||
|
||||
## 0.7.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- d835d112fe: replace the deprecated file-loader for fonts with assets module
|
||||
- 15e324ce60: Set the default TZ (Timezone) env for the test command to be UTC so any date related tests are consistent across timezones.
|
||||
- 9f1362dcc1: Upgrade `@material-ui/lab` to `4.0.0-alpha.57`.
|
||||
|
||||
## 0.7.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/cli",
|
||||
"description": "CLI for developing Backstage plugins and apps",
|
||||
"version": "0.7.11",
|
||||
"version": "0.7.12",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -117,11 +117,11 @@
|
||||
"yn": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/backend-common": "^0.9.2",
|
||||
"@backstage/backend-common": "^0.9.3",
|
||||
"@backstage/config": "^0.1.9",
|
||||
"@backstage/core-components": "^0.4.1",
|
||||
"@backstage/core-plugin-api": "^0.1.7",
|
||||
"@backstage/core-app-api": "^0.1.12",
|
||||
"@backstage/core-components": "^0.4.2",
|
||||
"@backstage/core-plugin-api": "^0.1.8",
|
||||
"@backstage/core-app-api": "^0.1.13",
|
||||
"@backstage/dev-utils": "^0.2.9",
|
||||
"@backstage/test-utils": "^0.1.17",
|
||||
"@backstage/theme": "^0.2.10",
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* CLI for developing Backstage plugins and apps
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
import program from 'commander';
|
||||
import chalk from 'chalk';
|
||||
import { exitWithError } from './lib/errors';
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"@backstage/theme": "^{{version '@backstage/theme'}}",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
"@material-ui/lab": "4.0.0-alpha.57",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-use": "^17.2.4"
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @backstage/codemods
|
||||
|
||||
## 0.1.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.4.2
|
||||
- @backstage/core-app-api@0.1.13
|
||||
- @backstage/core-plugin-api@0.1.8
|
||||
|
||||
## 0.1.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/codemods",
|
||||
"description": "A collection of codemods for Backstage projects",
|
||||
"version": "0.1.13",
|
||||
"version": "0.1.14",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A collection of codemods for Backstage projects
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
import program from 'commander';
|
||||
import chalk from 'chalk';
|
||||
import { codemods } from './codemods';
|
||||
|
||||
@@ -73,6 +73,4 @@ export type TransformFunc<T extends number | string | boolean> = (
|
||||
visibility: ConfigVisibility;
|
||||
},
|
||||
) => T | undefined;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Config loading functionality used by Backstage backend, and CLI
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export { readEnvConfig, loadConfigSchema, mergeConfigSchemas } from './lib';
|
||||
export type {
|
||||
ConfigSchema,
|
||||
|
||||
@@ -90,6 +90,4 @@ export type JsonPrimitive = number | string | boolean | null;
|
||||
|
||||
// @public
|
||||
export type JsonValue = JsonObject | JsonArray | JsonPrimitive;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Config API used by Backstage core, backend, and CLI
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export { ConfigReader } from './reader';
|
||||
export type {
|
||||
AppConfig,
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
# @backstage/core-app-api
|
||||
|
||||
## 0.1.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 671015f132: Switch to using utilities from `@backstage/version-bridge'.
|
||||
- bd1981d609: Allow users to specify their own AppThemeProvider
|
||||
- Updated dependencies
|
||||
- @backstage/core-components@0.4.2
|
||||
- @backstage/core-plugin-api@0.1.8
|
||||
|
||||
## 0.1.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -165,6 +165,7 @@ export type AppComponents = {
|
||||
Progress: ComponentType<{}>;
|
||||
Router: ComponentType<{}>;
|
||||
ErrorBoundaryFallback: ComponentType<ErrorBoundaryFallbackProps>;
|
||||
ThemeProvider: ComponentType<{}>;
|
||||
SignInPage?: ComponentType<SignInPageProps>;
|
||||
};
|
||||
|
||||
@@ -187,10 +188,9 @@ export type AppContext = {
|
||||
// @public (undocumented)
|
||||
export type AppOptions = {
|
||||
apis?: Iterable<AnyApiFactory>;
|
||||
icons?: Partial<AppIcons> &
|
||||
{
|
||||
[key in string]: IconComponent;
|
||||
};
|
||||
icons?: Partial<AppIcons> & {
|
||||
[key in string]: IconComponent;
|
||||
};
|
||||
plugins?: BackstagePluginWithAnyOutput[];
|
||||
components?: Partial<AppComponents>;
|
||||
themes?: AppTheme[];
|
||||
@@ -641,8 +641,6 @@ export class WebStorage implements StorageApi {
|
||||
// Warnings were encountered during analysis:
|
||||
//
|
||||
// src/apis/system/ApiProvider.d.ts:9:5 - (ae-forgotten-export) The symbol "ApiProviderProps" needs to be exported by the entry point index.d.ts
|
||||
// src/app/types.d.ts:88:5 - (ae-forgotten-export) The symbol "UnknownPluginOutput" needs to be exported by the entry point index.d.ts
|
||||
// src/app/types.d.ts:99:5 - (ae-forgotten-export) The symbol "AppIcons" needs to be exported by the entry point index.d.ts
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
// src/app/types.d.ts:89:5 - (ae-forgotten-export) The symbol "UnknownPluginOutput" needs to be exported by the entry point index.d.ts
|
||||
// src/app/types.d.ts:100:5 - (ae-forgotten-export) The symbol "AppIcons" needs to be exported by the entry point index.d.ts
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/core-app-api",
|
||||
"description": "Core app API used by Backstage apps",
|
||||
"version": "0.1.12",
|
||||
"version": "0.1.13",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
@@ -29,9 +29,9 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/core-components": "^0.4.1",
|
||||
"@backstage/core-components": "^0.4.2",
|
||||
"@backstage/config": "^0.1.9",
|
||||
"@backstage/core-plugin-api": "^0.1.7",
|
||||
"@backstage/core-plugin-api": "^0.1.8",
|
||||
"@backstage/theme": "^0.2.10",
|
||||
"@backstage/version-bridge": "^0.1.0",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
@@ -45,7 +45,7 @@
|
||||
"zen-observable": "^0.8.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.7.11",
|
||||
"@backstage/cli": "^0.7.12",
|
||||
"@backstage/test-utils": "^0.1.17",
|
||||
"@backstage/test-utils-core": "^0.1.2",
|
||||
"@testing-library/jest-dom": "^5.10.1",
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
createRoutableExtension,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { generateBoundRoutes, PrivateAppImpl } from './App';
|
||||
import { AppThemeProvider } from './AppThemeProvider';
|
||||
|
||||
describe('generateBoundRoutes', () => {
|
||||
it('runs happy path', () => {
|
||||
@@ -160,6 +161,7 @@ describe('Integration Test', () => {
|
||||
Progress: () => null,
|
||||
Router: BrowserRouter,
|
||||
ErrorBoundaryFallback: () => null,
|
||||
ThemeProvider: AppThemeProvider,
|
||||
};
|
||||
|
||||
it('runs happy paths', async () => {
|
||||
|
||||
@@ -66,7 +66,6 @@ import { RoutingProvider } from '../routing/RoutingProvider';
|
||||
import { validateRoutes } from '../routing/validation';
|
||||
import { AppContextProvider } from './AppContext';
|
||||
import { AppIdentity } from './AppIdentity';
|
||||
import { AppThemeProvider } from './AppThemeProvider';
|
||||
import {
|
||||
AppComponents,
|
||||
AppConfigLoader,
|
||||
@@ -151,12 +150,14 @@ function useConfigLoader(
|
||||
noConfigNode = <BootErrorPage step="load-config" error={config.error} />;
|
||||
}
|
||||
|
||||
const { ThemeProvider } = components;
|
||||
|
||||
// Before the config is loaded we can't use a router, so exit early
|
||||
if (noConfigNode) {
|
||||
return {
|
||||
node: (
|
||||
<ApiProvider apis={ApiRegistry.from([[appThemeApiRef, appThemeApi]])}>
|
||||
<AppThemeProvider>{noConfigNode}</AppThemeProvider>
|
||||
<ThemeProvider>{noConfigNode}</ThemeProvider>
|
||||
</ApiProvider>
|
||||
),
|
||||
};
|
||||
@@ -303,10 +304,12 @@ export class PrivateAppImpl implements BackstageApp {
|
||||
return loadedConfig.node;
|
||||
}
|
||||
|
||||
const { ThemeProvider } = this.components;
|
||||
|
||||
return (
|
||||
<ApiProvider apis={this.getApiHolder()}>
|
||||
<AppContextProvider appContext={appContext}>
|
||||
<AppThemeProvider>
|
||||
<ThemeProvider>
|
||||
<RoutingProvider
|
||||
routePaths={routePaths}
|
||||
routeParents={routeParents}
|
||||
@@ -316,7 +319,7 @@ export class PrivateAppImpl implements BackstageApp {
|
||||
>
|
||||
{children}
|
||||
</RoutingProvider>
|
||||
</AppThemeProvider>
|
||||
</ThemeProvider>
|
||||
</AppContextProvider>
|
||||
</ApiProvider>
|
||||
);
|
||||
|
||||
@@ -14,10 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { renderWithEffects } from '@backstage/test-utils';
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { defaultConfigLoader, OptionallyWrapInRouter } from './createApp';
|
||||
import {
|
||||
defaultConfigLoader,
|
||||
OptionallyWrapInRouter,
|
||||
createApp,
|
||||
} from './createApp';
|
||||
|
||||
(process as any).env = { NODE_ENV: 'test' };
|
||||
const anyEnv = process.env as any;
|
||||
@@ -115,3 +120,24 @@ describe('OptionallyWrapInRouter', () => {
|
||||
expect(getByText('Test')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Optional ThemeProvider', () => {
|
||||
it('should render app with user-provided ThemeProvider', async () => {
|
||||
const components = {
|
||||
NotFoundErrorPage: () => null,
|
||||
BootErrorPage: () => null,
|
||||
Progress: () => null,
|
||||
Router: MemoryRouter,
|
||||
ErrorBoundaryFallback: () => null,
|
||||
ThemeProvider: ({ children }: PropsWithChildren<{}>) => (
|
||||
<main role="main">{children}</main>
|
||||
),
|
||||
};
|
||||
|
||||
const App = createApp({ components }).getProvider();
|
||||
|
||||
await renderWithEffects(<App />);
|
||||
|
||||
expect(screen.getByRole('main')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
useInRouterContext,
|
||||
} from 'react-router-dom';
|
||||
import { PrivateAppImpl } from './App';
|
||||
import { AppThemeProvider } from './AppThemeProvider';
|
||||
import { defaultApis } from './defaultApis';
|
||||
import { defaultAppIcons } from './icons';
|
||||
import {
|
||||
@@ -149,6 +150,7 @@ export function createApp(options?: AppOptions) {
|
||||
Progress: Progress,
|
||||
Router: BrowserRouter,
|
||||
ErrorBoundaryFallback: DefaultErrorBoundaryFallback,
|
||||
ThemeProvider: AppThemeProvider,
|
||||
...options?.components,
|
||||
};
|
||||
const themes = options?.themes ?? [
|
||||
|
||||
@@ -72,6 +72,7 @@ export type AppComponents = {
|
||||
Progress: ComponentType<{}>;
|
||||
Router: ComponentType<{}>;
|
||||
ErrorBoundaryFallback: ComponentType<ErrorBoundaryFallbackProps>;
|
||||
ThemeProvider: ComponentType<{}>;
|
||||
|
||||
/**
|
||||
* An optional sign-in page that will be rendered instead of the AppRouter at startup.
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Core app API used by Backstage apps
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
export * from './apis';
|
||||
export * from './app';
|
||||
export * from './routing';
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
# @backstage/core-components
|
||||
|
||||
## 0.4.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 60c03f69a7: Change the styling of the `<DependencyGraph>` to have more contrast in light
|
||||
mode. Nodes now have a design similar to material UI buttons.
|
||||
- 9f1362dcc1: Upgrade `@material-ui/lab` to `4.0.0-alpha.57`.
|
||||
- d9f2ff12bb: Deprecated CheckboxTree component. Deprecated the filter type `'checkbox-tree'` from the `TableFilter` types.
|
||||
- 61e9fcf406: Improve UX for Login pop-up
|
||||
- 005510dabe: remove hard coded min height in page header
|
||||
- Updated dependencies
|
||||
- @backstage/core-plugin-api@0.1.8
|
||||
|
||||
## 0.4.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1889,7 +1889,7 @@ export interface TableColumn<T extends object = {}> extends Column<T> {
|
||||
// @public (undocumented)
|
||||
export type TableFilter = {
|
||||
column: string;
|
||||
type: 'select' | 'multiple-select' | 'checkbox-tree';
|
||||
type: 'select' | 'multiple-select' | /** @deprecated */ 'checkbox-tree';
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "TableProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
@@ -1983,6 +1983,4 @@ export function WarningPanel(props: WarningProps): JSX.Element;
|
||||
// src/components/TabbedLayout/RoutedTabs.d.ts:9:5 - (ae-forgotten-export) The symbol "SubRoute" needs to be exported by the entry point index.d.ts
|
||||
// src/components/Table/Table.d.ts:15:5 - (ae-forgotten-export) The symbol "SelectedFilters" needs to be exported by the entry point index.d.ts
|
||||
// src/layout/ErrorBoundary/ErrorBoundary.d.ts:7:5 - (ae-forgotten-export) The symbol "SlackChannel" needs to be exported by the entry point index.d.ts
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@backstage/core-components",
|
||||
"description": "Core components used by Backstage plugins and apps",
|
||||
"version": "0.4.1",
|
||||
"version": "0.4.2",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
@@ -30,13 +30,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/config": "^0.1.9",
|
||||
"@backstage/core-plugin-api": "^0.1.7",
|
||||
"@backstage/core-plugin-api": "^0.1.8",
|
||||
"@backstage/errors": "^0.1.2",
|
||||
"@backstage/theme": "^0.2.10",
|
||||
"@material-table/core": "^3.1.0",
|
||||
"@material-ui/core": "^4.12.2",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
"@material-ui/lab": "4.0.0-alpha.57",
|
||||
"@testing-library/react-hooks": "^3.4.2",
|
||||
"@types/dagre": "^0.7.44",
|
||||
"@types/prop-types": "^15.7.3",
|
||||
@@ -70,8 +70,8 @@
|
||||
"zen-observable": "^0.8.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/core-app-api": "^0.1.12",
|
||||
"@backstage/cli": "^0.7.11",
|
||||
"@backstage/core-app-api": "^0.1.13",
|
||||
"@backstage/cli": "^0.7.12",
|
||||
"@backstage/test-utils": "^0.1.17",
|
||||
"@testing-library/jest-dom": "^5.10.1",
|
||||
"@testing-library/react": "^11.2.5",
|
||||
|
||||
@@ -225,6 +225,10 @@ const indexer = (
|
||||
};
|
||||
}, {});
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated CheckboxTree is no longer used in Table filters
|
||||
*/
|
||||
export function CheckboxTree(props: CheckboxTreeProps) {
|
||||
const { subCategories, label, selected, onChange, triggerReset } = props;
|
||||
const classes = useStyles();
|
||||
|
||||
@@ -53,7 +53,7 @@ const useSubvalueCellStyles = makeStyles<BackstageTheme>(theme => ({
|
||||
export type Without<T, K> = Pick<T, Exclude<keyof T, K>>;
|
||||
|
||||
export type Filter = {
|
||||
type: 'select' | 'checkbox-tree' | 'multiple-select';
|
||||
type: 'select' | /** @deprecated */ 'checkbox-tree' | 'multiple-select';
|
||||
element:
|
||||
| Without<CheckboxTreeProps, 'onChange'>
|
||||
| Without<SelectProps, 'onChange'>;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user