Merge branch 'master' into css-fix

Signed-off-by: James Brooks <jamesbrooks@spotify.com>
This commit is contained in:
James Brooks
2025-08-07 19:15:36 +01:00
79 changed files with 547 additions and 707 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-plugin-api': minor
---
**BREAKING**: Removed the deprecated `createFrontendPlugin` variant where the plugin ID is passed via an `id` option. To update existing code, switch to using the `pluginId` option instead.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend': minor
---
Fixed fs:readdir action example
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/plugin-catalog-graph': patch
'@backstage/plugin-api-docs': patch
'@backstage/plugin-org': patch
---
Updated README instructions for the new frontend system
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/repo-tools': patch
---
Removed build-in ignore of the `packages/canon` package for knip reports.
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/frontend-defaults': patch
'@backstage/frontend-app-api': patch
'@backstage/cli': patch
---
Deprecated new frontend system config setting `app.experimental.packages` to just `app.packages`. The old config will continue working for the time being, but may be removed in a future release.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/create-app': patch
---
Updated the `app.packages` config setting now that it no longer is experimental
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/frontend-plugin-api': patch
'@backstage/frontend-app-api': patch
---
Improved runtime error message clarity when extension factories don't return an iterable object.
-1
View File
@@ -28,7 +28,6 @@ yarn.lock @backstage/maintainers @backst
/microsite/static @backstage/maintainers @backstage/documentation-maintainers
/packages @backstage/framework-maintainers
/packages/backend-openapi-utils @backstage/maintainers @backstage/reviewers @backstage/openapi-tooling-maintainers
/packages/canon @backstage/design-system-maintainers
/packages/catalog-client @backstage/catalog-maintainers
/packages/catalog-model @backstage/catalog-maintainers
/packages/cli @backstage/tooling-maintainers
-4
View File
@@ -127,10 +127,6 @@ jobs:
- name: build all packages
run: yarn backstage-cli repo build --all
# For now canon has a custom build script and needs to be built separately
- name: build canon
run: yarn --cwd packages/canon build
# For now BUI has a custom build script and needs to be built separately
- name: build BUI
run: yarn --cwd packages/ui build
-4
View File
@@ -110,10 +110,6 @@ jobs:
- name: build
run: yarn backstage-cli repo build --all
# For now canon has a custom build script and needs to be built separately
- name: build canon
run: yarn --cwd packages/canon build
# For now BUI has a custom build script and needs to be built separately
- name: build BUI
run: yarn --cwd packages/ui build
+4 -4
View File
@@ -1,4 +1,4 @@
name: Sync Canon Docs
name: Sync BUI Docs
on:
push:
branches: [master]
@@ -36,7 +36,7 @@ jobs:
- name: Configure Git
run: |
git config --global user.email noreply@backstage.io
git config --global user.name 'Github Canon Docs workflow'
git config --global user.name 'Github BUI Docs workflow'
- name: Install dependencies
working-directory: docs-ui
@@ -53,9 +53,9 @@ jobs:
git rm -rf .
cp -R ../docs-ui/dist/. .
- name: Commit to canon-storybook repo
- name: Commit to bui-storybook repo
working-directory: bui-external-docs
run: |
git add .
git commit -am "Canon Docs build for backstage/backstage@${{ github.sha }}"
git commit -am "BUI Docs build for backstage/backstage@${{ github.sha }}"
git push
+1 -1
View File
@@ -40,7 +40,7 @@ These labels indicate which part of Backstage an issue or pull request relates t
- `area:auditor` - Auditor service and it's use in plugins.
- `area:auth` - Authentication and 3rd party authorization.
- `area:catalog` - The Catalog plugin and the Software Catalog model and integrations.
- `area:design-system` - The Canon design system and library.
- `area:design-system` - The Backstage UI design system and library.
- `area:documentation` - Documentation for adopters, users, and developers.
- `area:events` - The Events system and integrations for other plugins.
- `area:framework` - The core Backstage framework.
+1 -2
View File
@@ -1,8 +1,7 @@
app:
title: Backstage Example App
baseUrl: http://localhost:3000
experimental:
packages: all # ✨
packages: all # ✨
#datadogRum:
# clientToken: '123456789'
@@ -0,0 +1,77 @@
---
id: adrs-adr015
title: 'ADR015: Types and naming for element and component options'
description: Architecture Decision Record (ADR) for the proper types and naming for element and component options
---
## Context
Until now there hasn't been a clear standard for how to define options that are intended to provide JSX elements or components. This led to a mix of different patterns in public APIs, which this ADR aims to standardize.
## Decision
We will use one of the following option property names and types when defining options that are intended to provide JSX elements or components:
### Simple element
This option is used when a simple synchronous JSX element is provided. It must only be used in areas where lazy-loading is not needed.
```tsx
{
element: JSX.Element;
}
```
### Simple component
This option is used when a simple synchronous component is provided. It must only be used in areas where lazy-loading is not needed.
```tsx
{
component: (props: { ... }) => JSX.Element | null
}
```
### Async element loader
This option is used when a simple asynchronous JSX element is provided. It is the preferred option when only producing a single instance and there is no need to pass properties to the component. This format simplifies the creation of closures for passing additional properties in the loader implementation.
```tsx
{
loader: () => Promise<JSX.Element>;
}
```
### Async component loader
This option is used when a simple asynchronous component is provided. It is the preferred option when properties need to be passed to the component or multiple instance are needed, and lazy-loading is required.
```tsx
{
loader: () => Promise<(props: { ... }) => JSX.Element | null>
}
```
### Any component loader
This option is used in the same cases as the async component loader, but when the option of synchronous loading is also needed. The structure of always having the outer loader function, even in the synchronous case, makes it possible to determine the type of the loader at runtime.
```tsx
{
loader: (() => props => JSX.Element | null) | (() => Promise<props => JSX.Element | null>)
}
```
Note that when consuming this loader we'll need to unconditionally wrap it with `React.lazy`. This is because you can't delay the call to `React.lazy` until rendering, because you're not allowed to call it within a render function. This means that we can't first call the loader to check whether the returned value is a promise or not, and we must instead unconditionally wrap it with `React.lazy`. Therefore the implementation of accepting one of these loaders as an option needs to look something like this:
```tsx
const LazyComponent = React.lazy(() =>
Promise.resolve(options.loader()).then(loaded => ({ default: loaded })),
);
```
## Consequences
We will update all APIs for the new frontend system in the `@backstage/frontend-*` packages.
We will not update any of the existing APIs for the old frontend system in the `@backstage/core-*` packages.
+11 -14
View File
@@ -48,31 +48,28 @@ App feature discovery lets you automatically discover and install features provi
Because feature discovery needs to interact with the compilation process, it is only available when using the `@backstage/cli` to build your app. It is hooked into the WebPack compilation process by scanning your app package for compatible dependencies, which are then made part of the app compilation bundle.
Since the `@backstage/cli` is a more stable component than the new frontend system, feature discovery is currently marked as an experimental feature of the CLI and needs to be enabled manually. To enable it, add the following configuration to your `app-config.yaml`:
To enable frontend feature discovery, add the following configuration to your `app-config.yaml`:
```yaml
app:
experimental:
packages: all
packages: all
```
This will cause all dependencies in your app package to be installed automatically. If this is not desired, you can use include or exclude filters to narrow down the set of packages:
```yaml
app:
experimental:
packages:
# Only the following packages will be included
include:
- '@backstage/plugin-catalog'
- '@backstage/plugin-scaffolder'
packages:
# Only the following packages will be included
include:
- '@backstage/plugin-catalog'
- '@backstage/plugin-scaffolder'
---
app:
experimental:
packages:
# All but the following package will be included
exclude:
- '@backstage/plugin-catalog'
packages:
# All but the following package will be included
exclude:
- '@backstage/plugin-catalog'
```
Note that you do not need to manually exclude packages that you also import explicitly in code, since plugin instances are deduplicated by the app. You will never end up with duplicate plugin installations except if they are in fact two different plugin instances with different IDs.
@@ -244,8 +244,7 @@ Plugins don't even have to be imported manually after installing their package i
```yaml title="in app-config.yaml"
app:
# Enabling plugin and override features discovery
experimental:
packages: all # ✨
packages: all # ✨
```
### `featureFlags`
+1 -1
View File
@@ -154,7 +154,7 @@
"sloc": "^0.3.1",
"sort-package-json": "^2.8.0",
"typedoc": "^0.28.0",
"typescript": "~5.6.0"
"typescript": "~5.7.0"
},
"packageManager": "yarn@4.8.1",
"engines": {
+1 -2
View File
@@ -1,6 +1,5 @@
app:
experimental:
packages: 'all' # ✨
packages: 'all' # ✨
routes:
bindings:
+1 -5
View File
@@ -1,6 +1,6 @@
# Knip report
## Unused dependencies (30)
## Unused dependencies (26)
| Name | Location | Severity |
| :----------------------------------------------- | :----------- | :------- |
@@ -12,19 +12,15 @@
| @backstage/plugin-catalog-common | package.json | error |
| @backstage/plugin-techdocs-react | package.json | error |
| @backstage/plugin-catalog-graph | package.json | error |
| @backstage/plugin-notifications | package.json | error |
| @backstage/plugin-search-common | package.json | error |
| @backstage/plugin-search-react | package.json | error |
| @backstage/integration-react | package.json | error |
| @backstage/plugin-auth-react | package.json | error |
| @backstage/plugin-scaffolder | package.json | error |
| @backstage/frontend-app-api | package.json | error |
| @backstage/core-plugin-api | package.json | error |
| @backstage/plugin-api-docs | package.json | error |
| @backstage/plugin-catalog | package.json | error |
| @backstage/plugin-signals | package.json | error |
| @backstage/catalog-model | package.json | error |
| @backstage/plugin-search | package.json | error |
| @backstage/app-defaults | package.json | error |
| @backstage/plugin-app | package.json | error |
| @backstage/plugin-org | package.json | error |
+1 -1
View File
@@ -94,7 +94,7 @@
"@types/react": "*",
"@types/react-dom": "*",
"@types/zen-observable": "^0.8.0",
"axios": "^1.7.7",
"axios": "^1.11.0",
"cross-env": "^7.0.0",
"msw": "^1.0.0"
},
@@ -1,8 +1,17 @@
# Knip report
## Unused dependencies (1)
## Unused dependencies (10)
| Name | Location | Severity |
| :------------------------------ | :----------- | :------- |
| @backstage/plugin-search-common | package.json | error |
| Name | Location | Severity |
| :------------------------------------ | :----------- | :------- |
| @backstage/plugin-search-backend-node | package.json | error |
| @backstage/plugin-permission-common | package.json | error |
| @backstage/plugin-catalog-backend | package.json | error |
| @backstage/plugin-permission-node | package.json | error |
| @backstage/plugin-scaffolder-node | package.json | error |
| @backstage/plugin-events-backend | package.json | error |
| @backstage/plugin-search-common | package.json | error |
| @backstage/plugin-events-node | package.json | error |
| @backstage/plugin-auth-node | package.json | error |
| express-promise-router | package.json | error |
-9
View File
@@ -1,9 +0,0 @@
module.exports = {
...require('@backstage/cli/config/eslint-factory')(__dirname),
extends: ['plugin:storybook/recommended'],
rules: {
'react/forbid-elements': 'off',
'@backstage/no-mixed-plugin-imports': 'off'
},
};
-1
View File
@@ -1 +0,0 @@
css
-328
View File
@@ -1,328 +0,0 @@
# @backstage/canon
## 0.6.1-next.0
### Patch Changes
- Updated dependencies
- @backstage/ui@0.7.0-next.0
## 0.6.0
### Minor Changes
- 1d64db6: **Breaking changes** We are updating our Link component to use React Aria under the hood. To match their API we are updating the `to` prop to `href` to match both internal and external routing. We are also updating our variant naming to include all our new font sizes.
- 83fd7f4: **Breaking change** We are moving the Select component to use React Aria under the hood. We updated most props and events according to their underlying API.
- cae63df: **Breaking changes** The Tabs components has been updates to use React Aria under the hood and to work with react-router-dom directly.
- 4c6d891: **BREAKING CHANGES**
Were updating our Button component to provide better support for button links.
- Were introducing a new `ButtonLink` component, which replaces the previous render prop pattern.
- To maintain naming consistency across components, `IconButton` is being renamed to `ButtonIcon`.
- Additionally, the render prop will be removed from all button-related components.
These changes aim to simplify usage and improve clarity in our component API.
- 2e30459: We are moving our Tooltip component to use React Aria under the hood. In doing so, the structure of the component and its prop are changing to follow the new underlying structure.
- 8fd6fcb: We are renaming @backstage/canon into @backstage/ui. As part of this move we are renaming all class names and CSS variables to follow the new name. "--canon" prefix is becoming "--bui" and all component class names starting with ".canon" will now start with ".bui"
### Patch Changes
- 140f652: We are consolidating all css files into a single styles.css in Canon.
- 76255b8: Add new Card component to Canon.
- 8154fb9: Add new SearchField component in Canon
- b0a6c8e: Add new Header component to Canon.
- 6910892: Add new `RadioGroup` + `Radio` component to Canon
- 9c17305: Fix scrolling width and height on ScrollArea component in Canon.
- 390ea20: Export Card and Skeleton components.
- be76576: Improve Button, ButtonIcon and ButtonLink styling in Canon.
- 17beb9b: Update return types for Heading & Text components for React 19.
- a8a8514: We are transforming how we structure our class names and data attributes definitions for all components. They are now all set in the same place.
- 667b951: Added placeholder prop to TextField component.
- eac4a4c: Add new tertiary variant to Button, ButtonIcon and ButtonLink in Canon.
- e71333a: adding export for ButtonLink so it's importable
- 8f2e82d: Add new Skeleton component in Canon
- Updated dependencies
- @backstage/ui@0.6.0
## 0.6.0-next.1
### Minor Changes
- 2e30459: We are moving our Tooltip component to use React Aria under the hood. In doing so, the structure of the component and its prop are changing to follow the new underlying structure.
### Patch Changes
- 76255b8: Add new Card component to Canon.
- b0a6c8e: Add new Header component to Canon.
- be76576: Improve Button, ButtonIcon and ButtonLink styling in Canon.
- 17beb9b: Update return types for Heading & Text components for React 19.
- eac4a4c: Add new tertiary variant to Button, ButtonIcon and ButtonLink in Canon.
- 8f2e82d: Add new Skeleton component in Canon
## 0.6.0-next.0
### Minor Changes
- 4c6d891: **BREAKING CHANGES**
Were updating our Button component to provide better support for button links.
- Were introducing a new `ButtonLink` component, which replaces the previous render prop pattern.
- To maintain naming consistency across components, `IconButton` is being renamed to `ButtonIcon`.
- Additionally, the render prop will be removed from all button-related components.
These changes aim to simplify usage and improve clarity in our component API.
### Patch Changes
- 140f652: We are consolidating all css files into a single styles.css in Canon.
- 8154fb9: Add new SearchField component in Canon
- 6910892: Add new `RadioGroup` + `Radio` component to Canon
- a8a8514: We are transforming how we structure our class names and data attributes definitions for all components. They are now all set in the same place.
- 667b951: Added placeholder prop to TextField component.
- e71333a: adding export for ButtonLink so it's importable
## 0.5.0
### Minor Changes
- 621fac9: We are updating the default size of the Button component in Canon to be small instead of medium.
- a842554: We set the default size for IconButton in Canon to be small instead of medium.
- 35fd51d: Move TextField component to use react Aria under the hood. Introducing a new FieldLabel component to help build custom fields.
- 78204a2: **Breaking** We are adding a new as prop on the Heading and Text component to make it easier to change the component tag. We are removing the render prop in favour of the as prop.
- c49e335: TextField in Canon now has multiple label sizes as well as the capacity to hide label and description but still make them available for screen readers.
- 24b45ef: Fixes spacing props on layout components and aligned on naming for the Grid component. You should now call the Grid root component using <Grid.Root /> instead of just <Grid />.
### Patch Changes
- 44df879: Add min-width: 0; by default on every Flex components in Canon to help support truncated texts inside flex elements.
- ee6ffe6: Fix styling for the title4 prop on the Heading component in Canon.
- f2f814a: Added a render prop to the Button component in Canon to use it as a link.
- 98f02a6: Add new Switch component in Canon.
- c94f8e0: The filter input in menu comboboxes should now always use the full width of the menu it's in.
- 269316d: Remove leftover console.log from Container component.
## 0.5.0-next.2
### Patch Changes
- 44df879: Add min-width: 0; by default on every Flex components in Canon to help support truncated texts inside flex elements.
- ee6ffe6: Fix styling for the title4 prop on the Heading component in Canon.
- f2f814a: Added a render prop to the Button component in Canon to use it as a link.
## 0.5.0-next.1
### Minor Changes
- 621fac9: We are updating the default size of the Button component in Canon to be small instead of medium.
- a842554: We set the default size for IconButton in Canon to be small instead of medium.
## 0.5.0-next.0
### Minor Changes
- 24b45ef: Fixes spacing props on layout components and aligned on naming for the Grid component. You should now call the Grid root component using <Grid.Root /> instead of just <Grid />.
### Patch Changes
- 269316d: Remove leftover console.log from Container component.
## 0.4.0
### Minor Changes
- ea36f74: **Breaking Change** Icons on Button and IconButton now need to be imported and placed like this: <Button iconStart={<ChevronDownIcon />} />
- ccb1fc6: We are modifying the way we treat custom render using 'useRender()' under the hood from BaseUI.
- 04a65c6: The icon prop in TextField now accept a ReactNode instead of an icon name. We also updated the icon sizes for each input sizes.
### Patch Changes
- c8f32db: Use correct colour token for TextField clear button icon, prevent layout shift whenever it is hidden or shown and properly size focus area around it. Also stop leading icon shrinking when used together with clear button.
- e996368: Fix Canon missing dependencies
- 720033c: For improved a11y, clicking a Select component label now focuses the Select trigger element, and the TextField component's label is now styled to indicate it's interactive.
- 6189bfd: Added new icon and onClear props to the TextField to make it easier to accessorize inputs.
- 9510105: Add new Tabs component to Canon
- 97b25a1: Pin version of @base-ui-components/react.
- 206ffbe: Fixed an issue with Canon's DataTable.Pagination component showing the wrong number for the "to" count.
- 72d019d: Removed various typos
- 4551fb7: Update Menu component in Canon to make the UI more condensed. We are also adding a new Combobox option for nested navigation.
- 185d3a8: Use the Field component from Base UI within the TextField.
- 1ea1db0: Add new truncate prop to Text and Heading components in Canon.
## 0.4.0-next.3
### Patch Changes
- c8f32db: Use correct colour token for TextField clear button icon, prevent layout shift whenever it is hidden or shown and properly size focus area around it. Also stop leading icon shrinking when used together with clear button.
## 0.4.0-next.2
### Patch Changes
- 6189bfd: Added new icon and onClear props to the TextField to make it easier to accessorize inputs.
- 97b25a1: Pin version of @base-ui-components/react.
- 185d3a8: Use the Field component from Base UI within the TextField.
## 0.4.0-next.1
### Minor Changes
- ea36f74: **Breaking Change** Icons on Button and IconButton now need to be imported and placed like this: <Button iconStart={<ChevronDownIcon />} />
### Patch Changes
- 720033c: For improved a11y, clicking a Select component label now focuses the Select trigger element, and the TextField component's label is now styled to indicate it's interactive.
- 206ffbe: Fixed an issue with Canon's DataTable.Pagination component showing the wrong number for the "to" count.
- 72d019d: Removed various typos
## 0.3.2-next.0
### Patch Changes
- e996368: Fix Canon missing dependencies
## 0.3.0
### Minor Changes
- df4e292: Improve class name structure using data attributes instead of class names.
- f038613: Updated TextField and Select component to work with React Hook Form.
- 1b0cf40: Add new Select component for Canon
- 5074d61: **BREAKING**: Added a new TextField component to replace the Field and Input component. After feedback, it became clear that we needed to build a more opinionated version to avoid any problem in the future.
### Patch Changes
- 6af7b16: Updated styles for the Menu component in Canon.
- bcbc593: Fix Checkbox styles on dark theme in Canon.
- e7efb7d: Add new breakpoint helpers up(), down() and current breakpoint to help you use our breakpoints in your React components.
- f7cb538: Internal refactor and fixes to the prop extraction logic for layout components.
- 35b36ec: Add new Collapsible component for Canon.
- a47fd39: Removes instances of default React imports, a necessary update for the upcoming React 19 migration.
<https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html>
- 513477f: Add global CSS reset for anchor tags.
- 24f0e08: Improved Container styles, changing our max-width to 120rem and improving padding on smaller screens.
- 851779d: Add new Avatar component to Canon.
- ec5ebd1: Add new TableCellProfile component for Table and DataTable in Canon.
- 5e80f0b: Fix types on the Icon component.
- 0e654bf: Add new DataTable component and update Table component styles.
- 7ae28ba: Move styles to the root of the TextField component.
- 4fe5b08: We added a render prop to the Link component to make sure it can work with React Router.
- 74d463c: Fix Select styles on small sizes + with long option names in Canon.
- f25a5be: Added a new gray scale for Canon for both light and dark theme.
- 5ee4fc2: Add support for column sizing in DataTable.
- 05a5003: Fix the Icon component when the name is not found to return null instead of an empty SVG.
## 0.3.0-next.2
### Minor Changes
- f038613: Updated TextField and Select component to work with React Hook Form.
- 1b0cf40: Add new Select component for Canon
- 5074d61: **BREAKING**: Added a new TextField component to replace the Field and Input component. After feedback, it became clear that we needed to build a more opinionated version to avoid any problem in the future.
### Patch Changes
- a47fd39: Removes instances of default React imports, a necessary update for the upcoming React 19 migration.
<https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html>
- 24f0e08: Improved Container styles, changing our max-width to 120rem and improving padding on smaller screens.
- 7ae28ba: Move styles to the root of the TextField component.
- 4fe5b08: We added a render prop to the Link component to make sure it can work with React Router.
## 0.2.1-next.1
### Patch Changes
- f7cb538: Internal refactor and fixes to the prop extraction logic for layout components.
- 5e80f0b: Fix types on the Icon component.
## 0.2.1-next.0
### Patch Changes
- 6af7b16: Updated styles for the Menu component in Canon.
- 513477f: Add global CSS reset for anchor tags.
- 05a5003: Fix the Icon component when the name is not found to return null instead of an empty SVG.
## 0.2.0
### Minor Changes
- 5a5db29: Fix CSS imports and move CSS outputs out of the dist folder.
- 4557beb: Added a new Tooltip component to Canon.
- 1e4dfdb: We added a new IconButton component with fixed sizes showcasing a single icon.
- e8d12f9: Added about 40 new icons to Canon.
- 8689010: We are renaming CanonProvider to IconProvider to improve clarity on how to override icons.
- bf319b7: Added a new Menu component to Canon.
- cb7e99d: Updating styles for Text and Link components as well as global surface tokens.
- bd8520d: Added a new ScrollArea component for Canon.
### Patch Changes
- 56850ca: Fix Button types that was preventing the use of native attributes like onClick.
- 89e8686: To avoid conflicts with Backstage, we removed global styles and set font-family and font-weight for each components.
- 05e9d41: Introducing Canon to Backstage. Canon styling system is based on pure CSS. We are adding our styles.css at the top of your Backstage instance.
## 0.2.0-next.1
### Minor Changes
- 8689010: We are renaming CanonProvider to IconProvider to improve clarity on how to override icons.
### Patch Changes
- 89e8686: To avoid conflicts with Backstage, we removed global styles and set font-family and font-weight for each components.
## 0.2.0-next.0
### Minor Changes
- 5a5db29: Fix CSS imports and move CSS outputs out of the dist folder.
## 0.1.0
### Minor Changes
- 72c9800: **BREAKING**: Merged the Stack and Inline component into a single component called Flex.
- 65f4acc: This is the first alpha release for Canon. As part of this release we are introducing 5 layout components and 7 components. All theming is done through CSS variables.
- 1e4ccce: **BREAKING**: Fixing css structure and making sure that props are applying the correct styles for all responsive values.
- 8309bdb: Updated core CSS tokens and fixing the Button component accordingly.
### Patch Changes
- 989af25: Removed client directive as they are not needed in React 18.
- f44e5cf: Fix spacing props not being applied for custom values.
- 58ec9e7: Removed older versions of React packages as a preparatory step for upgrading to React 19. This commit does not introduce any functional changes, but removes dependencies on previous React versions, allowing for a cleaner upgrade path in subsequent commits.
## 0.1.0-next.2
### Minor Changes
- 8309bdb: Updated core CSS tokens and fixing the Button component accordingly.
### Patch Changes
- f44e5cf: Fix spacing props not being applied for custom values.
## 0.1.0-next.1
### Minor Changes
- 72c9800: **BREAKING**: Merged the Stack and Inline component into a single component called Flex.
- 1e4ccce: **BREAKING**: Fixing css structure and making sure that props are applying the correct styles for all responsive values.
### Patch Changes
- 989af25: Removed client directive as they are not needed in React 18.
- 58ec9e7: Removed older versions of React packages as a preparatory step for upgrading to React 19. This commit does not introduce any functional changes, but removes dependencies on previous React versions, allowing for a cleaner upgrade path in subsequent commits.
## 0.1.0-next.0
### Minor Changes
- 65f4acc: This is the first alpha release for Canon. As part of this release we are introducing 5 layout components and 7 components. All theming is done through CSS variables.
-3
View File
@@ -1,3 +0,0 @@
# @backstage/canon
Canon has been renamed to Backstage UI, replace usage of this package with `@backstage/ui`. This replacement is done automatically if you use the `versions:bump` command from the `@backstage/cli`.
-9
View File
@@ -1,9 +0,0 @@
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: backstage-canon
title: '@backstage/canon'
spec:
lifecycle: experimental
type: backstage-web-library
owner: design-system-maintainers
-43
View File
@@ -1,43 +0,0 @@
{
"name": "@backstage/canon",
"version": "0.6.1-next.0",
"backstage": {
"role": "web-library",
"moved": "@backstage/ui"
},
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
"keywords": [
"backstage"
],
"homepage": "https://canon.backstage.io",
"repository": {
"type": "git",
"url": "https://github.com/backstage/backstage",
"directory": "packages/canon"
},
"license": "Apache-2.0",
"sideEffects": true,
"main": "src/index.ts",
"types": "src/index.ts",
"files": [
"dist",
"css"
],
"scripts": {
"build": "backstage-cli package build && mkdir -p css && cp -r ../ui/css/styles.css css/styles.css",
"clean": "backstage-cli package clean",
"prepack": "backstage-cli package prepack",
"postpack": "backstage-cli package postpack"
},
"dependencies": {
"@backstage/ui": "workspace:^"
},
"devDependencies": {
"@backstage/cli": "workspace:^"
},
"deprecated": "This package has been deprecated. Please use @backstage/ui instead."
}
-7
View File
@@ -1,7 +0,0 @@
## API Report File for "@backstage/canon"
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
export * from '@backstage/ui';
```
-23
View File
@@ -1,23 +0,0 @@
/*
* Copyright 2024 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.
*/
/**
* Components used by Backstage plugins and apps
*
* @packageDocumentation
*/
export * from '@backstage/ui';
+1 -3
View File
@@ -59,12 +59,10 @@
| @rspack/dev-server | package.json | error |
| @rspack/core | package.json | error |
## Unlisted dependencies (4)
## Unlisted dependencies (2)
| Name | Location | Severity |
| :-------- | :------------------------------------------------- | :------- |
| react-dom | src/modules/build/lib/bundler/hasReactDomClient.ts | error |
| react-dom | src/modules/build/lib/bundler/config.ts | error |
| react | src/modules/build/lib/bundler/config.ts | error |
| react | src/modules/build/lib/bundler/server.ts | error |
@@ -32,7 +32,10 @@ interface PackageDetectionConfig {
function readPackageDetectionConfig(
config: Config,
): PackageDetectionConfig | undefined {
const packages = config.getOptional('app.experimental.packages');
// The experimental key is deprecated, but supported still for backwards compatibility
const packages =
config.getOptional('app.packages') ??
config.getOptional('app.experimental.packages');
if (packages === undefined || packages === null) {
return undefined;
}
@@ -40,21 +43,16 @@ function readPackageDetectionConfig(
if (typeof packages === 'string') {
if (packages !== 'all') {
throw new Error(
`Invalid app.experimental.packages mode, got '${packages}', expected 'all'`,
`Invalid app.packages mode, got '${packages}', expected 'all'`,
);
}
return {};
}
if (typeof packages !== 'object' || Array.isArray(packages)) {
throw new Error(
"Invalid config at 'app.experimental.packages', expected object",
);
throw new Error("Invalid config at 'app.packages', expected object");
}
const packagesConfig = new ConfigReader(
packages,
'app.experimental.packages',
);
const packagesConfig = new ConfigReader(packages, 'app.packages');
return {
include: packagesConfig.getOptionalStringArray('include'),
@@ -17,12 +17,8 @@
import { DismissableBanner, Props } from './DismissableBanner';
import Typography from '@material-ui/core/Typography';
import { WebStorage } from '@backstage/core-app-api';
import {
ErrorApi,
storageApiRef,
StorageApi,
} from '@backstage/core-plugin-api';
import { TestApiProvider } from '@backstage/test-utils';
import { storageApiRef, StorageApi } from '@backstage/core-plugin-api';
import { TestApiProvider, MockErrorApi } from '@backstage/test-utils';
import { Link } from '../Link';
export default {
@@ -36,11 +32,10 @@ export default {
},
};
let errorApi: ErrorApi;
const containerStyle = { width: '70%' };
const createWebStorage = (): StorageApi => {
return WebStorage.create({ errorApi });
return WebStorage.create({ errorApi: new MockErrorApi() });
};
const apis = [[storageApiRef, createWebStorage()] as const];
@@ -2,8 +2,7 @@ app:
title: Scaffolded Backstage App
baseUrl: http://localhost:3000
experimental:
packages: all
packages: all
extensions:
# Disable the nav items that we're manually rendering in packages/app/src/modules/nav/Sidebar.tsx
+17
View File
@@ -20,10 +20,27 @@ export interface Config {
/**
* @visibility frontend
* @deepVisibility frontend
* @deprecated This is no longer experimental; use `app.packages` instead.
*/
packages?: 'all' | { include?: string[]; exclude?: string[] };
};
/**
* Controls what packages are loaded by the new frontend system.
*
* @remarks
*
* When using the 'all' option, all feature packages that were added as
* dependencies to the app will be loaded automatically.
*
* The `include` and `exclude` options can be used to more finely control
* which individual package names to include or exclude.
*
* @visibility frontend
* @deepVisibility frontend
*/
packages?: 'all' | { include?: string[]; exclude?: string[] };
routes?: {
/**
* Maps external route references to regular route references. Both the
@@ -18,10 +18,13 @@ import {
AppNode,
Extension,
ExtensionDataRef,
ExtensionDefinition,
ExtensionFactoryMiddleware,
ExtensionInput,
PortableSchema,
ResolvedExtensionInput,
createExtension,
createExtensionBlueprint,
createExtensionDataRef,
createExtensionInput,
} from '@backstage/frontend-plugin-api';
@@ -957,6 +960,127 @@ describe('instantiateAppNodeTree', () => {
);
});
it('should throw if extension factories do not provide an iterable object', () => {
function createInstance(
extension: ExtensionDefinition,
middleware?: ExtensionFactoryMiddleware,
) {
return createAppNodeInstance({
extensionFactoryMiddleware: middleware,
apis: testApis,
node: makeNode(
resolveExtensionDefinition(extension, { namespace: 'test' }),
),
attachments: new Map(),
});
}
const baseOpts = {
attachTo: { id: 'ignored', input: 'ignored' },
output: [testDataRef],
};
const badFactory = () => 'not-iterable' as any;
const goodFactory = () => [testDataRef('test')];
expect(() =>
createInstance(
createExtension({
attachTo: { id: 'ignored', input: 'ignored' },
output: [testDataRef],
factory: badFactory,
}),
),
).toThrow(
`Failed to instantiate extension 'test', extension factory did not provide an iterable object`,
);
expect(() =>
createInstance(
createExtension({
...baseOpts,
factory: goodFactory,
}).override({
factory: badFactory,
}),
),
).toThrow(
`Failed to instantiate extension 'test', extension factory override did not provide an iterable object`,
);
// Bad middleware
expect(() =>
createInstance(
createExtension({
...baseOpts,
factory: goodFactory,
}),
() => 'not-iterable' as any,
),
).toThrow(
`Failed to instantiate extension 'test', extension factory middleware did not provide an iterable object`,
);
expect(() =>
createInstance(
createExtensionBlueprint({
kind: 'test',
...baseOpts,
factory: badFactory,
}).make({ params: {} }),
),
).toThrow(
`Failed to instantiate extension 'test:test', extension factory did not provide an iterable object`,
);
// Using makeWithOverrides
expect(() =>
createInstance(
createExtensionBlueprint({
kind: 'test',
...baseOpts,
factory: goodFactory,
}).makeWithOverrides({
factory: badFactory,
}),
),
).toThrow(
`Failed to instantiate extension 'test:test', extension factory did not provide an iterable object`,
);
// Using makeWithOverrides and factory middleware
expect(() =>
createInstance(
createExtensionBlueprint({
kind: 'test',
...baseOpts,
factory: goodFactory,
}).makeWithOverrides({
factory: badFactory,
}),
orig => orig(),
),
).toThrow(
`Failed to instantiate extension 'test:test', extension factory did not provide an iterable object`,
);
// Using makeWithOverrides and factory middleware
expect(() =>
createInstance(
createExtensionBlueprint({
kind: 'test',
...baseOpts,
factory: badFactory,
}).makeWithOverrides({
factory: orig => orig({ params: {} }),
}),
orig => orig(),
),
).toThrow(
`Failed to instantiate extension 'test:test', original blueprint factory did not provide an iterable object`,
);
});
it('should forward extension factory errors', () => {
expect(() =>
createAppNodeInstance({
@@ -309,11 +309,20 @@ export function createAppNodeInstance(options: {
inputs: context.inputs,
config: overrideContext?.config ?? context.config,
}),
'extension factory',
);
}, context),
'extension factory middleware',
)
: internalExtension.factory(context);
if (
typeof outputDataValues !== 'object' ||
!outputDataValues?.[Symbol.iterator]
) {
throw new Error('extension factory did not provide an iterable object');
}
const outputDataMap = new Map<string, unknown>();
for (const value of outputDataValues) {
if (outputDataMap.has(value.id)) {
@@ -373,6 +373,7 @@ function mergeExtensionFactoryMiddleware(
apis: ctx.apis,
config: ctxOverrides?.config ?? ctx.config,
}),
'extension factory middleware',
);
}, ctx);
};
@@ -1,2 +1,8 @@
# Knip report
## Unused dependencies (1)
| Name | Location | Severity |
| :--------------- | :----------- | :------- |
| @react-hookz/web | package.json | error |
@@ -27,7 +27,7 @@ Object.defineProperty(global, '__@backstage/discovered__', {
});
const config = new ConfigReader({
app: { experimental: { packages: 'all' } },
app: { packages: 'all' },
});
describe('discoverAvailableFeatures', () => {
+7 -9
View File
@@ -26,7 +26,10 @@ interface DiscoveryGlobal {
}
function readPackageDetectionConfig(config: Config) {
const packages = config.getOptional('app.experimental.packages');
// The experimental key is deprecated, but supported still for backwards compatibility
const packages =
config.getOptional('app.packages') ??
config.getOptional('app.experimental.packages');
if (packages === undefined || packages === null) {
return undefined;
}
@@ -34,21 +37,16 @@ function readPackageDetectionConfig(config: Config) {
if (typeof packages === 'string') {
if (packages !== 'all') {
throw new Error(
`Invalid app.experimental.packages mode, got '${packages}', expected 'all'`,
`Invalid app.packages mode, got '${packages}', expected 'all'`,
);
}
return {};
}
if (typeof packages !== 'object' || Array.isArray(packages)) {
throw new Error(
"Invalid config at 'app.experimental.packages', expected object",
);
throw new Error("Invalid config at 'app.packages', expected object");
}
const packagesConfig = new ConfigReader(
packages,
'app.experimental.packages',
);
const packagesConfig = new ConfigReader(packages, 'app.packages');
return {
include: packagesConfig.getOptionalStringArray('include'),
@@ -1,2 +1,8 @@
# Knip report
## Unused dependencies (1)
| Name | Location | Severity |
| :---------------- | :----------- | :------- |
| @backstage/config | package.json | error |
@@ -127,10 +127,8 @@ describe('dynamicFrontendFeaturesLoader', () => {
config: mockApis.config({
data: {
app: {
experimental: {
packages: {
include: [],
},
packages: {
include: [],
},
},
backend: {
@@ -204,10 +202,8 @@ describe('dynamicFrontendFeaturesLoader', () => {
config: mockApis.config({
data: {
app: {
experimental: {
packages: {
include: [],
},
packages: {
include: [],
},
},
backend: {
@@ -330,10 +326,8 @@ describe('dynamicFrontendFeaturesLoader', () => {
config: mockApis.config({
data: {
app: {
experimental: {
packages: {
include: [],
},
packages: {
include: [],
},
},
backend: {
@@ -447,10 +441,8 @@ describe('dynamicFrontendFeaturesLoader', () => {
config: mockApis.config({
data: {
app: {
experimental: {
packages: {
include: [],
},
packages: {
include: [],
},
},
backend: {
@@ -540,10 +532,8 @@ describe('dynamicFrontendFeaturesLoader', () => {
config: mockApis.config({
data: {
app: {
experimental: {
packages: {
include: [],
},
packages: {
include: [],
},
},
backend: {
@@ -604,10 +594,8 @@ describe('dynamicFrontendFeaturesLoader', () => {
config: mockApis.config({
data: {
app: {
experimental: {
packages: {
include: [],
},
packages: {
include: [],
},
},
backend: {
@@ -653,10 +641,8 @@ describe('dynamicFrontendFeaturesLoader', () => {
config: mockApis.config({
data: {
app: {
experimental: {
packages: {
include: [],
},
packages: {
include: [],
},
},
backend: {
@@ -759,10 +745,8 @@ describe('dynamicFrontendFeaturesLoader', () => {
config: mockApis.config({
data: {
app: {
experimental: {
packages: {
include: [],
},
packages: {
include: [],
},
},
backend: {
@@ -889,10 +873,8 @@ describe('dynamicFrontendFeaturesLoader', () => {
config: mockApis.config({
data: {
app: {
experimental: {
packages: {
include: [],
},
packages: {
include: [],
},
},
backend: {
@@ -1002,10 +984,8 @@ describe('dynamicFrontendFeaturesLoader', () => {
config: mockApis.config({
data: {
app: {
experimental: {
packages: {
include: [],
},
packages: {
include: [],
},
},
backend: {
@@ -1112,10 +1092,8 @@ describe('dynamicFrontendFeaturesLoader', () => {
config: mockApis.config({
data: {
app: {
experimental: {
packages: {
include: [],
},
packages: {
include: [],
},
},
backend: {
+1 -2
View File
@@ -1,11 +1,10 @@
# Knip report
## Unused dependencies (3)
## Unused dependencies (2)
| Name | Location | Severity |
| :------------------------ | :----------- | :------- |
| @backstage/version-bridge | package.json | error |
| @backstage/types | package.json | error |
| zod | package.json | error |
## Unused devDependencies (5)
@@ -26,8 +26,13 @@ export function createExtensionDataContainer<UData extends ExtensionDataRef>(
? ExtensionDataValue<IData, IId>
: never
>,
contextName: string,
declaredRefs?: ExtensionDataRef<any, any, any>[],
): ExtensionDataContainer<UData> {
if (typeof values !== 'object' || !values?.[Symbol.iterator]) {
throw new Error(`${contextName} did not provide an iterable object`);
}
const container = new Map<string, ExtensionDataValue<any, any>>();
const verifyRefs =
declaredRefs && new Map(declaredRefs.map(ref => [ref.id, ref]));
@@ -817,29 +817,6 @@ export function createFrontendPlugin<
MakeSortedExtensionsMap<TExtensions[number], TId>
>;
// @public @deprecated (undocumented)
export function createFrontendPlugin<
TId extends string,
TRoutes extends {
[name in string]: RouteRef | SubRouteRef;
} = {},
TExternalRoutes extends {
[name in string]: ExternalRouteRef;
} = {},
TExtensions extends readonly ExtensionDefinition[] = [],
>(
options: Omit<
PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>,
'pluginId'
> & {
id: string;
},
): FrontendPlugin<
TRoutes,
TExternalRoutes,
MakeSortedExtensionsMap<TExtensions[number], TId>
>;
// @public
export function createRouteRef<
TParams extends
@@ -448,6 +448,7 @@ export function createExtension<
) as any,
[ctxParamsSymbol as any]: innerContext?.params,
}) as Iterable<any>,
'original extension factory',
options.output,
);
},
@@ -459,6 +460,15 @@ export function createExtension<
},
);
if (
typeof parentResult !== 'object' ||
!parentResult?.[Symbol.iterator]
) {
throw new Error(
'extension factory override did not provide an iterable object',
);
}
const deduplicatedResult = new Map<
string,
ExtensionDataValue<any, any>
@@ -391,7 +391,7 @@ describe('createExtensionBlueprint', () => {
});
const mockInput = (node: string, ...data: ExtensionDataValue<any, any>[]) =>
Object.assign(createExtensionDataContainer(data), {
Object.assign(createExtensionDataContainer(data, 'mock'), {
node,
});
const mockParentInputs = {
@@ -521,6 +521,7 @@ export function createExtensionBlueprint<
) as any,
},
) as Iterable<any>,
'original blueprint factory',
options.output,
);
},
@@ -140,13 +140,6 @@ describe('createFrontendPlugin', () => {
expect(String(plugin)).toBe('Plugin{id=test}');
});
it('should create an empty plugin with deprecated id option', () => {
const plugin = createFrontendPlugin({ id: 'test' });
expect(plugin).toBeDefined();
expect(String(plugin)).toBe('Plugin{id=test}');
});
it('should create a plugin with extension instances', async () => {
const plugin = createFrontendPlugin({
pluginId: 'test',
@@ -147,49 +147,9 @@ export function createFrontendPlugin<
TRoutes,
TExternalRoutes,
MakeSortedExtensionsMap<TExtensions[number], TId>
>;
/**
* @public
* @deprecated The `id` option is deprecated, use `pluginId` instead.
*/
export function createFrontendPlugin<
TId extends string,
TRoutes extends { [name in string]: RouteRef | SubRouteRef } = {},
TExternalRoutes extends { [name in string]: ExternalRouteRef } = {},
TExtensions extends readonly ExtensionDefinition[] = [],
>(
options: Omit<
PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>,
'pluginId'
> & { id: string },
): FrontendPlugin<
TRoutes,
TExternalRoutes,
MakeSortedExtensionsMap<TExtensions[number], TId>
>;
export function createFrontendPlugin<
TId extends string,
TRoutes extends { [name in string]: RouteRef | SubRouteRef } = {},
TExternalRoutes extends { [name in string]: ExternalRouteRef } = {},
TExtensions extends readonly ExtensionDefinition[] = [],
>(
options:
| PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>
| (Omit<
PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>,
'pluginId'
> & { id: string }),
): FrontendPlugin<
TRoutes,
TExternalRoutes,
MakeSortedExtensionsMap<TExtensions[number], TId>
> {
const pluginId = 'pluginId' in options ? options.pluginId : options.id;
if (!pluginId) {
throw new Error(
"Either 'id' or 'pluginId' must be provided to createFrontendPlugin",
);
}
const pluginId = options.pluginId;
const extensions = new Array<Extension<any>>();
const extensionDefinitionsById = new Map<
string,
@@ -119,6 +119,7 @@ export function resolveInputOverrides(
if (providedData) {
const providedContainer = createExtensionDataContainer(
providedData as Iterable<ExtensionDataValue<any, any>>,
'extension input override',
declaredInput.extensionData,
);
if (!originalInput) {
@@ -157,6 +158,7 @@ export function resolveInputOverrides(
newInputs[name] = providedData.map((data, i) => {
const providedContainer = createExtensionDataContainer(
data as Iterable<ExtensionDataValue<any, any>>,
'extension input override',
declaredInput.extensionData,
);
return Object.assign(providedContainer, {
+1 -2
View File
@@ -1,6 +1,6 @@
# Knip report
## Unused dependencies (5)
## Unused dependencies (4)
| Name | Location | Severity |
| :---------------------------------- | :----------- | :------- |
@@ -8,7 +8,6 @@
| @stoplight/spectral-runtime | package.json | error |
| @electric-sql/pglite | package.json | error |
| is-glob | package.json | error |
| glob | package.json | error |
## Unused devDependencies (2)
@@ -21,11 +21,6 @@ import fs from 'fs-extra';
import type { KnipConfig } from 'knip';
import { createBinRunner } from '../util';
// Ignore these
const ignoredPackages = [
'packages/canon', // storybook config is different from the rest
];
interface KnipExtractionOptions {
packageDirs: string[];
isLocalBuild: boolean;
@@ -104,10 +99,7 @@ async function handlePackage({
isLocalBuild,
}: KnipPackageOptions) {
console.log(`## Processing ${packageDir}`);
if (ignoredPackages.includes(packageDir)) {
console.log(`Skipping ${packageDir}`);
return;
}
const fullDir = cliPaths.resolveTargetRoot(packageDir);
const reportPath = resolvePath(fullDir, 'knip-report.md');
const run = createBinRunner(cliPaths.targetRoot, '');
+2 -3
View File
@@ -64,7 +64,7 @@ export type JsonValue = JsonObject | JsonArray | JsonPrimitive;
// @public
export type Observable<T> = {
[Symbol.observable](): Observable<T>;
subscribe(observer: Observer_2<T>): Subscription;
subscribe(observer: Observer<T>): Subscription;
subscribe(
onNext?: (value: T) => void,
onError?: (error: Error) => void,
@@ -73,12 +73,11 @@ export type Observable<T> = {
};
// @public
type Observer_2<T> = {
export type Observer<T> = {
next?(value: T): void;
error?(error: Error): void;
complete?(): void;
};
export { Observer_2 as Observer };
// @public
export type Subscription = {
+20
View File
@@ -0,0 +1,20 @@
# Knip report
## Unused devDependencies (5)
| Name | Location | Severity |
| :------------------------------- | :----------- | :------- |
| @storybook/addon-styling-webpack | package.json | error |
| mini-css-extract-plugin | package.json | error |
| @storybook/blocks | package.json | error |
| globals | package.json | error |
| glob | package.json | error |
## Unlisted dependencies (3)
| Name | Location | Severity |
| :--------------------- | :----------------------------------------- | :------- |
| @react-types/overlays | src/components/Tooltip/Tooltip.stories.tsx | error |
| react-aria | src/components/Menu/Combobox.tsx | error |
| @storybook/preview-api | .storybook/preview.tsx | error |
+2 -3
View File
@@ -68,9 +68,8 @@ To link that a component provides or consumes an API, see the [`providesApis`](h
```yaml
# app-config.yaml
app:
experimental:
# Auto discovering all plugins extensions
packages: all
# Auto discovering all plugins extensions
packages: all
extensions:
# Enabling some entity cards
# The cards will be displayed in the same order it appears in this setting list
@@ -1,10 +1,11 @@
# Knip report
## Unused dependencies (1)
## Unused dependencies (2)
| Name | Location | Severity |
| :------- | :----------- | :------- |
| passport | package.json | error |
| zod | package.json | error |
## Unused devDependencies (3)
@@ -7,3 +7,9 @@
| passport | package.json | error |
| express | package.json | error |
## Unlisted dependencies (1)
| Name | Location | Severity |
| :-------------- | :------------- | :------- |
| passport-oauth2 | src/types.d.ts | error |
@@ -1,5 +1,11 @@
# Knip report
## Unused dependencies (1)
| Name | Location | Severity |
| :------------------------ | :----------- | :------- |
| @backstage/catalog-client | package.json | error |
## Unused devDependencies (1)
| Name | Location | Severity |
@@ -1,5 +1,11 @@
# Knip report
## Unused dependencies (1)
| Name | Location | Severity |
| :------------------------ | :----------- | :------- |
| @backstage/catalog-client | package.json | error |
## Unused devDependencies (1)
| Name | Location | Severity |
@@ -0,0 +1,2 @@
# Knip report
@@ -1,10 +1,11 @@
# Knip report
## Unused dependencies (1)
## Unused dependencies (2)
| Name | Location | Severity |
| :-------------------------------- | :----------- | :------- |
| @backstage/plugin-catalog-backend | package.json | error |
| @backstage/catalog-client | package.json | error |
## Unused devDependencies (1)
+18 -20
View File
@@ -36,18 +36,18 @@ This plugin installation requires the following steps:
1. Add the `@backstage/catalog-graph` dependency to your app `package.json` file and install it;
2. In your application's configuration file, enable the catalog entity relations graphic card extension so that the card begins to be presented on the catalog entity page:
```yaml
# app-config.yaml
app:
experimental:
# Auto discovering all plugins extensions
packages: all
extensions:
# This is required because the card is not enable by default once you install the plugin
- entity-card:catalog-graph/relations
```
```yaml
# app-config.yaml
app:
# Auto discovering all plugins extensions
packages: all
extensions:
# This is required because the card is not enable by default once you install the plugin
- entity-card:catalog-graph/relations
```
3. Then start the app, navigate to an entity's page and see the Relations graph there;
4. By clicking on the "View Graph" card action, you will be redirected to the catalog entity relations page.
## Customization
@@ -64,11 +64,10 @@ _Enabling auto discovering the plugin extensions in production_
# app-config.production.yaml
# Overriding configurations for the local production environment
app:
experimental:
packages:
# Only the following packages will be included
include:
- '@backstage/plugin-catalog-graph'
packages:
# Only the following packages will be included
include:
- '@backstage/plugin-catalog-graph'
```
_Disabling auto discovering the plugin extensions in development_
@@ -77,11 +76,10 @@ _Disabling auto discovering the plugin extensions in development_
# app-config.local.yaml
# Overriding configurations for the local development environment
app:
experimental:
packages:
# All but the following package will be included
exclude:
- '@backstage/plugin-catalog-graph'
packages:
# All but the following package will be included
exclude:
- '@backstage/plugin-catalog-graph'
```
For more options of package configurations, see [this](https://backstage.io/docs/frontend-system/architecture/app/#feature-discovery) documentation.
+6 -5
View File
@@ -1,9 +1,10 @@
# Knip report
## Unused dependencies (2)
## Unused dependencies (3)
| Name | Location | Severity |
| :----- | :----------- | :------- |
| semver | package.json | error |
| yn | package.json | error |
| Name | Location | Severity |
| :-------------------------------- | :----------- | :------- |
| @backstage/plugin-permission-node | package.json | error |
| semver | package.json | error |
| yn | package.json | error |
@@ -0,0 +1,2 @@
# Knip report
@@ -0,0 +1,2 @@
# Knip report
@@ -0,0 +1,2 @@
# Knip report
+2
View File
@@ -0,0 +1,2 @@
# Knip report
+6
View File
@@ -1,5 +1,11 @@
# Knip report
## Unused dependencies (1)
| Name | Location | Severity |
| :------ | :----------- | :------- |
| winston | package.json | error |
## Unused devDependencies (1)
| Name | Location | Severity |
+3 -3
View File
@@ -7,12 +7,12 @@
| @kubernetes-models/apimachinery | package.json | error |
| @kubernetes-models/base | package.json | error |
| @kubernetes/client-node | package.json | error |
| xterm-addon-attach | package.json | error |
| @xterm/addon-attach | package.json | error |
| kubernetes-models | package.json | error |
| xterm-addon-fit | package.json | error |
| @xterm/addon-fit | package.json | error |
| @xterm/xterm | package.json | error |
| cronstrue | package.json | error |
| js-yaml | package.json | error |
| lodash | package.json | error |
| luxon | package.json | error |
| xterm | package.json | error |
@@ -0,0 +1,9 @@
# Knip report
## Unused dependencies (2)
| Name | Location | Severity |
| :------------------------ | :----------- | :------- |
| @backstage/catalog-client | package.json | error |
| zod | package.json | error |
@@ -0,0 +1,17 @@
# Knip report
## Unused dependencies (2)
| Name | Location | Severity |
| :----------- | :----------- | :------- |
| @slack/types | package.json | error |
| @slack/bolt | package.json | error |
## Unused devDependencies (3)
| Name | Location | Severity |
| :-------------------- | :----------- | :------- |
| @backstage/test-utils | package.json | error |
| @faker-js/faker | package.json | error |
| msw | package.json | error |
+2 -3
View File
@@ -48,9 +48,8 @@ And below is an example of how a user page looks with the user profile and owner
```yaml
# app-config.yaml
app:
experimental:
# Auto discovering all plugins extensions
packages: all
# Auto discovering all plugins extensions
packages: all
extensions:
# Enabling the org plugin cards
- entity-card:org/group-profile
@@ -1,2 +1,8 @@
# Knip report
## Unused dependencies (1)
| Name | Location | Severity |
| :-- | :----------- | :------- |
| zod | package.json | error |
@@ -1,8 +1,2 @@
# Knip report
## Unused dependencies (1)
| Name | Location | Severity |
| :------ | :----------- | :------- |
| octokit | package.json | error |
+17 -7
View File
@@ -1,13 +1,23 @@
# Knip report
## Unused dependencies (4)
## Unused dependencies (14)
| Name | Location | Severity |
| :--------------------------------------- | :----------- | :------- |
| @backstage/plugin-bitbucket-cloud-common | package.json | error |
| concat-stream | package.json | error |
| p-limit | package.json | error |
| tar | package.json | error |
| Name | Location | Severity |
| :--------------------------------------------------------------- | :----------- | :------- |
| @backstage/plugin-catalog-backend-module-scaffolder-entity-model | package.json | error |
| @backstage/plugin-scaffolder-backend-module-bitbucket-server | package.json | error |
| @backstage/plugin-scaffolder-backend-module-bitbucket-cloud | package.json | error |
| @backstage/plugin-scaffolder-backend-module-bitbucket | package.json | error |
| @backstage/plugin-scaffolder-backend-module-gerrit | package.json | error |
| @backstage/plugin-scaffolder-backend-module-github | package.json | error |
| @backstage/plugin-scaffolder-backend-module-gitlab | package.json | error |
| @backstage/plugin-scaffolder-backend-module-azure | package.json | error |
| @backstage/plugin-scaffolder-backend-module-gitea | package.json | error |
| @backstage/plugin-bitbucket-cloud-common | package.json | error |
| @backstage/plugin-auth-node | package.json | error |
| concat-stream | package.json | error |
| p-limit | package.json | error |
| tar | package.json | error |
## Unused devDependencies (1)
@@ -18,7 +18,7 @@ import { resolveSafeChildPath } from '@backstage/backend-plugin-api';
import fs from 'fs/promises';
import path from 'path';
import { z as zod } from 'zod';
import { examples } from './rename.examples';
import { examples } from './read.examples';
const contentSchema = (z: typeof zod) =>
z.object({
+10
View File
@@ -1,2 +1,12 @@
# Knip report
## Unused dependencies (5)
| Name | Location | Severity |
| :----------------------------------------------- | :----------- | :------- |
| @backstage/plugin-search-backend-module-techdocs | package.json | error |
| @backstage/plugin-permission-common | package.json | error |
| @backstage/plugin-techdocs-common | package.json | error |
| @backstage/plugin-catalog-common | package.json | error |
| lodash | package.json | error |
+15 -24
View File
@@ -3772,15 +3772,6 @@ __metadata:
languageName: unknown
linkType: soft
"@backstage/canon@workspace:packages/canon":
version: 0.0.0-use.local
resolution: "@backstage/canon@workspace:packages/canon"
dependencies:
"@backstage/cli": "workspace:^"
"@backstage/ui": "workspace:^"
languageName: unknown
linkType: soft
"@backstage/catalog-client@npm:^1.10.2, @backstage/catalog-client@npm:^1.9.1":
version: 1.10.2
resolution: "@backstage/catalog-client@npm:1.10.2"
@@ -25697,14 +25688,14 @@ __metadata:
languageName: node
linkType: hard
"axios@npm:^1.0.0, axios@npm:^1.6.0, axios@npm:^1.7.4, axios@npm:^1.7.7, axios@npm:^1.8.3":
version: 1.10.0
resolution: "axios@npm:1.10.0"
"axios@npm:^1.0.0, axios@npm:^1.11.0, axios@npm:^1.6.0, axios@npm:^1.7.4, axios@npm:^1.8.3":
version: 1.11.0
resolution: "axios@npm:1.11.0"
dependencies:
follow-redirects: "npm:^1.15.6"
form-data: "npm:^4.0.0"
form-data: "npm:^4.0.4"
proxy-from-env: "npm:^1.1.0"
checksum: 10/d43c80316a45611fd395743e15d16ea69a95f2b7f7095f2bb12cb78f9ca0a905194a02e52a3bf4e0db9f85fd1186d6c690410644c10ecd8bb0a468e57c2040e4
checksum: 10/232df4af7a4e4e07baa84621b9cc4b0c518a757b4eacc7f635c0eb3642cb98dff347326739f24b891b3b4481b7b838c79a3a0c4819c9fbc1fc40232431b9c5dc
languageName: node
linkType: hard
@@ -31350,7 +31341,7 @@ __metadata:
"@types/react": "npm:*"
"@types/react-dom": "npm:*"
"@types/zen-observable": "npm:^0.8.0"
axios: "npm:^1.7.7"
axios: "npm:^1.11.0"
cross-env: "npm:^7.0.0"
history: "npm:^5.0.0"
msw: "npm:^1.0.0"
@@ -45900,7 +45891,7 @@ __metadata:
sloc: "npm:^0.3.1"
sort-package-json: "npm:^2.8.0"
typedoc: "npm:^0.28.0"
typescript: "npm:~5.6.0"
typescript: "npm:~5.7.0"
yaml: "npm:^2.7.0"
languageName: unknown
linkType: soft
@@ -49384,13 +49375,13 @@ __metadata:
languageName: node
linkType: hard
"typescript@npm:~5.6.0":
version: 5.6.3
resolution: "typescript@npm:5.6.3"
"typescript@npm:~5.7.0":
version: 5.7.3
resolution: "typescript@npm:5.7.3"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10/c328e418e124b500908781d9f7b9b93cf08b66bf5936d94332b463822eea2f4e62973bfb3b8a745fdc038785cb66cf59d1092bac3ec2ac6a3e5854687f7833f1
checksum: 10/6a7e556de91db3d34dc51cd2600e8e91f4c312acd8e52792f243c7818dfadb27bae677175fad6947f9c81efb6c57eb6b2d0c736f196a6ee2f1f7d57b74fc92fa
languageName: node
linkType: hard
@@ -49424,13 +49415,13 @@ __metadata:
languageName: node
linkType: hard
"typescript@patch:typescript@npm%3A~5.6.0#optional!builtin<compat/typescript>":
version: 5.6.3
resolution: "typescript@patch:typescript@npm%3A5.6.3#optional!builtin<compat/typescript>::version=5.6.3&hash=8c6c40"
"typescript@patch:typescript@npm%3A~5.7.0#optional!builtin<compat/typescript>":
version: 5.7.3
resolution: "typescript@patch:typescript@npm%3A5.7.3#optional!builtin<compat/typescript>::version=5.7.3&hash=5786d5"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10/00504c01ee42d470c23495426af07512e25e6546bce7e24572e72a9ca2e6b2e9bea63de4286c3cfea644874da1467dcfca23f4f98f7caf20f8b03c0213bb6837
checksum: 10/dc58d777eb4c01973f7fbf1fd808aad49a0efdf545528dab9b07d94fdcb65b8751742804c3057e9619a4627f2d9cc85547fdd49d9f4326992ad0181b49e61d81
languageName: node
linkType: hard