Signed-off-by: TA31OU <kyle.opperman@ing.com>
This commit is contained in:
TA31OU
2025-09-11 14:45:29 +02:00
parent c0990e2586
commit 99f7e737d6
301 changed files with 8375 additions and 583 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/cli': patch
---
Disallow import fallback of critical shared dependencies in module federation.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/config-loader': patch
---
Allow using `BACKSTAGE_ENV` for loading environment specific config files
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-defaults': patch
---
Fixed cache namespace and key prefix separator configuration to properly use configured values instead of hardcoded plugin ID. The cache manager now correctly combines the configured namespace with plugin IDs using the configured separator for Redis and Valkey. Memcache and memory store continue to use plugin ID as namespace.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend-module-puppetdb': patch
---
**BREAKING ALPHA**: The module has been moved from the `/alpha` export to the root of the package.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs': patch
---
Updated dependency `dompurify` to `^3.2.4`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs': patch
---
TechDocs page titles have been improved, especially for deeply nested pages.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-notifications': patch
---
Fixed missing app context when rendering the notifications view
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/create-app': patch
---
Bumped create-app version.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/app-defaults': minor
---
Add and configure the OpenShift authentication provider to the default APIs.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs-react': patch
---
Update to documentation regarding TechDocs redirects.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-mcp-actions-backend': patch
---
Proxy `/.well-known/oauth-authorization-server` to `/.well-known/openid-configuration` on `auth-backend` when `auth.experimentalDynamicClientRegistration.enabled` is enabled.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-auth-backend': patch
---
Implementing Dynamic Client Registration with the OIDC server. You can enable this by setting `auth.experimentalDynamicClientRegistration.enabled` in `app-config.yaml`. This is highly experimental, but feedback welcome.
+7
View File
@@ -0,0 +1,7 @@
---
'@backstage/plugin-auth-backend': patch
'@backstage/plugin-auth-react': patch
'@backstage/plugin-auth-node': patch
---
Updating plugin metadata
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-auth': minor
---
Initial publish of the `auth` frontend package
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-app-backend': patch
---
Internal update to not expose the old `createRouter`.
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-home': patch
---
Fixed race condition in CustomHomepageGrid by waiting for storage to load before rendering custom layout to prevent
rendering of the default content.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-kubernetes-backend': patch
---
Fix a bug where `getDefault` in the `kubernetesFetcherExtensionPoint` had the wrong `this` value
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-plugin-api': minor
---
Make `openshiftAuthApiRef` available in `@backstage/core-plugin-api`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs': minor
---
Adding redirect handling for TechDocs URLs that reference entities that now reference an external entity for TechDocs. Including tests and documentation.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder': patch
---
Render a TechDocs link on the Scaffolder Template List page when templates include either `backstage.io/techdocs-ref` or `backstage.io/techdocs-entity` annotations, using the shared `buildTechDocsURL` helper. Also adds tests to verify both annotations and optional `backstage.io/techdocs-entity-path` are respected.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-app': minor
---
Add implementation of OpenShift authentication provider.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend': patch
---
Prevent deadlock in catalog deferred stitching
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-user-settings': patch
---
Add the OpenShift authenticator provider to the default `user-settings` providers page.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs-backend': minor
---
Adding new entity that specifies an external entity in the techdocs-entity annotation and updates to documentation regarding TechDocs redirects.
+24 -2
View File
@@ -201,23 +201,42 @@
"@backstage/plugin-techdocs-react": "1.3.2",
"@backstage/plugin-user-settings": "0.8.25",
"@backstage/plugin-user-settings-backend": "0.3.5",
"@backstage/plugin-user-settings-common": "0.0.1"
"@backstage/plugin-user-settings-common": "0.0.1",
"@backstage/plugin-auth": "0.0.0"
},
"changesets": [
"better-eagles-tickle",
"big-cameras-turn",
"brave-bugs-know",
"brave-jars-speak",
"busy-chairs-itch",
"cold-donuts-train",
"cool-games-rescue",
"create-app-1757429965",
"curvy-sites-rhyme",
"easy-wings-turn",
"eleven-doors-down",
"eleven-doors-own",
"fine-hands-think",
"fix-select-aria-props",
"flat-colts-know",
"funny-eagles-try",
"giant-buttons-flash",
"giant-zebras-peel",
"gold-words-smoke",
"heavy-cats-unite",
"heavy-lies-listen",
"icy-camels-throw",
"itchy-moons-start",
"late-swans-press",
"legal-lemons-attend",
"lemon-terms-cheer",
"lucky-glasses-slide",
"mean-sites-cheer",
"olive-moons-burn",
"puny-books-fetch",
"quiet-papayas-mate",
"red-shrimps-fall",
"ripe-plants-pump",
"sharp-carrots-spend",
"sixty-pans-prove",
@@ -226,9 +245,12 @@
"slick-worms-drum",
"social-beers-unite",
"sweet-lemons-wonder",
"tangy-squids-film",
"tricky-buses-lead",
"warm-emus-itch",
"wet-kiwis-strive",
"whole-dingos-lay",
"yellow-dragons-float"
"yellow-dragons-float",
"young-doodles-enter"
]
}
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-components': patch
---
Dependency graph can now be opened in full screen mode
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-user-settings': patch
---
Tool-tip text correction for the Theme selection in settings page
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend': patch
---
Fixed a regression that prevented uploads greater than 100KB. Uploads up to 10MB are supported again.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs': patch
---
Support Techdocs redirect with dompurify 3.2.6+
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-react': patch
---
Fix scaffolder task log stream not having a minimum height
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-auth-backend-module-openshift-provider': minor
---
Add new `auth-backend-module-openshift-provider`. This authentication provider enables Backstage to sign in with OpenShift.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/integration': patch
---
Fixes issue with Github credentials provider which fails to match organization name if using allowedInstallationOwners
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-techdocs-addons-test-utils': minor
---
Adding catalogApiRef to test-utils to support catalog API usage by TechDocs reader page.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-plugin-api': minor
---
Make `openshiftApiRef` available to the new frontend system.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog': patch
---
Fix incorrect `defaultTarget` on `createComponentRouteRef`.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-app-api': minor
---
Add `OpenShiftAuth` helper to create default OAuth flow for OpenShift.
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-components': patch
---
update about card links style for pretty display with other language
@@ -146,6 +146,7 @@ Expedia
facto
failover
Fargate
faqs
featureful
Figma
firehydrant
@@ -460,6 +461,7 @@ subfolders
subheader
subheaders
subkey
subpage
subpath
subroutes
substring
+5
View File
@@ -209,6 +209,11 @@ scaffolder:
defaultCommitMessage: 'Initial commit'
auth:
experimentalDynamicClientRegistration:
enabled: true
allowedRedirectUriPatterns:
- cursor://*
### Add auth.keyStore.provider to more granularly control how to store JWK data when running
# the auth-backend.
#
+1
View File
@@ -34,6 +34,7 @@ Backstage comes with many common authentication providers in the core library:
- [Okta](okta/provider.md)
- [OAuth 2 Custom Proxy](oauth2-proxy/provider.md)
- [OneLogin](onelogin/provider.md)
- [OpenShift](openshift/provider.md)
- [VMware Cloud](vmware-cloud/provider.md)
These built-in providers handle the authentication flow for a particular service, including required scopes, callbacks, etc. These providers are each added to a
+130
View File
@@ -0,0 +1,130 @@
---
id: provider
title: OpenShift Authentication Provider
sidebar_label: OpenShift
description: Adding OpenShift OAuth as an authentication provider in Backstage
---
The Backstage `core-plugin-api` package comes with a OpenShift authentication
provider that can authenticate users using OpenShift OAuth.
## Use Case
This setup enables the [Kubernetes plugin](../../features/kubernetes/index.md) to access OpenShift clusters using the user's permissions,
leveraging OAuth 2.0 _On-Behalf-Of_ flow via the [Kubernetes Client Side Provider](../../features/kubernetes/authentication.md).
To make this work, the corresponding `User` entities must exist in the Backstage catalog,
and their names must match the OpenShift users.
Although the OpenShift authentication provider does not support OIDC natively,
you can still configure it for use with the Kubernetes integration by treating it as an OIDC provider
in the `KubernetesAuthProviders` configuration.
```ts title="packages/app/src/apis.ts"
import {
KubernetesAuthProviders,
kubernetesAuthProvidersApiRef,
} from '@backstage/plugin-kubernetes';
import {
googleAuthApiRef,
microsoftAuthApiRef,
openshiftAuthApiRef,
} from '@backstage/core-plugin-api';
export const apis: AnyApiFactory[] = [
// ...
createApiFactory({
api: kubernetesAuthProvidersApiRef,
deps: {
microsoftAuthApi: microsoftAuthApiRef,
googleAuthApi: googleAuthApiRef,
openshiftAuthApi: openshiftAuthApiRef,
},
factory({ microsoftAuthApi, googleAuthApi, openshiftAuthApi }) {
return new KubernetesAuthProviders({
microsoftAuthApi,
googleAuthApi,
oidcProviders: {
openshift: {
async getIdToken(_) {
return await openshiftAuthApi.getAccessToken('user:full');
},
},
},
});
},
}),
//...
];
```
:::note Note
The OpenShift auth API does **not** implement the `OpenIdConnectApi` interface. In other words, it does **not** return an ID token.
Instead, it returns an **access token**, which is used by the Kubernetes integration in place of an ID token.
This is the only functional difference from the standard OIDC-based authentication flow.
:::
## Create an OAuth client in OpenShift
Make sure that an OAuth client exists in the OpenShift cluster.
To configure the OpenShift integration, create an [`OAuthClient`](https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/authentication_and_authorization/configuring-oauth-clients).
The redirect URI must be in the following format: `https://<fqdn>/api/auth/openshift/handler/frame`.
## Configuration
The provider configuration can then be added to your `app-config.yaml` under the
root `auth` configuration:
```yaml
auth:
environment: development
providers:
openshift:
development:
clientId: ${AUTH_OPENSHIFT_CLIENT_ID}
clientSecret: ${AUTH_OPENSHIFT_CLIENT_SECRET}
authorizationUrl: ${AUTH_OPENSHIFT_AUTHORIZATION_URL}
tokenUrl: ${AUTH_OPENSHIFT_TOKEN_URL}
openshiftApiServerUrl: ${OPENSHIFT_API_SERVER_URL}
## uncomment to set lifespan of user session
# sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code
# sessionDuration: 1d
signIn:
resolvers:
- resolver: displayNameMatchingUserEntityName
```
The OpenShift provider is a structure with these configuration keys:
- `clientId`: The client ID of your OpenShift OAuth client, e.g., `my-backstage`
- `clientSecret`: The client secret tied to the OpenShift OAuth client.
- `authorizationUrl`: The OpenShift OAuth client auth endpoint, format: `https://<oauth-client-route>/oauth/authorize`.
- `tokenUrl`: The OpenShift OAuth client token endpoint, format: `https://<oauth-client-route>/oauth/token`.
- `openshiftApiServerUrl`: The OpenShift API server endpoint, format: `https://<openshift-api>`.
- `sessionDuration`: (optional): Lifespan of the user session.
- `signIn`: The configuration for the sign-in process, including the **resolvers**
that should be used to match the user from the auth provider with the user
entity in the Backstage catalog (typically a single resolver is sufficient).
The provider needs to use the scope **user:full**.
## Backend Installation
To add the provider to the backend we will first need to install the package by running this command:
```bash title="from your Backstage root directory"
yarn --cwd packages/backend add @backstage/plugin-auth-backend-module-openshift-provider
```
Then we will need to add this line:
```ts title="in packages/backend/src/index.ts"
backend.add(import('@backstage/plugin-auth-backend'));
/* highlight-add-start */
backend.add(import('@backstage/plugin-auth-backend-module-openshift-provider'));
/* highlight-add-end */
```
@@ -45,7 +45,7 @@ When an action is executed, it receives a context object (`ActionsRegistryAction
Here's an example of how to register an action with the Actions Registry Service:
```typescript
import { ActionsRegistryService } from '@backstage/backend-plugin-api';
import { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha';
export function registerMyActions(actionsRegistry: ActionsRegistryService) {
// Register a simple read-only action
@@ -7,6 +7,39 @@ description: Documentation for the Cache service
This service lets your plugin interact with a cache. It is bound to your plugin too, so that you will only set and get values in your plugin's private namespace.
## Configuration
The cache service can be configured using the `backend.cache` section in your `app-config.yaml`:
```yaml
backend:
cache:
store: redis # or 'valkey', 'memcache', 'memory'
connection: redis://localhost:6379
# Store-specific configuration (Redis/Valkey only)
redis:
client:
# Optional: Global namespace prefix for all cache keys
namespace: 'my-app'
# Optional: Separator used between namespace and plugin ID (default: ':')
keyPrefixSeparator: ':'
# Other Redis-specific options...
clearBatchSize: 1000
useUnlink: false
```
### Namespace Configuration
For Redis and Valkey stores, you can configure a global namespace that will be prefixed to all cache keys:
- **Without namespace**: Cache keys use only the plugin ID (e.g., `catalog:some-key`)
- **With namespace**: Cache keys use the format `namespace:pluginId:key` (e.g., `my-app:catalog:some-key`)
The `keyPrefixSeparator` controls what character is used between the namespace and plugin ID (defaults to `:`).
**Note**: Memory and Memcache stores do not support namespace configuration and will always use the plugin ID directly.
## Using the service
The following example shows how to get a cache client in your `example` backend plugin and setting and getting values from the cache.
+18 -4
View File
@@ -16,10 +16,24 @@ allowing for customization.
## Supplying Configuration
Configuration is stored in YAML files where the defaults are `app-config.yaml`
and `app-config.local.yaml` for local overrides. Other sets of files can by
loaded by passing `--config <path>` flags. The configuration files themselves
contain plain YAML, but with support for loading in data and secrets from
various sources using for example `$env` and `$file` keys.
and `app-config.local.yaml` for local overrides. Additionally, it is possible
to define environment based configuration files with `BACKSTAGE_ENV`
environment variable, which will load `app-config.<BACKSTAGE_ENV>.yaml`.
Loading order of these files is as follows:
1. `app-config.yaml`
2. `app-config.<BACKSTAGE_ENV>.yaml`
3. `app-config.local.yaml`
4. `app-config.<BACKSTAGE_ENV>.local.yaml`
Other sets of files can by loaded by passing `--config <path>` flags.
Read more about the configuration loading order in the
[Configuration Files](./writing.md#configuration-files) section.
The configuration files themselves contain plain YAML, but with support for
loading in data and secrets from various sources using for example
`$env` and `$file` keys.
It is also possible to supply configuration through environment variables, for
example `APP_CONFIG_app_baseUrl=https://staging.example.com`. However these
-4
View File
@@ -221,7 +221,3 @@ future.
- [`catalog-info.yaml`](https://github.com/backstage/backstage/tree/master/catalog-info.yaml) -
Description of Backstage in the Backstage Entity format.
- [`lerna.json`](https://github.com/backstage/backstage/tree/master/lerna.json) -
[Lerna](https://github.com/lerna/lerna) monorepo config. We are using
`yarn workspaces`, so this will only be used for executing scripts.
@@ -126,7 +126,7 @@ metadata:
The value of this annotation informs of the path to this component's TechDocs within an external entity that owns the TechDocs.
In conjunction with [backstage.io/techdocs-entity](#backstageiotechdocs-entity) this allows for deep linking into the TechDocs of
another entity, not just linking to the root of another entities TechDocs.
another entity, not just linking to the root of another entity's TechDocs.
### backstage.io/view-url, backstage.io/edit-url
+6
View File
@@ -12,6 +12,8 @@ This page answers frequently asked questions about [TechDocs](README.md).
- [What static site generator is TechDocs using?](#what-static-site-generator-is-techdocs-using)
- [What is the mkdocs-techdocs-core plugin?](#what-is-the-mkdocs-techdocs-core-plugin)
- [Does TechDocs support file formats other than Markdown (e.g. RST, AsciiDoc)?](#does-techdocs-support-file-formats-other-than-markdown-eg-rst-asciidoc-)
- [What should be the value of `backstage.io/techdocs-ref` when using external build and storage?](#what-should-be-the-value-of-backstageiotechdocs-ref-when-using-external-build-and-storage)
- [Is it possible for users to suggest changes or provide feedback on a TechDocs page?](#is-it-possible-for-users-to-suggest-changes-or-provide-feedback-on-a-techdocs-page)
#### What static site generator is TechDocs using?
@@ -46,6 +48,10 @@ annotation should still be present in entity descriptor file (e.g.
`catalog-info.yaml`) for Backstage to know that TechDocs is enabled for the
entity.
#### What happens when you navigate to a TechDocs URL for an entity uses the `backstage.io/techdocs-entity` annotation?
If you navigate to a TechDocs URL in the format `docs/{namespace}/{kind}/{name}` for an entity that has the `backstage.io/techdocs-entity` annotation (instead of the `backstage.io/techdocs-ref` annotation), then Backstage will redirect to the TechDocs page of the entity referenced in the value of that annotation.
#### Is it possible for users to suggest changes or provide feedback on a TechDocs page?
This is supported for TechDocs sites whose source code is hosted in either
@@ -185,7 +185,7 @@ export const examplePlugin = createFrontendPlugin({
## Plugin specific extensions
There are many different plugins that you can extend with additional functionality through extensions. One such plugin is [the catalog plugin](../../features/software-catalog/), one of the core features of Backstage. It lets you catalog the software in your organization, where each item in the catalog has its own page that can be populated with tools and information relating to that catalog entity. In this example we will explore how our plugin can provide such a tool to display on an entity page.
There are many different plugins that you can extend with additional functionality through extensions. One such plugin is [the catalog plugin](https://backstage.io/docs/features/software-catalog/), one of the core features of Backstage. It lets you catalog the software in your organization, where each item in the catalog has its own page that can be populated with tools and information relating to that catalog entity. In this example we will explore how our plugin can provide such a tool to display on an entity page.
```tsx title="in src/plugin.ts - An example entity content extension"
import { EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha';
+5 -5
View File
@@ -31,7 +31,7 @@ This guide also assumes a basic understanding of working on a Linux based operat
[Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/)
- A GNU-like build environment available at the command line.
For example, on Debian/Ubuntu you will want to have the `make` and `build-essential` packages installed.
On macOS, you will want to have run `xcode-select --install` to get the XCode command line build tooling in place.
On macOS, you will want to run `xcode-select --install` to get the XCode command line build tooling in place.
- An account with elevated rights to install the dependencies
- `curl` or `wget` installed
- Node.js [Active LTS Release](../overview/versioning-policy.md#nodejs-releases) installed using one of these
@@ -58,9 +58,9 @@ The Backstage app we'll be creating will only have demo data until we set up int
:::
To install the Backstage Standalone app, we will make use of `npx`. `npx` is a tool that comes preinstalled with Node.js and lets you run commands straight from `npm` or other registries. Before we jump in to running the command, let's chat about what it does.
To install the Backstage Standalone app, we will make use of `npx`. `npx` is a tool that comes preinstalled with Node.js and lets you run commands straight from `npm` or other registries. Before we run the command, let's discuss what it does.
This command will create a new directory with a Backstage app inside. The wizard will ask you for the name of the app. This name will be created as sub directory in your current working directory.
This command will create a new directory with a Backstage app inside. The wizard will ask you for the name of the app. This name will be created as subdirectory in your current working directory.
![create app](../assets/getting-started/create-app-output.png)
@@ -89,8 +89,8 @@ app
- **package.json**: Root package.json for the project. _Note: Be sure that you
don't add any npm dependencies here as they probably should be installed in
the intended workspace rather than in the root._
- **packages/**: Lerna leaf packages or "workspaces". Everything here is going
to be a separate package, managed by lerna.
- **packages/**: Yarn workspaces, everything here is going
to be a separate package, managed by Yarn.
- **packages/app/**: A fully functioning Backstage frontend app that acts as a
good starting point for you to get to know Backstage.
- **packages/backend/**: We include a backend that helps power features such as
+1 -1
View File
@@ -208,7 +208,7 @@ One of the [packages](#package) within a [monorepo](#monorepo). A package may or
1. A single repository for a collection of related software projects, such as all projects belonging to an organization.
2. A project layout that consists of multiple [packages](#package) within a single project, where packages are able to have local dependencies on each other. Often enabled through tooling such as [lerna](https://lerna.js.org/) and [yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/)
2. A project layout that consists of multiple [packages](#package) within a single project, where packages are able to have local dependencies on each other. Often enabled through tooling such as [yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/)
## Name
+695
View File
@@ -0,0 +1,695 @@
# Release v1.43.0-next.2
Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.43.0-next.2](https://backstage.github.io/upgrade-helper/?to=1.43.0-next.2)
## @backstage/catalog-client@1.12.0-next.0
### Minor Changes
- 0e9ec44: Introduced new `streamEntities` async generator method for the catalog.
Catalog API and Catalog Service now includes a `streamEntities` method that allows for streaming entities from the catalog.
This method is designed to handle large datasets efficiently by processing entities in a stream rather than loading them
all into memory at once. This is useful when you need to fetch a large number of entities but do not want to use pagination
or fetch all entities at once.
Example usage:
```ts
const pageStream = catalogClient.streamEntities({ pageSize: 100 }, { token });
for await (const page of pageStream) {
// Handle page of entities
for (const entity of page) {
console.log(entity);
}
}
```
## @backstage/plugin-auth@0.1.0-next.0
### Minor Changes
- 54ddfef: Initial publish of the `auth` frontend package
### Patch Changes
- Updated dependencies
- @backstage/core-components@0.17.6-next.1
## @backstage/plugin-catalog-node@1.19.0-next.1
### Minor Changes
- 0e9ec44: Introduced new `streamEntities` async generator method for the catalog.
Catalog API and Catalog Service now includes a `streamEntities` method that allows for streaming entities from the catalog.
This method is designed to handle large datasets efficiently by processing entities in a stream rather than loading them
all into memory at once. This is useful when you need to fetch a large number of entities but do not want to use pagination
or fetch all entities at once.
Example usage:
```ts
const pageStream = catalogClient.streamEntities({ pageSize: 100 }, { token });
for await (const page of pageStream) {
// Handle page of entities
for (const entity of page) {
console.log(entity);
}
}
```
### Patch Changes
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
## @backstage/plugin-catalog-react@1.21.0-next.2
### Minor Changes
- 0e9ec44: Introduced new `streamEntities` async generator method for the catalog.
Catalog API and Catalog Service now includes a `streamEntities` method that allows for streaming entities from the catalog.
This method is designed to handle large datasets efficiently by processing entities in a stream rather than loading them
all into memory at once. This is useful when you need to fetch a large number of entities but do not want to use pagination
or fetch all entities at once.
Example usage:
```ts
const pageStream = catalogClient.streamEntities({ pageSize: 100 }, { token });
for await (const page of pageStream) {
// Handle page of entities
for (const entity of page) {
console.log(entity);
}
}
```
### Patch Changes
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
- @backstage/core-components@0.17.6-next.1
- @backstage/core-compat-api@0.5.2-next.2
## @backstage/backend-defaults@0.12.1-next.1
### Patch Changes
- 4eda590: Fixed cache namespace and key prefix separator configuration to properly use configured values instead of hardcoded plugin ID. The cache manager now correctly combines the configured namespace with plugin IDs using the configured separator for Redis and Valkey. Memcache and memory store continue to use plugin ID as namespace.
- Updated dependencies
- @backstage/config-loader@1.10.3-next.0
- @backstage/plugin-auth-node@0.6.7-next.1
- @backstage/integration@1.18.0-next.0
- @backstage/integration-aws-node@0.1.17
## @backstage/backend-dynamic-feature-service@0.7.4-next.1
### Patch Changes
- Updated dependencies
- @backstage/config-loader@1.10.3-next.0
- @backstage/backend-defaults@0.12.1-next.1
- @backstage/plugin-auth-node@0.6.7-next.1
- @backstage/plugin-catalog-backend@3.0.2-next.1
- @backstage/plugin-app-node@0.1.37-next.1
## @backstage/cli@0.34.2-next.2
### Patch Changes
- Updated dependencies
- @backstage/config-loader@1.10.3-next.0
- @backstage/integration@1.18.0-next.0
## @backstage/config-loader@1.10.3-next.0
### Patch Changes
- a73f495: Allow using `BACKSTAGE_ENV` for loading environment specific config files
## @backstage/core-compat-api@0.5.2-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-react@1.21.0-next.2
## @backstage/core-components@0.17.6-next.1
### Patch Changes
- 1ad3d94: Dependency graph can now be opened in full screen mode
- ae7d426: update about card links style for pretty display with other language
## @backstage/create-app@0.7.4-next.2
### Patch Changes
- Bumped create-app version.
## @backstage/dev-utils@1.1.14-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
## @backstage/repo-tools@0.15.2-next.1
### Patch Changes
- Updated dependencies
- @backstage/config-loader@1.10.3-next.0
## @backstage/ui@0.7.1-next.0
### Patch Changes
- 7307930: Add missing class for flex: baseline
- 89da341: Fix Select component to properly attach aria-label and aria-labelledby props to the rendered element for improved accessibility.
## @backstage/plugin-api-docs@0.12.11-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/plugin-catalog@1.31.3-next.2
- @backstage/core-compat-api@0.5.2-next.2
## @backstage/plugin-app-backend@0.5.6-next.1
### Patch Changes
- afd368e: Internal update to not expose the old `createRouter`.
- Updated dependencies
- @backstage/config-loader@1.10.3-next.0
- @backstage/plugin-auth-node@0.6.7-next.1
- @backstage/plugin-app-node@0.1.37-next.1
## @backstage/plugin-app-node@0.1.37-next.1
### Patch Changes
- Updated dependencies
- @backstage/config-loader@1.10.3-next.0
## @backstage/plugin-auth-backend@0.25.4-next.1
### Patch Changes
- 1d47bf3: Implementing Dynamic Client Registration with the OIDC server. You can enable this by setting `auth.experimentalDynamicClientRegistration.enabled` in `app-config.yaml`. This is highly experimental, but feedback welcome.
- 54ddfef: Updating plugin metadata
- Updated dependencies
- @backstage/plugin-auth-node@0.6.7-next.1
- @backstage/plugin-catalog-node@1.19.0-next.1
## @backstage/plugin-auth-node@0.6.7-next.1
### Patch Changes
- 54ddfef: Updating plugin metadata
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
## @backstage/plugin-auth-react@0.1.19-next.1
### Patch Changes
- 54ddfef: Updating plugin metadata
- Updated dependencies
- @backstage/core-components@0.17.6-next.1
## @backstage/plugin-catalog@1.31.3-next.2
### Patch Changes
- 85c5e04: Fix incorrect `defaultTarget` on `createComponentRouteRef`.
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/core-compat-api@0.5.2-next.2
## @backstage/plugin-catalog-backend@3.0.2-next.1
### Patch Changes
- 2204f5b: Prevent deadlock in catalog deferred stitching
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration@1.18.0-next.0
## @backstage/plugin-catalog-backend-module-aws@0.4.15-next.1
### Patch Changes
- Updated dependencies
- @backstage/backend-defaults@0.12.1-next.1
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration@1.18.0-next.0
- @backstage/integration-aws-node@0.1.17
## @backstage/plugin-catalog-backend-module-azure@0.3.9-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration@1.18.0-next.0
## @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.6-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-node@1.19.0-next.1
## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.5.3-next.1
### Patch Changes
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration@1.18.0-next.0
## @backstage/plugin-catalog-backend-module-bitbucket-server@0.5.3-next.1
### Patch Changes
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration@1.18.0-next.0
## @backstage/plugin-catalog-backend-module-gcp@0.3.12-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-node@1.19.0-next.1
## @backstage/plugin-catalog-backend-module-gerrit@0.3.6-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration@1.18.0-next.0
## @backstage/plugin-catalog-backend-module-gitea@0.1.4-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration@1.18.0-next.0
## @backstage/plugin-catalog-backend-module-github@0.11.0-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-backend@3.0.2-next.1
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration@1.18.0-next.0
## @backstage/plugin-catalog-backend-module-github-org@0.3.14-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/plugin-catalog-backend-module-github@0.11.0-next.1
## @backstage/plugin-catalog-backend-module-gitlab@0.7.3-next.1
### Patch Changes
- Updated dependencies
- @backstage/backend-defaults@0.12.1-next.1
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration@1.18.0-next.0
## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.13-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/plugin-catalog-backend-module-gitlab@0.7.3-next.1
## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.7.4-next.1
### Patch Changes
- Updated dependencies
- @backstage/backend-defaults@0.12.1-next.1
- @backstage/plugin-catalog-backend@3.0.2-next.1
- @backstage/plugin-catalog-node@1.19.0-next.1
## @backstage/plugin-catalog-backend-module-ldap@0.11.9-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-node@1.19.0-next.1
## @backstage/plugin-catalog-backend-module-msgraph@0.8.0-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-node@1.19.0-next.1
## @backstage/plugin-catalog-backend-module-openapi@0.2.14-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration@1.18.0-next.0
## @backstage/plugin-catalog-backend-module-puppetdb@0.2.14-next.1
### Patch Changes
- afd368e: **BREAKING ALPHA**: The module has been moved from the `/alpha` export to the root of the package.
- Updated dependencies
- @backstage/plugin-catalog-node@1.19.0-next.1
## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.12-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-node@1.19.0-next.1
## @backstage/plugin-catalog-backend-module-unprocessed@0.6.4-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-auth-node@0.6.7-next.1
- @backstage/plugin-catalog-node@1.19.0-next.1
## @backstage/plugin-catalog-graph@0.4.23-next.2
### Patch Changes
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/core-compat-api@0.5.2-next.2
## @backstage/plugin-catalog-import@0.13.5-next.2
### Patch Changes
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/integration@1.18.0-next.0
- @backstage/core-compat-api@0.5.2-next.2
## @backstage/plugin-devtools-backend@0.5.9-next.1
### Patch Changes
- Updated dependencies
- @backstage/config-loader@1.10.3-next.0
- @backstage/backend-defaults@0.12.1-next.1
## @backstage/plugin-home@0.8.12-next.2
### Patch Changes
- 929c55a: Fixed race condition in CustomHomepageGrid by waiting for storage to load before rendering custom layout to prevent
rendering of the default content.
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/core-compat-api@0.5.2-next.2
## @backstage/plugin-kubernetes@0.12.11-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/core-compat-api@0.5.2-next.2
## @backstage/plugin-kubernetes-backend@0.20.2-next.2
### Patch Changes
- dd7b6d2: Fix a bug where `getDefault` in the `kubernetesFetcherExtensionPoint` had the wrong `this` value
- Updated dependencies
- @backstage/plugin-auth-node@0.6.7-next.1
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration-aws-node@0.1.17
## @backstage/plugin-kubernetes-cluster@0.0.29-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
## @backstage/plugin-mcp-actions-backend@0.1.3-next.1
### Patch Changes
- 1d47bf3: Proxy `/.well-known/oauth-authorization-server` to `/.well-known/openid-configuration` on `auth-backend` when `auth.experimentalDynamicClientRegistration.enabled` is enabled.
- Updated dependencies
- @backstage/backend-defaults@0.12.1-next.1
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-node@1.19.0-next.1
## @backstage/plugin-notifications-backend@0.5.10-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-auth-node@0.6.7-next.1
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/plugin-notifications-node@0.2.19-next.1
## @backstage/plugin-notifications-backend-module-email@0.3.13-next.1
### Patch Changes
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration-aws-node@0.1.17
- @backstage/plugin-notifications-node@0.2.19-next.1
## @backstage/plugin-notifications-backend-module-slack@0.1.5-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/plugin-notifications-node@0.2.19-next.1
## @backstage/plugin-notifications-node@0.2.19-next.1
### Patch Changes
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
## @backstage/plugin-org@0.6.44-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/core-compat-api@0.5.2-next.2
## @backstage/plugin-org-react@0.1.42-next.2
### Patch Changes
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
## @backstage/plugin-scaffolder@1.34.1-next.2
### Patch Changes
- 0d415ae: Render a TechDocs link on the Scaffolder Template List page when templates include either `backstage.io/techdocs-ref` or `backstage.io/techdocs-entity` annotations, using the shared `buildTechDocsURL` helper. Also adds tests to verify both annotations and optional `backstage.io/techdocs-entity-path` are respected.
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/plugin-scaffolder-react@1.19.1-next.2
- @backstage/integration@1.18.0-next.0
- @backstage/core-compat-api@0.5.2-next.2
## @backstage/plugin-scaffolder-backend@2.2.1-next.1
### Patch Changes
- Updated dependencies
- @backstage/backend-defaults@0.12.1-next.1
- @backstage/plugin-auth-node@0.6.7-next.1
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration@1.18.0-next.0
- @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.12-next.1
- @backstage/plugin-scaffolder-backend-module-github@0.8.3-next.1
## @backstage/plugin-scaffolder-backend-module-github@0.8.3-next.1
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration@1.18.0-next.0
## @backstage/plugin-scaffolder-react@1.19.1-next.2
### Patch Changes
- 58fc108: Fix scaffolder task log stream not having a minimum height
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
## @backstage/plugin-search@1.4.30-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/core-compat-api@0.5.2-next.2
## @backstage/plugin-search-backend-module-catalog@0.3.8-next.1
### Patch Changes
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-node@1.19.0-next.1
## @backstage/plugin-search-backend-module-techdocs@0.4.6-next.1
### Patch Changes
- Updated dependencies
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-node@1.19.0-next.1
## @backstage/plugin-techdocs@1.14.2-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-auth-react@0.1.19-next.1
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/integration@1.18.0-next.0
- @backstage/core-compat-api@0.5.2-next.2
## @backstage/plugin-techdocs-addons-test-utils@1.0.53-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/plugin-catalog@1.31.3-next.2
- @backstage/plugin-techdocs@1.14.2-next.2
## @backstage/plugin-techdocs-backend@2.1.0-next.1
### Patch Changes
- Updated dependencies
- @backstage/backend-defaults@0.12.1-next.1
- @backstage/catalog-client@1.12.0-next.0
- @backstage/plugin-catalog-node@1.19.0-next.1
- @backstage/integration@1.18.0-next.0
- @backstage/plugin-search-backend-module-techdocs@0.4.6-next.1
## @backstage/plugin-user-settings@0.8.26-next.2
### Patch Changes
- b713b54: Tool-tip text correction for the Theme selection in settings page
- Updated dependencies
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/core-compat-api@0.5.2-next.2
## example-app@0.2.113-next.2
### Patch Changes
- Updated dependencies
- @backstage/ui@0.7.1-next.0
- @backstage/plugin-auth-react@0.1.19-next.1
- @backstage/plugin-home@0.8.12-next.2
- @backstage/plugin-scaffolder@1.34.1-next.2
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/plugin-user-settings@0.8.26-next.2
- @backstage/plugin-scaffolder-react@1.19.1-next.2
- @backstage/plugin-catalog@1.31.3-next.2
- @backstage/cli@0.34.2-next.2
- @backstage/plugin-catalog-graph@0.4.23-next.2
- @backstage/plugin-catalog-import@0.13.5-next.2
- @backstage/plugin-org@0.6.44-next.2
- @backstage/plugin-techdocs@1.14.2-next.2
- @backstage/plugin-api-docs@0.12.11-next.2
- @backstage/plugin-kubernetes@0.12.11-next.2
- @backstage/plugin-kubernetes-cluster@0.0.29-next.2
- @backstage/plugin-search@1.4.30-next.2
- @backstage/plugin-techdocs-module-addons-contrib@1.1.28-next.0
## example-app-next@0.0.27-next.2
### Patch Changes
- Updated dependencies
- @backstage/ui@0.7.1-next.0
- @backstage/plugin-auth-react@0.1.19-next.1
- @backstage/plugin-auth@0.1.0-next.0
- @backstage/plugin-home@0.8.12-next.2
- @backstage/plugin-scaffolder@1.34.1-next.2
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/plugin-user-settings@0.8.26-next.2
- @backstage/plugin-scaffolder-react@1.19.1-next.2
- @backstage/plugin-catalog@1.31.3-next.2
- @backstage/cli@0.34.2-next.2
- @backstage/plugin-catalog-graph@0.4.23-next.2
- @backstage/plugin-catalog-import@0.13.5-next.2
- @backstage/plugin-org@0.6.44-next.2
- @backstage/plugin-techdocs@1.14.2-next.2
- @backstage/core-compat-api@0.5.2-next.2
- @backstage/plugin-api-docs@0.12.11-next.2
- @backstage/plugin-kubernetes@0.12.11-next.2
- @backstage/plugin-kubernetes-cluster@0.0.29-next.2
- @backstage/plugin-search@1.4.30-next.2
- @backstage/plugin-techdocs-module-addons-contrib@1.1.28-next.0
-6
View File
@@ -1,6 +0,0 @@
{
"packages": ["packages/*", "plugins/*"],
"npmClient": "yarn",
"useWorkspaces": true,
"version": "0.0.0"
}
+10
View File
@@ -0,0 +1,10 @@
---
title: Data Contract
author: Jan Remunda
authorUrl: https://www.remunda.cz/#backstage
category: Discovery
description: Ingest and visualize Data Contracts to your catalog via API Entities.
documentation: https://www.npmjs.com/package/@remunda/backstage-plugin-datacontract
iconUrl: https://www.remunda.cz/logos/datacontract.png
npmPackageName: '@remunda/backstage-plugin-datacontract'
addedDate: '2025-08-19'
@@ -0,0 +1,19 @@
import React from 'react';
type Props = {
searchTerm: string;
onSearchTermChange: (newTerm: string) => void;
};
export const PluginsSearch = (props: Props) => {
const { searchTerm, onSearchTermChange } = props;
return (
<input
name="search"
onInput={e => onSearchTermChange((e.target as HTMLInputElement).value)}
value={searchTerm}
placeholder="Search plugins..."
className="DocSearch-Input search"
/>
);
};
+55 -29
View File
@@ -5,10 +5,11 @@ import { truncateDescription } from '@site/src/util/truncateDescription';
import { ChipCategory } from '@site/src/util/types';
import Layout from '@theme/Layout';
import clsx from 'clsx';
import React, { useState } from 'react';
import React, { useMemo, useState } from 'react';
import { IPluginData, PluginCard } from './_pluginCard';
import pluginsStyles from './plugins.module.scss';
import { PluginsSearch } from '@site/src/components/pluginsSearch/pluginsSearch';
interface IPluginsList {
corePlugins: IPluginData[];
@@ -55,6 +56,7 @@ const Plugins = () => {
const [selectedCategories, setSelectedCategories] = useState<string[]>([]);
const [showCoreFeatures, setShowCoreFeatures] = useState(true);
const [showOtherPlugins, setShowOtherPlugins] = useState(true);
const [searchTerm, setSearchTerm] = useState('');
const handleChipClick = (categoryName: string) => {
const isSelected =
@@ -97,6 +99,34 @@ const Plugins = () => {
}
};
const matchesSearch = (pluginData: IPluginData, term: string) => {
if (!term) return true;
const lowerTerm = term.toLowerCase();
return (
pluginData.title.toLowerCase().includes(lowerTerm) ||
pluginData.description.toLowerCase().includes(lowerTerm) ||
pluginData.category.toLowerCase().includes(lowerTerm) ||
(pluginData.author && pluginData.author.toLowerCase().includes(lowerTerm))
);
};
const matchesCategory = (pluginData: IPluginData, categories: string[]) => {
if (categories.length === 0) return true;
return categories.includes(pluginData.category);
};
const corePlugins = useMemo(() => {
return plugins.corePlugins
.filter(pluginData => matchesCategory(pluginData, selectedCategories))
.filter(pluginData => matchesSearch(pluginData, searchTerm));
}, [selectedCategories, searchTerm]);
const otherPlugins = useMemo(() => {
return plugins.otherPlugins
.filter(pluginData => matchesCategory(pluginData, selectedCategories))
.filter(pluginData => matchesSearch(pluginData, searchTerm));
}, [selectedCategories, searchTerm]);
return (
<Layout>
<div
@@ -126,31 +156,36 @@ const Plugins = () => {
categories={categories}
handleChipClick={handleChipClick}
/>
<PluginsSearch
searchTerm={searchTerm}
onSearchTermChange={setSearchTerm}
/>
</div>
{showCoreFeatures && (
{corePlugins.length === 0 && otherPlugins.length === 0 && (
<div className="margin-vert--lg">
<h3>No plugins found</h3>
<p>
We couldn't find any plugins matching your criteria. Please try
adjusting your search or filter settings.
</p>
</div>
)}
{showCoreFeatures && corePlugins.length > 0 && (
<div>
<h2>Core Features</h2>
<h2>Core Features ({corePlugins.length})</h2>
<div className="pluginsContainer margin-bottom--lg">
{plugins.corePlugins
.filter(
pluginData =>
!selectedCategories.length ||
selectedCategories.includes(pluginData.category),
)
.map(pluginData => (
<PluginCard
key={pluginData.title}
{...pluginData}
></PluginCard>
))}
{corePlugins.map(pluginData => (
<PluginCard key={pluginData.title} {...pluginData}></PluginCard>
))}
</div>
</div>
)}
{showOtherPlugins && (
{showOtherPlugins && otherPlugins.length > 0 && (
<div>
<h2>All Plugins</h2>
<h2>All Plugins ({otherPlugins.length})</h2>
<p>
Friendly reminder: While we love the variety and contributions of
our open source plugins, they haven't been fully vetted by the
@@ -158,18 +193,9 @@ const Plugins = () => {
your due diligence before installing. Happy exploring!
</p>
<div className="pluginsContainer margin-bottom--lg">
{plugins.otherPlugins
.filter(
pluginData =>
!selectedCategories.length ||
selectedCategories.includes(pluginData.category),
)
.map(pluginData => (
<PluginCard
key={pluginData.title}
{...pluginData}
></PluginCard>
))}
{otherPlugins.map(pluginData => (
<PluginCard key={pluginData.title} {...pluginData}></PluginCard>
))}
</div>
</div>
)}
@@ -76,6 +76,20 @@
height: 1rem;
}
:global(.search) {
float: right;
margin-bottom: 1rem;
margin-right: 1rem;
font-size: calc(0.875rem * var(--ifm-button-size-multiplier));
font-weight: var(--ifm-button-font-weight);
background-color: transparent;
border: var(--ifm-button-border-width) solid var(--ifm-color-primary);
border-radius: var(--ifm-button-border-radius);
color: var(--ifm-color-primary);
width: 220px;
height: 2.2rem;
}
:global(.dropdown) {
float: right;
margin-bottom: 1rem;
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "root",
"version": "1.43.0-next.1",
"version": "1.43.0-next.2",
"backstage": {
"cli": {
"new": {
@@ -35,6 +35,7 @@ import {
FetchMiddlewares,
VMwareCloudAuth,
FrontendHostDiscovery,
OpenShiftAuth,
} from '@backstage/core-app-api';
import {
@@ -58,6 +59,7 @@ import {
bitbucketServerAuthApiRef,
atlassianAuthApiRef,
vmwareCloudAuthApiRef,
openshiftAuthApiRef,
} from '@backstage/core-plugin-api';
import {
permissionApiRef,
@@ -275,6 +277,22 @@ export const apis = [
});
},
}),
createApiFactory({
api: openshiftAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) => {
return OpenShiftAuth.create({
configApi,
discoveryApi,
oauthRequestApi,
environment: configApi.getOptionalString('auth.environment'),
});
},
}),
createApiFactory({
api: permissionApiRef,
deps: {
+27
View File
@@ -1,5 +1,32 @@
# example-app-next
## 0.0.27-next.2
### Patch Changes
- Updated dependencies
- @backstage/ui@0.7.1-next.0
- @backstage/plugin-auth-react@0.1.19-next.1
- @backstage/plugin-auth@0.1.0-next.0
- @backstage/plugin-home@0.8.12-next.2
- @backstage/plugin-scaffolder@1.34.1-next.2
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/plugin-user-settings@0.8.26-next.2
- @backstage/plugin-scaffolder-react@1.19.1-next.2
- @backstage/plugin-catalog@1.31.3-next.2
- @backstage/cli@0.34.2-next.2
- @backstage/plugin-catalog-graph@0.4.23-next.2
- @backstage/plugin-catalog-import@0.13.5-next.2
- @backstage/plugin-org@0.6.44-next.2
- @backstage/plugin-techdocs@1.14.2-next.2
- @backstage/core-compat-api@0.5.2-next.2
- @backstage/plugin-api-docs@0.12.11-next.2
- @backstage/plugin-kubernetes@0.12.11-next.2
- @backstage/plugin-kubernetes-cluster@0.0.29-next.2
- @backstage/plugin-search@1.4.30-next.2
- @backstage/plugin-techdocs-module-addons-contrib@1.1.28-next.0
## 0.0.27-next.1
### Patch Changes
-1
View File
@@ -4,7 +4,6 @@ app:
routes:
bindings:
catalog.viewTechDoc: techdocs.docRoot
catalog.createComponent: catalog-import.importPage
org.catalogIndex: catalog.catalogIndex
pluginOverrides:
+2 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-app-next",
"version": "0.0.27-next.1",
"version": "0.0.27-next.2",
"backstage": {
"role": "frontend"
},
@@ -49,6 +49,7 @@
"@backstage/plugin-api-docs": "workspace:^",
"@backstage/plugin-app": "workspace:^",
"@backstage/plugin-app-visualizer": "workspace:^",
"@backstage/plugin-auth": "workspace:^",
"@backstage/plugin-auth-react": "workspace:^",
"@backstage/plugin-catalog": "workspace:^",
"@backstage/plugin-catalog-common": "workspace:^",
+25
View File
@@ -1,5 +1,30 @@
# example-app
## 0.2.113-next.2
### Patch Changes
- Updated dependencies
- @backstage/ui@0.7.1-next.0
- @backstage/plugin-auth-react@0.1.19-next.1
- @backstage/plugin-home@0.8.12-next.2
- @backstage/plugin-scaffolder@1.34.1-next.2
- @backstage/plugin-catalog-react@1.21.0-next.2
- @backstage/core-components@0.17.6-next.1
- @backstage/plugin-user-settings@0.8.26-next.2
- @backstage/plugin-scaffolder-react@1.19.1-next.2
- @backstage/plugin-catalog@1.31.3-next.2
- @backstage/cli@0.34.2-next.2
- @backstage/plugin-catalog-graph@0.4.23-next.2
- @backstage/plugin-catalog-import@0.13.5-next.2
- @backstage/plugin-org@0.6.44-next.2
- @backstage/plugin-techdocs@1.14.2-next.2
- @backstage/plugin-api-docs@0.12.11-next.2
- @backstage/plugin-kubernetes@0.12.11-next.2
- @backstage/plugin-kubernetes-cluster@0.0.29-next.2
- @backstage/plugin-search@1.4.30-next.2
- @backstage/plugin-techdocs-module-addons-contrib@1.1.28-next.0
## 0.2.113-next.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "example-app",
"version": "0.2.113-next.1",
"version": "0.2.113-next.2",
"backstage": {
"role": "frontend"
},
+7
View File
@@ -23,6 +23,7 @@ import {
oneloginAuthApiRef,
bitbucketAuthApiRef,
bitbucketServerAuthApiRef,
openshiftAuthApiRef,
} from '@backstage/core-plugin-api';
export const providers = [
@@ -74,4 +75,10 @@ export const providers = [
message: 'Sign In using Bitbucket Server',
apiRef: bitbucketServerAuthApiRef,
},
{
id: 'openshift-auth-provider',
title: 'OpenShift',
message: 'Sign In using OpenShift',
apiRef: openshiftAuthApiRef,
},
];
+11
View File
@@ -1,5 +1,16 @@
# @backstage/backend-defaults
## 0.12.1-next.1
### Patch Changes
- 4eda590: Fixed cache namespace and key prefix separator configuration to properly use configured values instead of hardcoded plugin ID. The cache manager now correctly combines the configured namespace with plugin IDs using the configured separator for Redis and Valkey. Memcache and memory store continue to use plugin ID as namespace.
- Updated dependencies
- @backstage/config-loader@1.10.3-next.0
- @backstage/plugin-auth-node@0.6.7-next.1
- @backstage/integration@1.18.0-next.0
- @backstage/integration-aws-node@0.1.17
## 0.12.1-next.0
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/backend-defaults",
"version": "0.12.1-next.0",
"version": "0.12.1-next.1",
"description": "Backend defaults used by Backstage backend apps",
"backstage": {
"role": "node-library"
@@ -333,4 +333,147 @@ describe('CacheManager store options', () => {
keyPrefixSeparator: '!',
});
});
it('correctly applies namespace configuration to redis and valkey stores', () => {
const testCases = [
{ store: 'redis', namespace: 'test1', separator: ':' },
{ store: 'valkey', namespace: 'test2', separator: '!' },
];
testCases.forEach(({ store, namespace, separator }) => {
const manager = CacheManager.fromConfig(
mockServices.rootConfig({
data: {
backend: {
cache: {
store,
connection: 'redis://localhost:6379',
[store]: {
client: {
namespace,
keyPrefixSeparator: separator,
},
},
},
},
},
}),
);
manager.forPlugin('testPlugin');
if (store === 'redis') {
// eslint-disable-next-line jest/no-conditional-expect
expect(KeyvRedis).toHaveBeenCalledWith('redis://localhost:6379', {
namespace,
keyPrefixSeparator: separator,
});
} else if (store === 'valkey') {
// eslint-disable-next-line jest/no-conditional-expect
expect(KeyvValkey).toHaveBeenCalledWith('redis://localhost:6379', {
namespace,
keyPrefixSeparator: separator,
});
}
});
});
it('falls back to pluginId when no namespace is configured', () => {
const manager = CacheManager.fromConfig(
mockServices.rootConfig({
data: {
backend: {
cache: {
store: 'redis',
connection: 'redis://localhost:6379',
},
},
},
}),
);
manager.forPlugin('testPlugin');
expect(KeyvRedis).toHaveBeenCalledWith('redis://localhost:6379', {
keyPrefixSeparator: ':',
});
});
describe('Namespace construction', () => {
it('returns pluginId when no store options are provided', () => {
const result = (CacheManager as any).constructNamespace(
'testPlugin',
undefined,
);
expect(result).toBe('testPlugin');
});
it('returns pluginId when store options have no namespace', () => {
const storeOptions = {
client: {
keyPrefixSeparator: ':',
},
};
const result = (CacheManager as any).constructNamespace(
'testPlugin',
storeOptions,
);
expect(result).toBe('testPlugin');
});
it('combines namespace and pluginId with default separator', () => {
const storeOptions = {
client: {
namespace: 'my-app',
keyPrefixSeparator: ':',
},
};
const result = (CacheManager as any).constructNamespace(
'testPlugin',
storeOptions,
);
expect(result).toBe('my-app:testPlugin');
});
it('combines namespace and pluginId with custom separator', () => {
const storeOptions = {
client: {
namespace: 'my-app',
keyPrefixSeparator: '-',
},
};
const result = (CacheManager as any).constructNamespace(
'testPlugin',
storeOptions,
);
expect(result).toBe('my-app-testPlugin');
});
it('uses default separator when keyPrefixSeparator is not provided', () => {
const storeOptions = {
client: {
namespace: 'my-app',
},
};
const result = (CacheManager as any).constructNamespace(
'testPlugin',
storeOptions,
);
expect(result).toBe('my-app:testPlugin');
});
it('handles empty namespace by falling back to pluginId', () => {
const storeOptions = {
client: {
namespace: '',
keyPrefixSeparator: ':',
},
};
const result = (CacheManager as any).constructNamespace(
'testPlugin',
storeOptions,
);
expect(result).toBe('testPlugin');
});
});
});
@@ -213,6 +213,26 @@ export class CacheManager {
return redisOptions;
}
/**
* Construct the full namespace based on the options and pluginId.
*
* @param pluginId - The plugin ID to namespace
* @param storeOptions - Optional cache store configuration options
* @returns The constructed namespace string combining the configured namespace with pluginId
*/
private static constructNamespace(
pluginId: string,
storeOptions: RedisCacheStoreOptions | undefined,
): string {
const prefix = storeOptions?.client?.namespace
? `${storeOptions.client.namespace}${
storeOptions.client.keyPrefixSeparator ?? ':'
}`
: '';
return `${prefix}${pluginId}`;
}
/** @internal */
constructor(
store: string,
@@ -286,7 +306,7 @@ export class CacheManager {
});
}
return new Keyv({
namespace: pluginId,
namespace: CacheManager.constructNamespace(pluginId, this.storeOptions),
ttl: defaultTtl,
store: stores[pluginId],
emitErrors: false,
@@ -326,7 +346,7 @@ export class CacheManager {
});
}
return new Keyv({
namespace: pluginId,
namespace: CacheManager.constructNamespace(pluginId, this.storeOptions),
ttl: defaultTtl,
store: stores[pluginId],
emitErrors: false,
@@ -1,5 +1,16 @@
# @backstage/backend-dynamic-feature-service
## 0.7.4-next.1
### Patch Changes
- Updated dependencies
- @backstage/config-loader@1.10.3-next.0
- @backstage/backend-defaults@0.12.1-next.1
- @backstage/plugin-auth-node@0.6.7-next.1
- @backstage/plugin-catalog-backend@3.0.2-next.1
- @backstage/plugin-app-node@0.1.37-next.1
## 0.7.4-next.0
### Patch Changes
@@ -1,6 +1,6 @@
{
"name": "@backstage/backend-dynamic-feature-service",
"version": "0.7.4-next.0",
"version": "0.7.4-next.1",
"description": "Backstage dynamic feature service",
"backstage": {
"role": "node-library"
+1
View File
@@ -37,6 +37,7 @@
"@backstage/plugin-auth-backend": "workspace:^",
"@backstage/plugin-auth-backend-module-github-provider": "workspace:^",
"@backstage/plugin-auth-backend-module-guest-provider": "workspace:^",
"@backstage/plugin-auth-backend-module-openshift-provider": "workspace:^",
"@backstage/plugin-auth-node": "workspace:^",
"@backstage/plugin-catalog-backend": "workspace:^",
"@backstage/plugin-catalog-backend-module-backstage-openapi": "workspace:^",
+1
View File
@@ -33,6 +33,7 @@ const searchLoader = createBackendFeatureLoader({
backend.add(import('@backstage/plugin-auth-backend'));
backend.add(import('./authModuleGithubProvider'));
backend.add(import('@backstage/plugin-auth-backend-module-guest-provider'));
backend.add(import('@backstage/plugin-auth-backend-module-openshift-provider'));
backend.add(import('@backstage/plugin-app-backend'));
backend.add(import('@backstage/plugin-catalog-backend-module-unprocessed'));
backend.add(
+23
View File
@@ -1,5 +1,28 @@
# @backstage/catalog-client
## 1.12.0-next.0
### Minor Changes
- 0e9ec44: Introduced new `streamEntities` async generator method for the catalog.
Catalog API and Catalog Service now includes a `streamEntities` method that allows for streaming entities from the catalog.
This method is designed to handle large datasets efficiently by processing entities in a stream rather than loading them
all into memory at once. This is useful when you need to fetch a large number of entities but do not want to use pagination
or fetch all entities at once.
Example usage:
```ts
const pageStream = catalogClient.streamEntities({ pageSize: 100 }, { token });
for await (const page of pageStream) {
// Handle page of entities
for (const entity of page) {
console.log(entity);
}
}
```
## 1.11.0
### Minor Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/catalog-client",
"version": "1.11.0",
"version": "1.12.0-next.0",
"description": "An isomorphic client for the catalog backend",
"backstage": {
"role": "common-library"
+8
View File
@@ -1,5 +1,13 @@
# @backstage/cli
## 0.34.2-next.2
### Patch Changes
- Updated dependencies
- @backstage/config-loader@1.10.3-next.0
- @backstage/integration@1.18.0-next.0
## 0.34.2-next.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/cli",
"version": "0.34.2-next.1",
"version": "0.34.2-next.2",
"description": "CLI for developing Backstage plugins and apps",
"backstage": {
"role": "cli"
@@ -264,24 +264,30 @@ export async function createConfig(
singleton: true,
requiredVersion: '*',
eager: !isRemote,
import: false,
},
'react-dom': {
singleton: true,
requiredVersion: '*',
eager: !isRemote,
import: false,
},
// React Router
'react-router': {
singleton: true,
requiredVersion: '*',
eager: !isRemote,
import: false,
},
'react-router-dom': {
singleton: true,
requiredVersion: '*',
eager: !isRemote,
import: false,
},
// MUI v4
// not setting import: false for MUI packages as this
// will break once Backstage moves to BUI
'@material-ui/core/styles': {
singleton: true,
requiredVersion: '*',
@@ -293,6 +299,8 @@ export async function createConfig(
eager: !isRemote,
},
// MUI v5
// not setting import: false for MUI packages as this
// will break once Backstage moves to BUI
'@mui/material/styles/': {
singleton: true,
requiredVersion: '*',
+6
View File
@@ -1,5 +1,11 @@
# @backstage/config-loader
## 1.10.3-next.0
### Patch Changes
- a73f495: Allow using `BACKSTAGE_ENV` for loading environment specific config files
## 1.10.2
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/config-loader",
"version": "1.10.2",
"version": "1.10.3-next.0",
"description": "Config loading functionality used by Backstage backend, and CLI",
"backstage": {
"role": "node-library"
@@ -41,16 +41,6 @@ describe('collectConfigSchemas', () => {
mockDir.clear();
});
it('should not find any schemas without packages', async () => {
mockDir.setContent({
'lerna.json': JSON.stringify({
packages: ['packages/*'],
}),
});
await expect(collectConfigSchemas([], [])).resolves.toEqual([]);
});
it('should find schema in a local package', async () => {
mockDir.setContent({
node_modules: {
@@ -89,6 +89,19 @@ describe('ConfigSources', () => {
{ name: 'FileConfigSource', path: `${root}app-config.yaml` },
{ name: 'FileConfigSource', path: `${root}app-config.local.yaml` },
]);
process.env = Object.assign(process.env, { BACKSTAGE_ENV: 'test' });
expect(
mergeSources(
ConfigSources.defaultForTargets({ rootDir: '/', targets: [] }),
),
).toEqual([
{ name: 'FileConfigSource', path: `${root}app-config.yaml` },
{ name: 'FileConfigSource', path: `${root}app-config.test.yaml` },
{ name: 'FileConfigSource', path: `${root}app-config.local.yaml` },
{ name: 'FileConfigSource', path: `${root}app-config.test.local.yaml` },
]);
fsSpy.mockRestore();
expect(
@@ -182,6 +182,14 @@ export class ConfigSources {
if (argSources.length === 0) {
const defaultPath = resolvePath(rootDir, 'app-config.yaml');
const localPath = resolvePath(rootDir, 'app-config.local.yaml');
const envPath = resolvePath(
rootDir,
`app-config.${process.env.BACKSTAGE_ENV}.yaml`,
);
const envLocalPath = resolvePath(
rootDir,
`app-config.${process.env.BACKSTAGE_ENV}.local.yaml`,
);
const alwaysIncludeDefaultConfigSource =
!options.allowMissingDefaultConfig;
@@ -195,6 +203,16 @@ export class ConfigSources {
);
}
if (process.env.BACKSTAGE_ENV && fs.pathExistsSync(envPath)) {
argSources.push(
FileConfigSource.create({
watch: options.watch,
path: envPath,
substitutionFunc: options.substitutionFunc,
}),
);
}
if (fs.pathExistsSync(localPath)) {
argSources.push(
FileConfigSource.create({
@@ -204,6 +222,16 @@ export class ConfigSources {
}),
);
}
if (process.env.BACKSTAGE_ENV && fs.pathExistsSync(envLocalPath)) {
argSources.push(
FileConfigSource.create({
watch: options.watch,
path: envLocalPath,
substitutionFunc: options.substitutionFunc,
}),
);
}
}
return this.merge(argSources);
+7
View File
@@ -52,6 +52,7 @@ import { Observable } from '@backstage/types';
import { oktaAuthApiRef } from '@backstage/core-plugin-api';
import { oneloginAuthApiRef } from '@backstage/core-plugin-api';
import { OpenIdConnectApi } from '@backstage/core-plugin-api';
import { openshiftAuthApiRef } from '@backstage/core-plugin-api';
import { PendingOAuthRequest } from '@backstage/core-plugin-api';
import { ProfileInfo } from '@backstage/core-plugin-api';
import { ProfileInfoApi } from '@backstage/core-plugin-api';
@@ -651,6 +652,12 @@ export type OpenLoginPopupOptions = {
height?: number;
};
// @public
export class OpenShiftAuth {
// (undocumented)
static create(options: OAuthApiCreateOptions): typeof openshiftAuthApiRef.T;
}
// @public
export type PopupOptions = {
size?:
@@ -26,4 +26,5 @@ export * from './bitbucket';
export * from './bitbucketServer';
export * from './atlassian';
export * from './vmwareCloud';
export * from './openshift';
export type { OAuthApiCreateOptions, AuthApiCreateOptions } from './types';
@@ -0,0 +1,52 @@
/*
* Copyright 2025 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 { openshiftAuthApiRef } from '@backstage/core-plugin-api';
import { OAuth2 } from '../oauth2';
import { OAuthApiCreateOptions } from '../types';
const DEFAULT_PROVIDER = {
id: 'openshift',
title: 'OpenShift',
icon: () => null,
};
/**
* Implements the OAuth flow to OpenShift
*
* @public
*/
export default class OpenShiftAuth {
static create(options: OAuthApiCreateOptions): typeof openshiftAuthApiRef.T {
const {
configApi,
discoveryApi,
environment = 'development',
provider = DEFAULT_PROVIDER,
oauthRequestApi,
defaultScopes = ['user:info'],
} = options;
return OAuth2.create({
configApi,
discoveryApi,
oauthRequestApi,
provider,
environment,
defaultScopes,
});
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2023 The Backstage Authors
* Copyright 2025 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.
@@ -14,5 +14,4 @@
* limitations under the License.
*/
export * from './module';
export { default } from './module';
export { default as OpenShiftAuth } from './OpenShiftAuth';
+7
View File
@@ -1,5 +1,12 @@
# @backstage/core-compat-api
## 0.5.2-next.2
### Patch Changes
- Updated dependencies
- @backstage/plugin-catalog-react@1.21.0-next.2
## 0.5.2-next.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/core-compat-api",
"version": "0.5.2-next.1",
"version": "0.5.2-next.2",
"backstage": {
"role": "web-library"
},
+7
View File
@@ -1,5 +1,12 @@
# @backstage/core-components
## 0.17.6-next.1
### Patch Changes
- 1ad3d94: Dependency graph can now be opened in full screen mode
- ae7d426: update about card links style for pretty display with other language
## 0.17.6-next.0
### Patch Changes
+3 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/core-components",
"version": "0.17.6-next.0",
"version": "0.17.6-next.1",
"description": "Core components used by Backstage plugins and apps",
"backstage": {
"role": "web-library"
@@ -80,6 +80,7 @@
"pluralize": "^8.0.0",
"qs": "^6.9.4",
"rc-progress": "3.5.1",
"react-full-screen": "^1.1.1",
"react-helmet": "6.1.0",
"react-hook-form": "^7.12.2",
"react-idle-timer": "5.7.2",
@@ -106,6 +107,7 @@
"@types/d3-selection": "^3.0.1",
"@types/d3-shape": "^3.0.1",
"@types/d3-zoom": "^3.0.1",
"@types/fscreen": "^1",
"@types/google-protobuf": "^3.7.2",
"@types/react": "^18.0.0",
"@types/react-helmet": "^6.1.0",
@@ -61,6 +61,7 @@ export const coreComponentsTranslationRef: TranslationRef<
readonly 'alertDisplay.message_other': '({{ count }} newer messages)';
readonly 'autoLogout.stillTherePrompt.title': 'Logging out due to inactivity';
readonly 'autoLogout.stillTherePrompt.buttonText': "Yes! Don't log me out";
readonly 'dependencyGraph.fullscreenTooltip': 'Toggle fullscreen';
readonly 'proxiedSignInPage.title': 'You do not appear to be signed in. Please try reloading the browser page.';
}
>;
+1
View File
@@ -258,6 +258,7 @@ export interface DependencyGraphProps<NodeData, EdgeData>
extends SVGProps<SVGSVGElement> {
acyclicer?: 'greedy';
align?: DependencyGraphTypes.Alignment;
allowFullscreen?: boolean;
curve?: 'curveStepBefore' | 'curveMonotoneX';
defs?: JSX.Element | JSX.Element[];
direction?: DependencyGraphTypes.Direction;
@@ -14,10 +14,10 @@
* limitations under the License.
*/
import { render } from '@testing-library/react';
import { DependencyGraph } from './DependencyGraph';
import { DependencyGraphTypes as Types } from './types';
import { EDGE_TEST_ID, LABEL_TEST_ID, NODE_TEST_ID } from './constants';
import { renderInTestApp } from '@backstage/test-utils';
describe('<DependencyGraph />', () => {
beforeAll(() => {
@@ -36,9 +36,8 @@ describe('<DependencyGraph />', () => {
const CUSTOM_TEST_ID = 'custom-test-id';
it('renders each node and edge supplied', async () => {
const { getByText, queryAllByTestId, findAllByTestId } = render(
<DependencyGraph nodes={nodes} edges={edges} />,
);
const { getByText, queryAllByTestId, findAllByTestId } =
await renderInTestApp(<DependencyGraph nodes={nodes} edges={edges} />);
const renderedNodes = await findAllByTestId(NODE_TEST_ID);
expect(renderedNodes).toHaveLength(3);
expect(getByText(nodes[0].id)).toBeInTheDocument();
@@ -49,9 +48,10 @@ describe('<DependencyGraph />', () => {
});
it('update render if already referenced nodes are added later', async () => {
const { getByText, queryAllByTestId, findAllByTestId, rerender } = render(
<DependencyGraph nodes={nodes.slice(0, 2)} edges={edges} />,
);
const { getByText, queryAllByTestId, findAllByTestId, rerender } =
await renderInTestApp(
<DependencyGraph nodes={nodes.slice(0, 2)} edges={edges} />,
);
let renderedNodes = await findAllByTestId(NODE_TEST_ID);
expect(renderedNodes).toHaveLength(2);
@@ -75,9 +75,10 @@ describe('<DependencyGraph />', () => {
{ ...edges[0], label: 'first' },
{ ...edges[1], label: 'second' },
];
const { getByText, getAllByTestId, findAllByTestId } = render(
<DependencyGraph nodes={nodes} edges={labeledEdges} />,
);
const { getByText, getAllByTestId, findAllByTestId } =
await renderInTestApp(
<DependencyGraph nodes={nodes} edges={labeledEdges} />,
);
const renderedEdges = await findAllByTestId(EDGE_TEST_ID);
expect(renderedEdges).toHaveLength(2);
expect(getAllByTestId(LABEL_TEST_ID)).toHaveLength(2);
@@ -94,7 +95,7 @@ describe('<DependencyGraph />', () => {
<circle data-testid={CUSTOM_TEST_ID} r={100} />
</g>
);
const { getByText, findByTestId, container } = render(
const { getByText, findByTestId, container } = await renderInTestApp(
<DependencyGraph nodes={singleNode} edges={[]} renderNode={renderNode} />,
);
const node = await findByTestId(CUSTOM_TEST_ID);
@@ -112,7 +113,7 @@ describe('<DependencyGraph />', () => {
<circle data-testid={CUSTOM_TEST_ID} r={100} />
</g>
);
const { getByText, findByTestId, container } = render(
const { getByText, findByTestId, container } = await renderInTestApp(
<DependencyGraph
nodes={nodes}
edges={labeledEdge}
@@ -16,11 +16,11 @@
import {
SVGProps,
useState,
useRef,
useMemo,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import * as d3Zoom from 'd3-zoom';
import * as d3Selection from 'd3-selection';
@@ -31,6 +31,25 @@ import { DependencyGraphTypes as Types } from './types';
import { Node } from './Node';
import { Edge, GraphEdge } from './Edge';
import { ARROW_MARKER_ID } from './constants';
import IconButton from '@material-ui/core/IconButton';
import FullscreenIcon from '@material-ui/icons/Fullscreen';
import FullscreenExitIcon from '@material-ui/icons/FullscreenExit';
import { FullScreen, useFullScreenHandle } from 'react-full-screen';
import { makeStyles, Theme } from '@material-ui/core/styles';
import Tooltip from '@material-ui/core/Tooltip';
import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
import { coreComponentsTranslationRef } from '../../translation';
const useStyles = makeStyles((theme: Theme) => ({
root: {
overflow: 'hidden',
minHeight: '100%',
minWidth: '100%',
},
fullscreen: {
backgroundColor: theme.palette.background.paper,
},
}));
/**
* Properties of {@link DependencyGraph}
@@ -142,7 +161,6 @@ export interface DependencyGraphProps<NodeData, EdgeData>
* Custom edge rendering component
*/
renderEdge?: Types.RenderEdgeFunction<EdgeData>;
/**
* Custom node rendering component
*/
@@ -186,9 +204,18 @@ export interface DependencyGraphProps<NodeData, EdgeData>
* Default: 'grow'
*/
fit?: 'grow' | 'contain';
/**
* Controls if user can toggle fullscreen mode
*
* @remarks
*
* Default: true
*/
allowFullscreen?: boolean;
}
const WORKSPACE_ID = 'workspace';
const DEPENDENCY_GRAPH_SVG = 'dependency-graph';
/**
* Graph component used to visualize relations between entities
@@ -222,11 +249,15 @@ export function DependencyGraph<NodeData, EdgeData>(
curve = 'curveMonotoneX',
showArrowHeads = false,
fit = 'grow',
allowFullscreen = true,
...svgProps
} = props;
const theme = useTheme();
const [containerWidth, setContainerWidth] = useState<number>(100);
const [containerHeight, setContainerHeight] = useState<number>(100);
const fullScreenHandle = useFullScreenHandle();
const styles = useStyles();
const { t } = useTranslationRef(coreComponentsTranslationRef);
const graph = useRef<dagre.graphlib.Graph<Types.DependencyNode<NodeData>>>(
new dagre.graphlib.Graph(),
@@ -248,11 +279,17 @@ export function DependencyGraph<NodeData, EdgeData>(
const containerRef = useMemo(
() =>
debounce((node: SVGSVGElement) => {
if (!node) {
debounce((root: HTMLDivElement) => {
if (!root) {
return;
}
// Set up zooming + panning
const node: SVGSVGElement = root.querySelector(
`svg#${DEPENDENCY_GRAPH_SVG}`,
) as SVGSVGElement;
if (!node) {
return;
}
const container = d3Selection.select<SVGSVGElement, null>(node);
const workspace = d3Selection.select(node.getElementById(WORKSPACE_ID));
@@ -288,7 +325,7 @@ export function DependencyGraph<NodeData, EdgeData>(
}
const { width: newContainerWidth, height: newContainerHeight } =
node.getBoundingClientRect();
root.getBoundingClientRect();
if (containerWidth !== newContainerWidth) {
setContainerWidth(newContainerWidth);
}
@@ -412,70 +449,97 @@ export function DependencyGraph<NodeData, EdgeData>(
}
return (
<svg
ref={containerRef}
{...svgProps}
width="100%"
height={scalableHeight}
viewBox={`0 0 ${maxWidth} ${maxHeight}`}
>
<defs>
<marker
id={ARROW_MARKER_ID}
viewBox="0 0 24 24"
markerWidth="14"
markerHeight="14"
refX="16"
refY="12"
orient="auto"
markerUnits="strokeWidth"
>
<path
fill={theme.palette.textSubtle}
d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z"
/>
</marker>
{defs}
</defs>
<g id={WORKSPACE_ID}>
<svg
width={graphWidth}
height={graphHeight}
y={maxHeight / 2 - graphHeight / 2}
x={maxWidth / 2 - graphWidth / 2}
viewBox={`0 0 ${graphWidth} ${graphHeight}`}
>
{graphEdges.map(e => {
const edge = graph.current.edge(e) as GraphEdge<EdgeData>;
if (!edge) return null;
if (renderEdge) return renderEdge({ edge, id: e });
<div ref={containerRef} className={styles.root}>
<FullScreen
handle={fullScreenHandle}
className={fullScreenHandle.active ? styles.fullscreen : styles.root}
>
{allowFullscreen && (
<Tooltip title={t('dependencyGraph.fullscreenTooltip')}>
<IconButton
style={{ float: 'right' }}
onClick={
fullScreenHandle.active
? fullScreenHandle.exit
: fullScreenHandle.enter
}
>
{fullScreenHandle.active ? (
<FullscreenExitIcon />
) : (
<FullscreenIcon />
)}
</IconButton>
</Tooltip>
)}
return (
<Edge
key={`${e.v}-${e.w}`}
id={e}
setEdge={setEdge}
render={renderLabel}
edge={edge}
curve={curve}
showArrowHeads={showArrowHeads}
<svg
{...svgProps}
width="100%"
height={scalableHeight}
viewBox={`0 0 ${maxWidth} ${maxHeight}`}
id={DEPENDENCY_GRAPH_SVG}
>
<defs>
<marker
id={ARROW_MARKER_ID}
viewBox="0 0 24 24"
markerWidth="14"
markerHeight="14"
refX="16"
refY="12"
orient="auto"
markerUnits="strokeWidth"
>
<path
fill={theme.palette.textSubtle}
d="M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z"
/>
);
})}
{graphNodes.map((id: string) => {
const node = graph.current.node(id);
if (!node) return null;
return (
<Node
key={id}
setNode={setNode}
render={renderNode}
node={node}
/>
);
})}
</marker>
{defs}
</defs>
<g id={WORKSPACE_ID}>
<svg
width={graphWidth}
height={graphHeight}
y={maxHeight / 2 - graphHeight / 2}
x={maxWidth / 2 - graphWidth / 2}
viewBox={`0 0 ${graphWidth} ${graphHeight}`}
>
{graphEdges.map(e => {
const edge = graph.current.edge(e) as GraphEdge<EdgeData>;
if (!edge) return null;
if (renderEdge) return renderEdge({ edge, id: e });
return (
<Edge
key={`${e.v}-${e.w}`}
id={e}
setEdge={setEdge}
render={renderLabel}
edge={edge}
curve={curve}
showArrowHeads={showArrowHeads}
/>
);
})}
{graphNodes.map((id: string) => {
const node = graph.current.node(id);
if (!node) return null;
return (
<Node
key={id}
setNode={setNode}
render={renderNode}
node={node}
/>
);
})}
</svg>
</g>
</svg>
</g>
</svg>
</FullScreen>
</div>
);
}
@@ -27,6 +27,7 @@ const useStyles = makeStyles(
gridAutoFlow: 'column',
gridAutoColumns: 'min-content',
gridGap: theme.spacing(3),
wordBreak: 'keep-all',
},
}),
{ name: 'BackstageHeaderIconLinkRow' },
@@ -120,6 +120,9 @@ export const coreComponentsTranslationRef = createTranslationRef({
buttonText: "Yes! Don't log me out",
},
},
dependencyGraph: {
fullscreenTooltip: 'Toggle fullscreen',
},
proxiedSignInPage: {
title:
'You do not appear to be signed in. Please try reloading the browser page.',
+5
View File
@@ -604,6 +604,11 @@ export type OpenIdConnectApi = {
getIdToken(options?: AuthRequestOptions): Promise<string>;
};
// @public
export const openshiftAuthApiRef: ApiRef<
OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi
>;
// @public @deprecated
export type OptionalParams<
Params extends {
@@ -474,3 +474,20 @@ export const vmwareCloudAuthApiRef: ApiRef<
> = createApiRef({
id: 'core.auth.vmware-cloud',
});
/**
* Provides authentication towards OpenShift APIs and identities.
*
* @public
* @remarks
*
* See {@link https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/authentication_and_authorization/configuring-oauth-clients}
* on how to configure the OAuth clients and
* {@link https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html-single/authentication_and_authorization/index#tokens-scoping-about_configuring-internal-oauth}
* for available scopes.
*/
export const openshiftAuthApiRef: ApiRef<
OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi
> = createApiRef({
id: 'core.auth.openshift',
});
+6
View File
@@ -1,5 +1,11 @@
# @backstage/create-app
## 0.7.4-next.2
### Patch Changes
- Bumped create-app version.
## 0.7.4-next.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@backstage/create-app",
"version": "0.7.4-next.1",
"version": "0.7.4-next.2",
"description": "A CLI that helps you create your own Backstage app",
"backstage": {
"role": "cli"

Some files were not shown because too many files have changed in this diff Show More