diff --git a/.changeset/dull-taxis-carry.md b/.changeset/dull-taxis-carry.md
new file mode 100644
index 0000000000..1466f1246a
--- /dev/null
+++ b/.changeset/dull-taxis-carry.md
@@ -0,0 +1,8 @@
+---
+'@backstage/plugin-adr': minor
+'@backstage/plugin-adr-backend': patch
+---
+
+The ADR plugin can now work with sites other than GitHub. Expanded the ADR backend plugin to provide endpoints to facilitate this.
+
+**BREAKING** The ADR plugin now uses UrlReaders. You will have to [configure integrations](https://backstage.io/docs/integrations/index#configuration) for all sites you want to get ADRs from. If you would like to create your own implementation that has different behavior, you can override the AdrApi [just like you can with other apis.](https://backstage.io/docs/api/utility-apis#app-apis) The previously used Octokit implementation has been completely removed.
diff --git a/.changeset/eighty-forks-pull.md b/.changeset/eighty-forks-pull.md
new file mode 100644
index 0000000000..f5bf555317
--- /dev/null
+++ b/.changeset/eighty-forks-pull.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-git-release-manager': patch
+---
+
+add exports to clear api-report messages
diff --git a/.changeset/fair-ants-work.md b/.changeset/fair-ants-work.md
new file mode 100644
index 0000000000..4cf3c80488
--- /dev/null
+++ b/.changeset/fair-ants-work.md
@@ -0,0 +1,7 @@
+---
+'@backstage/backend-app-api': minor
+---
+
+**BREAKING**: The `httpRouterFactory` now accepts a `getPath` option rather than `indexPlugin`. To set up custom index path, configure the new `rootHttpRouterFactory` with a custom `indexPath` instead.
+
+Added an implementation for the new `rootHttpRouterServiceRef`.
diff --git a/.changeset/fair-falcons-lie.md b/.changeset/fair-falcons-lie.md
new file mode 100644
index 0000000000..ba39d51241
--- /dev/null
+++ b/.changeset/fair-falcons-lie.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder': patch
+---
+
+Render the scaffolder action description using the `MarkdownContent` component. This will allow the page to show richer content to describe scaffolder actions.
diff --git a/.changeset/few-mice-study.md b/.changeset/few-mice-study.md
new file mode 100644
index 0000000000..57a89cc547
--- /dev/null
+++ b/.changeset/few-mice-study.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-common': patch
+---
+
+Added `loggerToWinstonLogger`, which was moved from `@backstage/backend-plugin-api`.
diff --git a/.changeset/few-penguins-admire.md b/.changeset/few-penguins-admire.md
new file mode 100644
index 0000000000..170b4aa606
--- /dev/null
+++ b/.changeset/few-penguins-admire.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-scaffolder-backend-module-rails': patch
+'@backstage/plugin-scaffolder-backend': patch
+---
+
+Change scaffolder task actions to include markdown to demonstrate the new `ActionsPage` markdown feature.
diff --git a/.changeset/forty-mangos-fail.md b/.changeset/forty-mangos-fail.md
new file mode 100644
index 0000000000..d86d9c0e56
--- /dev/null
+++ b/.changeset/forty-mangos-fail.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+Slightly improve readability of "base URL conflict" error handling code
diff --git a/.changeset/gorgeous-days-applaud.md b/.changeset/gorgeous-days-applaud.md
new file mode 100644
index 0000000000..a34307d720
--- /dev/null
+++ b/.changeset/gorgeous-days-applaud.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-plugin-api': patch
+---
+
+Added a new `rootHttpRouterServiceRef` and `RootHttpRouterService` interface.
diff --git a/.changeset/little-beans-hammer.md b/.changeset/little-beans-hammer.md
new file mode 100644
index 0000000000..d998f5f5ba
--- /dev/null
+++ b/.changeset/little-beans-hammer.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-test-utils': patch
+---
+
+The `startTestBackend` setup now includes default implementations for all core services.
diff --git a/.changeset/long-owls-raise.md b/.changeset/long-owls-raise.md
new file mode 100644
index 0000000000..9021e4031a
--- /dev/null
+++ b/.changeset/long-owls-raise.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-adr-backend': patch
+'@backstage/plugin-adr': patch
+---
+
+Clarify that default ADR parsers support MADR specification v2.x
diff --git a/.changeset/loud-beds-occur.md b/.changeset/loud-beds-occur.md
new file mode 100644
index 0000000000..546805e592
--- /dev/null
+++ b/.changeset/loud-beds-occur.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-user-settings': patch
+---
+
+Refactor for the feature flag filter functionality
diff --git a/.changeset/mean-moles-relate.md b/.changeset/mean-moles-relate.md
new file mode 100644
index 0000000000..1b3d01dd96
--- /dev/null
+++ b/.changeset/mean-moles-relate.md
@@ -0,0 +1,31 @@
+---
+'@backstage/plugin-search-react': minor
+---
+
+Allow customizing empty state component through `noResultsComponent` property.
+
+Example:
+
+```jsx
+No results were found>}>
+ {({ results }) => (
+
+ {results.map(({ type, document }) => {
+ switch (type) {
+ case 'custom-result-item':
+ return (
+
+ );
+ default:
+ return (
+
+ );
+ }
+ })}
+
+ )}
+
+```
diff --git a/.changeset/nasty-pumas-kneel.md b/.changeset/nasty-pumas-kneel.md
new file mode 100644
index 0000000000..cdfda89868
--- /dev/null
+++ b/.changeset/nasty-pumas-kneel.md
@@ -0,0 +1,6 @@
+---
+'@backstage/backend-plugin-api': patch
+'@backstage/backend-common': patch
+---
+
+Migrated types related to `TokenManagerService`, `CacheService` and `DatabaseService` into backend-plugin-api.
diff --git a/.changeset/ninety-bags-turn.md b/.changeset/ninety-bags-turn.md
new file mode 100644
index 0000000000..27b9a94ad2
--- /dev/null
+++ b/.changeset/ninety-bags-turn.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-lighthouse': patch
+---
+
+Fixed bug in Lighthouse Plugin where audit list item and create audit button navigated to a wrong URL.
diff --git a/.changeset/poor-crews-battle.md b/.changeset/poor-crews-battle.md
new file mode 100644
index 0000000000..e05391ef5e
--- /dev/null
+++ b/.changeset/poor-crews-battle.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-plugin-api': minor
+---
+
+Moved `loggerToWinstonLogger` to `@backstage/backend-common`.
diff --git a/.changeset/popular-boxes-think.md b/.changeset/popular-boxes-think.md
new file mode 100644
index 0000000000..91ac649643
--- /dev/null
+++ b/.changeset/popular-boxes-think.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+Removed unused package `type-fest`
diff --git a/.changeset/popular-cameras-worry.md b/.changeset/popular-cameras-worry.md
new file mode 100644
index 0000000000..a5cbd6562b
--- /dev/null
+++ b/.changeset/popular-cameras-worry.md
@@ -0,0 +1,6 @@
+---
+'@backstage/catalog-client': patch
+'@backstage/plugin-catalog-backend': patch
+---
+
+Enable the `by-refs` endpoint to receive `fields` through the POST body as well as through query parameters.
diff --git a/.changeset/red-tables-train.md b/.changeset/red-tables-train.md
new file mode 100644
index 0000000000..031d3720fc
--- /dev/null
+++ b/.changeset/red-tables-train.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-react': patch
+---
+
+Add a reusable pop over `EntityPeekAheadPopover` component. It shows more details about the associated entity. See the playbook here https://backstage.io/storybook/?path=/story/catalog-entitypeekaheadpopover--default
diff --git a/.changeset/renovate-0783312.md b/.changeset/renovate-0783312.md
new file mode 100644
index 0000000000..ef3a1c0bfa
--- /dev/null
+++ b/.changeset/renovate-0783312.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-scaffolder': patch
+---
+
+Updated dependency `use-immer` to `^0.8.0`.
diff --git a/.changeset/renovate-492e599.md b/.changeset/renovate-492e599.md
new file mode 100644
index 0000000000..7c98b20f8d
--- /dev/null
+++ b/.changeset/renovate-492e599.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-bitbucket-cloud-common': patch
+---
+
+Updated dependency `ts-morph` to `^17.0.0`.
diff --git a/.changeset/renovate-a3feeae.md b/.changeset/renovate-a3feeae.md
new file mode 100644
index 0000000000..c5aa58d5f2
--- /dev/null
+++ b/.changeset/renovate-a3feeae.md
@@ -0,0 +1,7 @@
+---
+'@backstage/backend-common': patch
+'@backstage/backend-test-utils': patch
+'@backstage/plugin-catalog-backend': patch
+---
+
+Updated dependency `better-sqlite3` to `^8.0.0`.
diff --git a/.changeset/renovate-e7f8e3a.md b/.changeset/renovate-e7f8e3a.md
new file mode 100644
index 0000000000..6947a05d2d
--- /dev/null
+++ b/.changeset/renovate-e7f8e3a.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-permission-react': patch
+'@backstage/plugin-playlist': patch
+---
+
+Updated dependency `swr` to `^2.0.0`.
diff --git a/.changeset/sharp-icons-obey.md b/.changeset/sharp-icons-obey.md
new file mode 100644
index 0000000000..2620dd9a07
--- /dev/null
+++ b/.changeset/sharp-icons-obey.md
@@ -0,0 +1,6 @@
+---
+'@backstage/plugin-techdocs-react': patch
+'@backstage/plugin-scaffolder': patch
+---
+
+Explicitly declaring children as optional props to facilitate react 18 changes
diff --git a/.changeset/spotty-numbers-dream.md b/.changeset/spotty-numbers-dream.md
new file mode 100644
index 0000000000..a40aa1e781
--- /dev/null
+++ b/.changeset/spotty-numbers-dream.md
@@ -0,0 +1,5 @@
+---
+'@backstage/repo-tools': patch
+---
+
+Updates Api-extractor and api-documenter version
diff --git a/.changeset/ten-peas-grab.md b/.changeset/ten-peas-grab.md
new file mode 100644
index 0000000000..c3022bb627
--- /dev/null
+++ b/.changeset/ten-peas-grab.md
@@ -0,0 +1,19 @@
+---
+'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch
+'@backstage/plugin-catalog-backend-module-bitbucket-server': patch
+'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch
+'@backstage/plugin-catalog-backend-module-msgraph': patch
+'@backstage/plugin-catalog-backend-module-gerrit': patch
+'@backstage/plugin-catalog-backend-module-github': patch
+'@backstage/plugin-catalog-backend-module-gitlab': patch
+'@backstage/plugin-events-backend-module-aws-sqs': patch
+'@backstage/plugin-catalog-backend-module-azure': patch
+'@backstage/plugin-catalog-backend-module-aws': patch
+'@backstage/plugin-scaffolder-backend': patch
+'@backstage/backend-app-api': patch
+'@backstage/plugin-catalog-backend': patch
+'@backstage/plugin-events-backend': patch
+'@backstage/plugin-app-backend': patch
+---
+
+Switched imports of `loggerToWinstonLogger` to `@backstage/backend-common`.
diff --git a/.changeset/tiny-cooks-hide.md b/.changeset/tiny-cooks-hide.md
new file mode 100644
index 0000000000..feab4b65d2
--- /dev/null
+++ b/.changeset/tiny-cooks-hide.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-defaults': patch
+---
+
+The new root HTTP router service is now installed by default.
diff --git a/.github/uffizzi/uffizzi.production.app-config.yaml b/.github/uffizzi/uffizzi.production.app-config.yaml
index 56055c8342..2e45740875 100644
--- a/.github/uffizzi/uffizzi.production.app-config.yaml
+++ b/.github/uffizzi/uffizzi.production.app-config.yaml
@@ -36,6 +36,16 @@ catalog:
- type: url
target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/all.yaml
+ - type: url
+ target: https://github.com/backstage/backstage/blob/master/packages/catalog-model/examples/acme-corp.yaml
+ rules:
+ - allow: [User, Group]
+
+ - type: url
+ target: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/sample-templates/all-templates.yaml
+ rules:
+ - allow: [Template]
+
proxy:
'/circleci/api':
target: https://circleci.com/api/v1.1
diff --git a/.github/vale/config.ini b/.github/vale/config.ini
deleted file mode 100644
index 36acb2c058..0000000000
--- a/.github/vale/config.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-StylesPath = .
-Vocab = Backstage
-
-[*.md]
-BasedOnStyles = Vale
-Vale.Terms = NO
diff --git a/.github/workflows/automate_stale.yml b/.github/workflows/automate_stale.yml
index 1d8aa525a9..452ecc48d6 100644
--- a/.github/workflows/automate_stale.yml
+++ b/.github/workflows/automate_stale.yml
@@ -8,7 +8,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- - uses: actions/stale@v6
+ - uses: actions/stale@v7
id: stale
with:
stale-issue-message: >
diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml
index 1a86f8de71..00b7d6d38d 100644
--- a/.github/workflows/uffizzi-build.yml
+++ b/.github/workflows/uffizzi-build.yml
@@ -52,7 +52,7 @@ jobs:
- name: Docker metadata
id: meta
- uses: docker/metadata-action@v3
+ uses: docker/metadata-action@v4
with:
images: registry.uffizzi.com/${{ env.UUID_TAG_APP }}
tags: type=raw,value=60d
diff --git a/.vale.ini b/.vale.ini
index fd1ea53b0d..fa7864a878 100644
--- a/.vale.ini
+++ b/.vale.ini
@@ -1,4 +1,7 @@
-StylesPath = .github/styles
+StylesPath = .github/vale
+
+Vocab = Backstage
[*.md]
BasedOnStyles = Vale
+Vale.Terms = NO
diff --git a/docs/features/software-catalog/api.md b/docs/features/software-catalog/api.md
index afd9a0af93..3ca7e5ef49 100644
--- a/docs/features/software-catalog/api.md
+++ b/docs/features/software-catalog/api.md
@@ -246,6 +246,37 @@ value. These are special in that they form the entity's unique
The return type is JSON, as a single [`Entity`](descriptor-format.md), or a 404
error if there was no entity with that reference triplet.
+### `POST /entities/by-refs`
+
+Gets a batch of entities by their entity refs. This is useful in contexts where
+you want to fetch a large number of specific entities efficiently, for example
+in GraphQL resolvers.
+
+The request body is JSON, on the form
+
+```json
+{
+ "entityRefs": ["component:default/foo", "api:default/bar"],
+ "fields": ["kind", "metadata.name"]
+}
+```
+
+where each `entityRefs` entry is an entity ref that you want to fetch. The
+`fields` array is optional and works the same way as the `GET /entities` fields
+above, e.g. it's used to fetch only certain slices of each entity.
+
+The return type is JSON, on the form
+
+```json
+{
+ "items": [{ "kind": "Component", "metadata": { "name": "foo" } }, null]
+}
+```
+
+where the `items` array has _the same length_ and _the same order_ as the input
+`entityRefs` array. Each element contains the corresponding entity data, or
+`null` if no entity existed in the catalog with that ref.
+
## Locations
TODO
diff --git a/docs/getting-started/keeping-backstage-updated.md b/docs/getting-started/keeping-backstage-updated.md
index 8e130e7094..e7324f4603 100644
--- a/docs/getting-started/keeping-backstage-updated.md
+++ b/docs/getting-started/keeping-backstage-updated.md
@@ -47,7 +47,7 @@ For this reason, any changes made to the template are documented along with
upgrade instructions in the
[changelog](https://github.com/backstage/backstage/blob/master/packages/create-app/CHANGELOG.md)
of the `@backstage/create-app` package. We recommend peeking at this changelog
--for any applicable updates when upgrading packages. As an alternative, the
+for any applicable updates when upgrading packages. As an alternative, the
[Backstage Upgrade Helper](https://backstage.github.io/upgrade-helper/) provides
a consolidated view of all the changes between two versions of Backstage. You
can find the current version of your Backstage installation in `backstage.json`.
diff --git a/microsite/yarn.lock b/microsite/yarn.lock
index e86a400340..3bc81619e3 100644
--- a/microsite/yarn.lock
+++ b/microsite/yarn.lock
@@ -5506,13 +5506,13 @@ __metadata:
linkType: hard
"json5@npm:^1.0.1":
- version: 1.0.1
- resolution: "json5@npm:1.0.1"
+ version: 1.0.2
+ resolution: "json5@npm:1.0.2"
dependencies:
minimist: ^1.2.0
bin:
json5: lib/cli.js
- checksum: e76ea23dbb8fc1348c143da628134a98adf4c5a4e8ea2adaa74a80c455fc2cdf0e2e13e6398ef819bfe92306b610ebb2002668ed9fc1af386d593691ef346fc3
+ checksum: 866458a8c58a95a49bef3adba929c625e82532bcff1fe93f01d29cb02cac7c3fe1f4b79951b7792c2da9de0b32871a8401a6e3c5b36778ad852bf5b8a61165d7
languageName: node
linkType: hard
diff --git a/package.json b/package.json
index f87d4ae1f4..4f89135a26 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,7 @@
"build:backend": "yarn workspace backend build",
"build:all": "backstage-cli repo build --all",
"build:api-reports": "yarn build:api-reports:only --tsc",
- "build:api-reports:only": "backstage-repo-tools api-reports --allow-warnings 'packages/core-components,plugins/+(catalog|catalog-import|git-release-manager|jenkins|kubernetes)'",
+ "build:api-reports:only": "backstage-repo-tools api-reports --allow-warnings 'packages/core-components,plugins/+(catalog|catalog-import|git-release-manager|jenkins|kubernetes)' -o ae-wrong-input-file-type",
"build:api-docs": "LANG=en_EN yarn build:api-reports --docs",
"tsc": "tsc",
"tsc:full": "backstage-cli repo clean && tsc --skipLibCheck false --incremental false",
diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md
index fa3f3bec2e..1ff40c8b5d 100644
--- a/packages/backend-app-api/api-report.md
+++ b/packages/backend-app-api/api-report.md
@@ -4,15 +4,17 @@
```ts
import { BackendFeature } from '@backstage/backend-plugin-api';
-import { CacheService } from '@backstage/backend-plugin-api';
import { ConfigService } from '@backstage/backend-plugin-api';
-import { DatabaseService } from '@backstage/backend-plugin-api';
import { ExtensionPoint } from '@backstage/backend-plugin-api';
+import { Handler } from 'express';
import { HttpRouterService } from '@backstage/backend-plugin-api';
import { LifecycleService } from '@backstage/backend-plugin-api';
import { LoggerService } from '@backstage/backend-plugin-api';
import { PermissionsService } from '@backstage/backend-plugin-api';
+import { PluginCacheManager } from '@backstage/backend-common';
+import { PluginDatabaseManager } from '@backstage/backend-common';
import { PluginEndpointDiscovery } from '@backstage/backend-common';
+import { RootHttpRouterService } from '@backstage/backend-plugin-api';
import { RootLifecycleService } from '@backstage/backend-plugin-api';
import { RootLoggerService } from '@backstage/backend-plugin-api';
import { SchedulerService } from '@backstage/backend-plugin-api';
@@ -34,7 +36,7 @@ export interface Backend {
// @public (undocumented)
export const cacheFactory: (
options?: undefined,
-) => ServiceFactory;
+) => ServiceFactory;
// @public (undocumented)
export const configFactory: (
@@ -55,7 +57,7 @@ export interface CreateSpecializedBackendOptions {
// @public (undocumented)
export const databaseFactory: (
options?: undefined,
-) => ServiceFactory;
+) => ServiceFactory;
// @public (undocumented)
export const discoveryFactory: (
@@ -69,7 +71,7 @@ export const httpRouterFactory: (
// @public (undocumented)
export type HttpRouterFactoryOptions = {
- indexPlugin?: string;
+ getPath(pluginId: string): string;
};
// @public
@@ -87,6 +89,17 @@ export const permissionsFactory: (
options?: undefined,
) => ServiceFactory;
+// @public (undocumented)
+export const rootHttpRouterFactory: (
+ options?: RootHttpRouterFactoryOptions | undefined,
+) => ServiceFactory;
+
+// @public (undocumented)
+export type RootHttpRouterFactoryOptions = {
+ indexPath?: string | false;
+ middleware?: Handler[];
+};
+
// @public
export const rootLifecycleFactory: (
options?: undefined,
diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json
index 93230341df..80598ec93d 100644
--- a/packages/backend-app-api/package.json
+++ b/packages/backend-app-api/package.json
@@ -38,6 +38,7 @@
"@backstage/backend-tasks": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/plugin-permission-node": "workspace:^",
+ "@types/express": "^4.17.6",
"express": "^4.17.1",
"express-promise-router": "^4.1.0",
"winston": "^3.2.1"
diff --git a/packages/backend-app-api/src/services/implementations/configService.ts b/packages/backend-app-api/src/services/implementations/configService.ts
index f58a756c64..6bb84aa5a1 100644
--- a/packages/backend-app-api/src/services/implementations/configService.ts
+++ b/packages/backend-app-api/src/services/implementations/configService.ts
@@ -14,11 +14,13 @@
* limitations under the License.
*/
-import { loadBackendConfig } from '@backstage/backend-common';
+import {
+ loadBackendConfig,
+ loggerToWinstonLogger,
+} from '@backstage/backend-common';
import {
coreServices,
createServiceFactory,
- loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
/** @public */
diff --git a/packages/backend-app-api/src/services/implementations/httpRouterService.test.ts b/packages/backend-app-api/src/services/implementations/httpRouterService.test.ts
new file mode 100644
index 0000000000..89f6db2ac8
--- /dev/null
+++ b/packages/backend-app-api/src/services/implementations/httpRouterService.test.ts
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2022 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 {
+ HttpRouterService,
+ ServiceFactory,
+} from '@backstage/backend-plugin-api';
+import { httpRouterFactory } from './httpRouterService';
+
+describe('httpRouterFactory', () => {
+ it('should register plugin paths', async () => {
+ const rootHttpRouter = { use: jest.fn() };
+ const factory = httpRouterFactory() as Exclude<
+ ServiceFactory,
+ { scope: 'root' }
+ >;
+ const innerFactory = await factory.factory({ rootHttpRouter });
+
+ const handler1 = () => {};
+ const router1 = await innerFactory({ plugin: { getId: () => 'test1' } });
+ router1.use(handler1);
+ expect(rootHttpRouter.use).toHaveBeenCalledTimes(1);
+ expect(rootHttpRouter.use).toHaveBeenCalledWith('/api/test1', handler1);
+
+ const handler2 = () => {};
+ const router2 = await innerFactory({ plugin: { getId: () => 'test2' } });
+ router2.use(handler2);
+ expect(rootHttpRouter.use).toHaveBeenCalledTimes(2);
+ expect(rootHttpRouter.use).toHaveBeenCalledWith('/api/test2', handler2);
+ });
+
+ it('should use custom path generator', async () => {
+ const rootHttpRouter = { use: jest.fn() };
+ const factory = httpRouterFactory({
+ getPath: id => `/some/${id}/path`,
+ }) as Exclude, { scope: 'root' }>;
+ const innerFactory = await factory.factory({ rootHttpRouter });
+
+ const handler1 = () => {};
+ const router1 = await innerFactory({ plugin: { getId: () => 'test1' } });
+ router1.use(handler1);
+ expect(rootHttpRouter.use).toHaveBeenCalledTimes(1);
+ expect(rootHttpRouter.use).toHaveBeenCalledWith(
+ '/some/test1/path',
+ handler1,
+ );
+
+ const handler2 = () => {};
+ const router2 = await innerFactory({ plugin: { getId: () => 'test2' } });
+ router2.use(handler2);
+ expect(rootHttpRouter.use).toHaveBeenCalledTimes(2);
+ expect(rootHttpRouter.use).toHaveBeenCalledWith(
+ '/some/test2/path',
+ handler2,
+ );
+ });
+});
diff --git a/packages/backend-app-api/src/services/implementations/httpRouterService.ts b/packages/backend-app-api/src/services/implementations/httpRouterService.ts
index 2021589a50..f1fc089ea3 100644
--- a/packages/backend-app-api/src/services/implementations/httpRouterService.ts
+++ b/packages/backend-app-api/src/services/implementations/httpRouterService.ts
@@ -18,49 +18,33 @@ import {
createServiceFactory,
coreServices,
} from '@backstage/backend-plugin-api';
-import Router from 'express-promise-router';
import { Handler } from 'express';
-import { createServiceBuilder } from '@backstage/backend-common';
/**
* @public
*/
export type HttpRouterFactoryOptions = {
/**
- * The plugin ID used for the index route. Defaults to 'app'
+ * A callback used to generate the path for each plugin, defaults to `/api/{pluginId}`.
*/
- indexPlugin?: string;
+ getPath(pluginId: string): string;
};
/** @public */
export const httpRouterFactory = createServiceFactory({
service: coreServices.httpRouter,
deps: {
- config: coreServices.config,
plugin: coreServices.pluginMetadata,
+ rootHttpRouter: coreServices.rootHttpRouter,
},
- async factory({ config }, options?: HttpRouterFactoryOptions) {
- const defaultPluginId = options?.indexPlugin ?? 'app';
-
- const apiRouter = Router();
- const rootRouter = Router();
-
- const service = createServiceBuilder(module)
- .loadConfig(config)
- .addRouter('/api', apiRouter)
- .addRouter('', rootRouter);
-
- await service.start();
+ async factory({ rootHttpRouter }, options?: HttpRouterFactoryOptions) {
+ const getPath = options?.getPath ?? (id => `/api/${id}`);
return async ({ plugin }) => {
- const pluginId = plugin.getId();
+ const path = getPath(plugin.getId());
return {
use(handler: Handler) {
- if (pluginId === defaultPluginId) {
- rootRouter.use(handler);
- } else {
- apiRouter.use(`/${pluginId}`, handler);
- }
+ rootHttpRouter.use(path, handler);
},
};
};
diff --git a/packages/backend-app-api/src/services/implementations/index.ts b/packages/backend-app-api/src/services/implementations/index.ts
index c87011d570..2365ff36f4 100644
--- a/packages/backend-app-api/src/services/implementations/index.ts
+++ b/packages/backend-app-api/src/services/implementations/index.ts
@@ -25,6 +25,8 @@ export { schedulerFactory } from './schedulerService';
export { tokenManagerFactory } from './tokenManagerService';
export { urlReaderFactory } from './urlReaderService';
export { httpRouterFactory } from './httpRouterService';
+export { rootHttpRouterFactory } from './rootHttpRouterService';
export { lifecycleFactory } from './lifecycleService';
export { rootLifecycleFactory } from './rootLifecycleService';
export type { HttpRouterFactoryOptions } from './httpRouterService';
+export type { RootHttpRouterFactoryOptions } from './rootHttpRouterService';
diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouterService.test.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouterService.test.ts
new file mode 100644
index 0000000000..fea99b0df9
--- /dev/null
+++ b/packages/backend-app-api/src/services/implementations/rootHttpRouterService.test.ts
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2022 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 { findConflictingPath } from './rootHttpRouterService';
+
+describe('findConflictingPath', () => {
+ it('finds conflicts when present', () => {
+ expect(findConflictingPath(['/a'], '/a')).toBe('/a');
+ expect(findConflictingPath(['/b'], '/a')).toBe(undefined);
+ expect(findConflictingPath(['/a'], '/a/b')).toBe('/a');
+ expect(findConflictingPath(['/a'], '/aa/b')).toBe(undefined);
+ expect(findConflictingPath(['/aa'], '/a/b')).toBe(undefined);
+ expect(findConflictingPath(['/a/b'], '/a')).toBe('/a/b');
+ expect(findConflictingPath(['/a/b'], '/aa')).toBe(undefined);
+ expect(findConflictingPath(['/b/a'], '/a')).toBe(undefined);
+ expect(findConflictingPath(['/a'], '/aa')).toBe(undefined);
+ });
+});
diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouterService.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouterService.ts
new file mode 100644
index 0000000000..dae7474793
--- /dev/null
+++ b/packages/backend-app-api/src/services/implementations/rootHttpRouterService.ts
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2022 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 {
+ createServiceFactory,
+ coreServices,
+} from '@backstage/backend-plugin-api';
+import Router from 'express-promise-router';
+import { Handler } from 'express';
+import { createServiceBuilder } from '@backstage/backend-common';
+
+/**
+ * @public
+ */
+export type RootHttpRouterFactoryOptions = {
+ /**
+ * The path to forward all unmatched requests to. Defaults to '/api/app'
+ */
+ indexPath?: string | false;
+
+ /**
+ * Middlewares that are added before all other routes.
+ */
+ middleware?: Handler[];
+};
+
+/** @public */
+export const rootHttpRouterFactory = createServiceFactory({
+ service: coreServices.rootHttpRouter,
+ deps: {
+ config: coreServices.config,
+ lifecycle: coreServices.rootLifecycle,
+ },
+ async factory({ config, lifecycle }, options?: RootHttpRouterFactoryOptions) {
+ const indexPath = options?.indexPath ?? '/api/app';
+
+ const namedRouter = Router();
+ const indexRouter = Router();
+
+ const service = createServiceBuilder(module).loadConfig(config);
+
+ for (const middleware of options?.middleware ?? []) {
+ service.addRouter('', middleware);
+ }
+
+ service.addRouter('', namedRouter).addRouter('', indexRouter);
+
+ const server = await service.start();
+ // Stop method isn't part of the public API, let's fix that once we move the implementation here.
+ const stoppableServer = server as typeof server & {
+ stop: (cb: (error?: Error) => void) => void;
+ };
+
+ lifecycle.addShutdownHook({
+ async fn() {
+ await new Promise((resolve, reject) => {
+ stoppableServer.stop((error?: Error) => {
+ if (error) {
+ reject(error);
+ } else {
+ resolve();
+ }
+ });
+ });
+ },
+ labels: { service: 'rootHttpRouter' },
+ });
+
+ const existingPaths = new Array();
+
+ return {
+ use: (path: string, handler: Handler) => {
+ if (path.match(/^[/\s]*$/)) {
+ throw new Error(`Root router path may not be empty`);
+ }
+ const conflictingPath = findConflictingPath(existingPaths, path);
+ if (conflictingPath) {
+ throw new Error(
+ `Path ${path} conflicts with the existing path ${conflictingPath}`,
+ );
+ }
+ existingPaths.push(path);
+ namedRouter.use(path, handler);
+
+ if (indexPath === path) {
+ indexRouter.use(handler);
+ }
+ },
+ };
+ },
+});
+
+function normalizePath(path: string): string {
+ return path.replace(/\/*$/, '/');
+}
+
+export function findConflictingPath(
+ paths: string[],
+ newPath: string,
+): string | undefined {
+ const normalizedNewPath = normalizePath(newPath);
+ for (const path of paths) {
+ const normalizedPath = normalizePath(path);
+ if (normalizedPath.startsWith(normalizedNewPath)) {
+ return path;
+ }
+ if (normalizedNewPath.startsWith(normalizedPath)) {
+ return path;
+ }
+ }
+ return undefined;
+}
diff --git a/packages/backend-app-api/src/services/implementations/rootLifecycleService.ts b/packages/backend-app-api/src/services/implementations/rootLifecycleService.ts
index c4ad4678ba..3797e6ffc5 100644
--- a/packages/backend-app-api/src/services/implementations/rootLifecycleService.ts
+++ b/packages/backend-app-api/src/services/implementations/rootLifecycleService.ts
@@ -13,10 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+import { loggerToWinstonLogger } from '@backstage/backend-common';
import {
createServiceFactory,
coreServices,
- loggerToWinstonLogger,
LifecycleServiceShutdownHook,
RootLifecycleService,
} from '@backstage/backend-plugin-api';
diff --git a/packages/backend-app-api/src/services/implementations/tokenManagerService.ts b/packages/backend-app-api/src/services/implementations/tokenManagerService.ts
index 6a2d47ae14..025830afc7 100644
--- a/packages/backend-app-api/src/services/implementations/tokenManagerService.ts
+++ b/packages/backend-app-api/src/services/implementations/tokenManagerService.ts
@@ -17,9 +17,11 @@
import {
coreServices,
createServiceFactory,
- loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
-import { ServerTokenManager } from '@backstage/backend-common';
+import {
+ loggerToWinstonLogger,
+ ServerTokenManager,
+} from '@backstage/backend-common';
/** @public */
export const tokenManagerFactory = createServiceFactory({
diff --git a/packages/backend-app-api/src/services/implementations/urlReaderService.ts b/packages/backend-app-api/src/services/implementations/urlReaderService.ts
index b68be74d8c..758b555d66 100644
--- a/packages/backend-app-api/src/services/implementations/urlReaderService.ts
+++ b/packages/backend-app-api/src/services/implementations/urlReaderService.ts
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-import { UrlReaders } from '@backstage/backend-common';
+import { loggerToWinstonLogger, UrlReaders } from '@backstage/backend-common';
import {
coreServices,
createServiceFactory,
- loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
/** @public */
diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md
index e8b41e21bb..43260c2a64 100644
--- a/packages/backend-common/api-report.md
+++ b/packages/backend-common/api-report.md
@@ -12,6 +12,9 @@ import { AzureIntegration } from '@backstage/integration';
import { BitbucketCloudIntegration } from '@backstage/integration';
import { BitbucketIntegration } from '@backstage/integration';
import { BitbucketServerIntegration } from '@backstage/integration';
+import { CacheClient } from '@backstage/backend-plugin-api';
+import { CacheClientOptions } from '@backstage/backend-plugin-api';
+import { CacheClientSetOptions } from '@backstage/backend-plugin-api';
import { Config } from '@backstage/config';
import cors from 'cors';
import Docker from 'dockerode';
@@ -24,12 +27,14 @@ import { GithubCredentialsProvider } from '@backstage/integration';
import { GithubIntegration } from '@backstage/integration';
import { GitLabIntegration } from '@backstage/integration';
import { isChildPath } from '@backstage/cli-common';
-import { JsonValue } from '@backstage/types';
import { Knex } from 'knex';
import { KubeConfig } from '@kubernetes/client-node';
import { LoadConfigOptionsRemote } from '@backstage/config-loader';
import { Logger } from 'winston';
+import { LoggerService } from '@backstage/backend-plugin-api';
import { MergeResult } from 'isomorphic-git';
+import { CacheService as PluginCacheManager } from '@backstage/backend-plugin-api';
+import { DatabaseService as PluginDatabaseManager } from '@backstage/backend-plugin-api';
import { DiscoveryService as PluginEndpointDiscovery } from '@backstage/backend-plugin-api';
import { PushResult } from 'isomorphic-git';
import { Readable } from 'stream';
@@ -46,6 +51,8 @@ import { SearchOptions } from '@backstage/backend-plugin-api';
import { SearchResponse } from '@backstage/backend-plugin-api';
import { SearchResponseFile } from '@backstage/backend-plugin-api';
import { Server } from 'http';
+import { TokenManagerService as TokenManager } from '@backstage/backend-plugin-api';
+import { TransportStreamOptions } from 'winston-transport';
import { UrlReaderService as UrlReader } from '@backstage/backend-plugin-api';
import { V1PodTemplateSpec } from '@kubernetes/client-node';
import * as winston from 'winston';
@@ -163,26 +170,11 @@ export class BitbucketUrlReader implements UrlReader {
toString(): string;
}
-// @public
-export interface CacheClient {
- delete(key: string): Promise;
- get(key: string): Promise;
- set(
- key: string,
- value: JsonValue,
- options?: CacheClientSetOptions,
- ): Promise;
-}
+export { CacheClient };
-// @public
-export type CacheClientOptions = {
- defaultTtl?: number;
-};
+export { CacheClientOptions };
-// @public
-export type CacheClientSetOptions = {
- ttl?: number;
-};
+export { CacheClientSetOptions };
// @public
export class CacheManager {
@@ -515,21 +507,18 @@ export function loadBackendConfig(options: {
argv: string[];
}): Promise;
+// @public (undocumented)
+export function loggerToWinstonLogger(
+ logger: LoggerService,
+ opts?: TransportStreamOptions,
+): Logger;
+
// @public
export function notFoundHandler(): RequestHandler;
-// @public
-export type PluginCacheManager = {
- getClient: (options?: CacheClientOptions) => CacheClient;
-};
+export { PluginCacheManager };
-// @public
-export interface PluginDatabaseManager {
- getClient(): Promise;
- migrations?: {
- skip?: boolean;
- };
-}
+export { PluginDatabaseManager };
export { PluginEndpointDiscovery };
@@ -710,13 +699,7 @@ export interface StatusCheckHandlerOptions {
statusCheck?: StatusCheck;
}
-// @public
-export interface TokenManager {
- authenticate(token: string): Promise;
- getToken(): Promise<{
- token: string;
- }>;
-}
+export { TokenManager };
export { UrlReader };
diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json
index fc131723a7..aff5e56abb 100644
--- a/packages/backend-common/package.json
+++ b/packages/backend-common/package.json
@@ -83,6 +83,7 @@
"tar": "^6.1.12",
"uuid": "^8.3.2",
"winston": "^3.2.1",
+ "winston-transport": "^4.5.0",
"yauzl": "^2.10.0",
"yn": "^4.0.0"
},
@@ -114,7 +115,7 @@
"@types/webpack-env": "^1.15.2",
"@types/yauzl": "^2.10.0",
"aws-sdk-mock": "^5.2.1",
- "better-sqlite3": "^7.5.0",
+ "better-sqlite3": "^8.0.0",
"http-errors": "^2.0.0",
"mock-fs": "^5.1.0",
"msw": "^0.49.0",
diff --git a/packages/backend-common/src/cache/CacheClient.ts b/packages/backend-common/src/cache/CacheClient.ts
index 96982edeaa..47cb786f14 100644
--- a/packages/backend-common/src/cache/CacheClient.ts
+++ b/packages/backend-common/src/cache/CacheClient.ts
@@ -14,57 +14,23 @@
* limitations under the License.
*/
+import {
+ CacheClient,
+ CacheClientSetOptions,
+} from '@backstage/backend-plugin-api';
import { JsonValue } from '@backstage/types';
import { createHash } from 'crypto';
import Keyv from 'keyv';
+export type {
+ CacheClient,
+ CacheClientSetOptions,
+} from '@backstage/backend-plugin-api';
+
type CacheClientArgs = {
client: Keyv;
};
-/**
- * Options passed to {@link CacheClient.set}.
- *
- * @public
- */
-export type CacheClientSetOptions = {
- /**
- * Optional TTL in milliseconds. Defaults to the TTL provided when the client
- * was set up (or no TTL if none are provided).
- */
- ttl?: number;
-};
-
-/**
- * A pre-configured, storage agnostic cache client suitable for use by
- * Backstage plugins.
- *
- * @public
- */
-export interface CacheClient {
- /**
- * Reads data from a cache store for the given key. If no data was found,
- * returns undefined.
- */
- get(key: string): Promise;
-
- /**
- * Writes the given data to a cache store, associated with the given key. An
- * optional TTL may also be provided, otherwise it defaults to the TTL that
- * was provided when the client was instantiated.
- */
- set(
- key: string,
- value: JsonValue,
- options?: CacheClientSetOptions,
- ): Promise;
-
- /**
- * Removes the given key from the cache store.
- */
- delete(key: string): Promise;
-}
-
/**
* A basic, concrete implementation of the CacheClient, suitable for almost
* all uses in Backstage.
diff --git a/packages/backend-common/src/cache/types.ts b/packages/backend-common/src/cache/types.ts
index 5cf8323c52..40e30b1059 100644
--- a/packages/backend-common/src/cache/types.ts
+++ b/packages/backend-common/src/cache/types.ts
@@ -15,21 +15,11 @@
*/
import { Logger } from 'winston';
-import { CacheClient } from './CacheClient';
-/**
- * Options given when constructing a {@link CacheClient}.
- *
- * @public
- */
-export type CacheClientOptions = {
- /**
- * An optional default TTL (in milliseconds) to be set when getting a client
- * instance. If not provided, data will persist indefinitely by default (or
- * can be configured per entry at set-time).
- */
- defaultTtl?: number;
-};
+export type {
+ CacheService as PluginCacheManager,
+ CacheClientOptions,
+} from '@backstage/backend-plugin-api';
/**
* Options given when constructing a {@link CacheManager}.
@@ -48,21 +38,3 @@ export type CacheManagerOptions = {
*/
onError?: (err: Error) => void;
};
-
-/**
- * Manages access to cache stores that plugins get.
- *
- * @public
- */
-export type PluginCacheManager = {
- /**
- * Provides backend plugins cache connections for themselves.
- *
- * @remarks
- *
- * The purpose of this method is to allow plugins to get isolated data stores
- * so that plugins are discouraged from cache-level integration and/or cache
- * key collisions.
- */
- getClient: (options?: CacheClientOptions) => CacheClient;
-};
diff --git a/packages/backend-common/src/database/types.ts b/packages/backend-common/src/database/types.ts
index 2fa8b749a8..2d59cf636e 100644
--- a/packages/backend-common/src/database/types.ts
+++ b/packages/backend-common/src/database/types.ts
@@ -17,32 +17,7 @@
import { Config } from '@backstage/config';
import { Knex } from 'knex';
-/**
- * The PluginDatabaseManager manages access to databases that Plugins get.
- *
- * @public
- */
-export interface PluginDatabaseManager {
- /**
- * getClient provides backend plugins database connections for itself.
- *
- * The purpose of this method is to allow plugins to get isolated data
- * stores so that plugins are discouraged from database integration.
- */
- getClient(): Promise;
-
- /**
- * This property is used to control the behavior of database migrations.
- */
- migrations?: {
- /**
- * skip database migrations. Useful if connecting to a read-only database.
- *
- * @defaultValue false
- */
- skip?: boolean;
- };
-}
+export type { DatabaseService as PluginDatabaseManager } from '@backstage/backend-plugin-api';
/**
* DatabaseConnector manages an underlying Knex database driver.
diff --git a/packages/backend-common/src/logging/index.ts b/packages/backend-common/src/logging/index.ts
index 4657dd4101..ff2315c51b 100644
--- a/packages/backend-common/src/logging/index.ts
+++ b/packages/backend-common/src/logging/index.ts
@@ -22,3 +22,4 @@ export {
redactWinstonLogLine,
} from './rootLogger';
export * from './voidLogger';
+export { loggerToWinstonLogger } from './loggerToWinstonLogger';
diff --git a/packages/backend-plugin-api/src/services/helpers/loggerToWinstonLogger.ts b/packages/backend-common/src/logging/loggerToWinstonLogger.ts
similarity index 96%
rename from packages/backend-plugin-api/src/services/helpers/loggerToWinstonLogger.ts
rename to packages/backend-common/src/logging/loggerToWinstonLogger.ts
index 6f435a250a..f15bd5be81 100644
--- a/packages/backend-plugin-api/src/services/helpers/loggerToWinstonLogger.ts
+++ b/packages/backend-common/src/logging/loggerToWinstonLogger.ts
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import { LoggerService } from '../definitions';
+import { LoggerService } from '@backstage/backend-plugin-api';
import { Logger as WinstonLogger, createLogger } from 'winston';
import Transport, { TransportStreamOptions } from 'winston-transport';
diff --git a/packages/backend-common/src/tokens/types.ts b/packages/backend-common/src/tokens/types.ts
index 2fa771b7e2..4e0fd698df 100644
--- a/packages/backend-common/src/tokens/types.ts
+++ b/packages/backend-common/src/tokens/types.ts
@@ -14,26 +14,4 @@
* limitations under the License.
*/
-/**
- * Interface for creating and validating tokens.
- *
- * @public
- */
-export interface TokenManager {
- /**
- * Fetches a valid token.
- *
- * @remarks
- *
- * Tokens are valid for roughly one hour; the actual deadline is set in the
- * payload `exp` claim. Never hold on to tokens for reuse; always ask for a
- * new one for each outgoing request. This ensures that you always get a
- * valid, fresh one.
- */
- getToken(): Promise<{ token: string }>;
-
- /**
- * Validates a given token.
- */
- authenticate(token: string): Promise;
-}
+export type { TokenManagerService as TokenManager } from '@backstage/backend-plugin-api';
diff --git a/packages/backend-defaults/src/CreateBackend.ts b/packages/backend-defaults/src/CreateBackend.ts
index a37a8c32b2..20edfc85a8 100644
--- a/packages/backend-defaults/src/CreateBackend.ts
+++ b/packages/backend-defaults/src/CreateBackend.ts
@@ -22,6 +22,7 @@ import {
databaseFactory,
discoveryFactory,
httpRouterFactory,
+ rootHttpRouterFactory,
lifecycleFactory,
rootLifecycleFactory,
loggerFactory,
@@ -45,6 +46,7 @@ export const defaultServiceFactories = [
tokenManagerFactory,
urlReaderFactory,
httpRouterFactory,
+ rootHttpRouterFactory,
lifecycleFactory,
rootLifecycleFactory,
];
diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md
index 9c6ffe6dd5..a829f6200c 100644
--- a/packages/backend-plugin-api/api-report.md
+++ b/packages/backend-plugin-api/api-report.md
@@ -7,14 +7,11 @@
import { Config } from '@backstage/config';
import { Handler } from 'express';
-import { Logger } from 'winston';
+import { JsonValue } from '@backstage/types';
+import { Knex } from 'knex';
import { PermissionEvaluator } from '@backstage/plugin-permission-common';
-import { PluginCacheManager } from '@backstage/backend-common';
-import { PluginDatabaseManager } from '@backstage/backend-common';
import { PluginTaskScheduler } from '@backstage/backend-tasks';
import { Readable } from 'stream';
-import { TokenManager } from '@backstage/backend-common';
-import { TransportStreamOptions } from 'winston-transport';
// @public (undocumented)
export interface BackendFeature {
@@ -65,8 +62,31 @@ export interface BackendRegistrationPoints {
}): void;
}
-// @public (undocumented)
-export interface CacheService extends PluginCacheManager {}
+// @public
+export interface CacheClient {
+ delete(key: string): Promise;
+ get(key: string): Promise;
+ set(
+ key: string,
+ value: JsonValue,
+ options?: CacheClientSetOptions,
+ ): Promise;
+}
+
+// @public
+export type CacheClientOptions = {
+ defaultTtl?: number;
+};
+
+// @public
+export type CacheClientSetOptions = {
+ ttl?: number;
+};
+
+// @public
+export interface CacheService {
+ getClient: (options?: CacheClientOptions) => CacheClient;
+}
// @public (undocumented)
export interface ConfigService extends Config {}
@@ -82,6 +102,7 @@ export namespace coreServices {
const logger: ServiceRef;
const permissions: ServiceRef;
const pluginMetadata: ServiceRef;
+ const rootHttpRouter: ServiceRef;
const rootLifecycle: ServiceRef;
const rootLogger: ServiceRef;
const scheduler: ServiceRef;
@@ -153,8 +174,13 @@ export function createServiceRef(options: {
) => Promise | (() => ServiceFactory)>;
}): ServiceRef;
-// @public (undocumented)
-export interface DatabaseService extends PluginDatabaseManager {}
+// @public
+export interface DatabaseService {
+ getClient(): Promise;
+ migrations?: {
+ skip?: boolean;
+ };
+}
// @public
export interface DiscoveryService {
@@ -201,12 +227,6 @@ export interface LoggerService {
warn(message: string, meta?: Error | LogMeta): void;
}
-// @public (undocumented)
-export function loggerToWinstonLogger(
- logger: LoggerService,
- opts?: TransportStreamOptions,
-): Logger;
-
// @public (undocumented)
export type LogMeta = {
[name: string]: unknown;
@@ -265,6 +285,11 @@ export type ReadUrlResponse = {
etag?: string;
};
+// @public (undocumented)
+export interface RootHttpRouterService {
+ use(path: string, handler: Handler): void;
+}
+
// @public (undocumented)
export interface RootLifecycleService extends LifecycleService {}
@@ -331,8 +356,13 @@ export type ServiceRef<
$$ref: 'service';
};
-// @public (undocumented)
-export interface TokenManagerService extends TokenManager {}
+// @public
+export interface TokenManagerService {
+ authenticate(token: string): Promise;
+ getToken(): Promise<{
+ token: string;
+ }>;
+}
// @public (undocumented)
export type TypesToServiceRef = {
diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json
index 732cfa3858..dc484a33b0 100644
--- a/packages/backend-plugin-api/package.json
+++ b/packages/backend-plugin-api/package.json
@@ -33,14 +33,13 @@
"start": "backstage-cli package start"
},
"dependencies": {
- "@backstage/backend-common": "workspace:^",
"@backstage/backend-tasks": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/plugin-permission-common": "workspace:^",
+ "@backstage/types": "workspace:^",
"@types/express": "^4.17.6",
"express": "^4.17.1",
- "winston": "^3.2.1",
- "winston-transport": "^4.5.0"
+ "knex": "^2.0.0"
},
"devDependencies": {
"@backstage/cli": "workspace:^"
diff --git a/packages/backend-plugin-api/src/services/definitions/CacheService.ts b/packages/backend-plugin-api/src/services/definitions/CacheService.ts
index 79c930f435..2702fdac6d 100644
--- a/packages/backend-plugin-api/src/services/definitions/CacheService.ts
+++ b/packages/backend-plugin-api/src/services/definitions/CacheService.ts
@@ -14,7 +14,79 @@
* limitations under the License.
*/
-import { PluginCacheManager } from '@backstage/backend-common';
+import { JsonValue } from '@backstage/types';
-/** @public */
-export interface CacheService extends PluginCacheManager {}
+/**
+ * Manages access to cache stores that plugins get.
+ *
+ * @public
+ */
+export interface CacheService {
+ /**
+ * Provides backend plugins cache connections for themselves.
+ *
+ * @remarks
+ *
+ * The purpose of this method is to allow plugins to get isolated data stores
+ * so that plugins are discouraged from cache-level integration and/or cache
+ * key collisions.
+ */
+ getClient: (options?: CacheClientOptions) => CacheClient;
+}
+
+/**
+ * Options passed to {@link CacheClient.set}.
+ *
+ * @public
+ */
+export type CacheClientSetOptions = {
+ /**
+ * Optional TTL in milliseconds. Defaults to the TTL provided when the client
+ * was set up (or no TTL if none are provided).
+ */
+ ttl?: number;
+};
+
+/**
+ * A pre-configured, storage agnostic cache client suitable for use by
+ * Backstage plugins.
+ *
+ * @public
+ */
+export interface CacheClient {
+ /**
+ * Reads data from a cache store for the given key. If no data was found,
+ * returns undefined.
+ */
+ get(key: string): Promise;
+
+ /**
+ * Writes the given data to a cache store, associated with the given key. An
+ * optional TTL may also be provided, otherwise it defaults to the TTL that
+ * was provided when the client was instantiated.
+ */
+ set(
+ key: string,
+ value: JsonValue,
+ options?: CacheClientSetOptions,
+ ): Promise;
+
+ /**
+ * Removes the given key from the cache store.
+ */
+ delete(key: string): Promise;
+}
+
+/**
+ * Options given when constructing a {@link CacheClient}.
+ *
+ * @public
+ */
+export type CacheClientOptions = {
+ /**
+ * An optional default TTL (in milliseconds) to be set when getting a client
+ * instance. If not provided, data will persist indefinitely by default (or
+ * can be configured per entry at set-time).
+ */
+ defaultTtl?: number;
+};
diff --git a/packages/backend-plugin-api/src/services/definitions/DatabaseService.ts b/packages/backend-plugin-api/src/services/definitions/DatabaseService.ts
index 30f1f574f2..583dfe8b8f 100644
--- a/packages/backend-plugin-api/src/services/definitions/DatabaseService.ts
+++ b/packages/backend-plugin-api/src/services/definitions/DatabaseService.ts
@@ -14,7 +14,31 @@
* limitations under the License.
*/
-import { PluginDatabaseManager } from '@backstage/backend-common';
+import { Knex } from 'knex';
-/** @public */
-export interface DatabaseService extends PluginDatabaseManager {}
+/**
+ * The DatabaseService manages access to databases that Plugins get.
+ *gs
+ * @public
+ */
+export interface DatabaseService {
+ /**
+ * getClient provides backend plugins database connections for itself.
+ *
+ * The purpose of this method is to allow plugins to get isolated data
+ * stores so that plugins are discouraged from database integration.
+ */
+ getClient(): Promise;
+
+ /**
+ * This property is used to control the behavior of database migrations.
+ */
+ migrations?: {
+ /**
+ * skip database migrations. Useful if connecting to a read-only database.
+ *
+ * @defaultValue false
+ */
+ skip?: boolean;
+ };
+}
diff --git a/packages/backend-plugin-api/src/services/definitions/RootHttpRouterService.ts b/packages/backend-plugin-api/src/services/definitions/RootHttpRouterService.ts
new file mode 100644
index 0000000000..e583e978fa
--- /dev/null
+++ b/packages/backend-plugin-api/src/services/definitions/RootHttpRouterService.ts
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2022 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 { Handler } from 'express';
+
+/**
+ * @public
+ */
+export interface RootHttpRouterService {
+ /**
+ * Registers a handler at the root of the backend router.
+ * The path is required and may not be empty.
+ */
+ use(path: string, handler: Handler): void;
+}
diff --git a/packages/backend-plugin-api/src/services/definitions/TokenManagerService.ts b/packages/backend-plugin-api/src/services/definitions/TokenManagerService.ts
index 7fccb60c7a..c9d7edcaef 100644
--- a/packages/backend-plugin-api/src/services/definitions/TokenManagerService.ts
+++ b/packages/backend-plugin-api/src/services/definitions/TokenManagerService.ts
@@ -14,7 +14,26 @@
* limitations under the License.
*/
-import { TokenManager } from '@backstage/backend-common';
+/**
+ * Interface for creating and validating tokens.
+ *
+ * @public
+ */
+export interface TokenManagerService {
+ /**
+ * Fetches a valid token.
+ *
+ * @remarks
+ *
+ * Tokens are valid for roughly one hour; the actual deadline is set in the
+ * payload `exp` claim. Never hold on to tokens for reuse; always ask for a
+ * new one for each outgoing request. This ensures that you always get a
+ * valid, fresh one.
+ */
+ getToken(): Promise<{ token: string }>;
-/** @public */
-export interface TokenManagerService extends TokenManager {}
+ /**
+ * Validates a given token.
+ */
+ authenticate(token: string): Promise;
+}
diff --git a/packages/backend-plugin-api/src/services/definitions/coreServices.ts b/packages/backend-plugin-api/src/services/definitions/coreServices.ts
index fc96ec8be9..7de92d6d01 100644
--- a/packages/backend-plugin-api/src/services/definitions/coreServices.ts
+++ b/packages/backend-plugin-api/src/services/definitions/coreServices.ts
@@ -103,6 +103,15 @@ export namespace coreServices {
import('./PluginMetadataService').PluginMetadataService
>({ id: 'core.pluginMetadata' });
+ /**
+ * The service reference for the root scoped {@link RootHttpRouterService}.
+ *
+ * @public
+ */
+ export const rootHttpRouter = createServiceRef<
+ import('./RootHttpRouterService').RootHttpRouterService
+ >({ id: 'core.rootHttpRouter', scope: 'root' });
+
/**
* The service reference for the root scoped {@link RootLifecycleService}.
*
diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts
index dedfd6223e..99b3cbd06d 100644
--- a/packages/backend-plugin-api/src/services/definitions/index.ts
+++ b/packages/backend-plugin-api/src/services/definitions/index.ts
@@ -15,7 +15,12 @@
*/
export { coreServices } from './coreServices';
-export type { CacheService } from './CacheService';
+export type {
+ CacheService,
+ CacheClient,
+ CacheClientOptions,
+ CacheClientSetOptions,
+} from './CacheService';
export type { ConfigService } from './ConfigService';
export type { DatabaseService } from './DatabaseService';
export type { DiscoveryService } from './DiscoveryService';
@@ -27,6 +32,7 @@ export type {
export type { LoggerService, LogMeta } from './LoggerService';
export type { PermissionsService } from './PermissionsService';
export type { PluginMetadataService } from './PluginMetadataService';
+export type { RootHttpRouterService } from './RootHttpRouterService';
export type { RootLifecycleService } from './RootLifecycleService';
export type { RootLoggerService } from './RootLoggerService';
export type { SchedulerService } from './SchedulerService';
diff --git a/packages/backend-plugin-api/src/services/index.ts b/packages/backend-plugin-api/src/services/index.ts
index 96bd3d320a..dd24127b88 100644
--- a/packages/backend-plugin-api/src/services/index.ts
+++ b/packages/backend-plugin-api/src/services/index.ts
@@ -15,5 +15,4 @@
*/
export * from './definitions';
-export * from './helpers';
export * from './system';
diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json
index 337c8e1adf..b1b4ee2d0c 100644
--- a/packages/backend-test-utils/package.json
+++ b/packages/backend-test-utils/package.json
@@ -39,7 +39,7 @@
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/cli": "workspace:^",
"@backstage/config": "workspace:^",
- "better-sqlite3": "^7.5.0",
+ "better-sqlite3": "^8.0.0",
"knex": "^2.0.0",
"msw": "^0.49.0",
"mysql2": "^2.2.5",
diff --git a/packages/backend/package.json b/packages/backend/package.json
index b38fafa8f2..085eec665b 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -32,6 +32,7 @@
"@backstage/catalog-model": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/integration": "workspace:^",
+ "@backstage/plugin-adr-backend": "workspace:^",
"@backstage/plugin-app-backend": "workspace:^",
"@backstage/plugin-auth-backend": "workspace:^",
"@backstage/plugin-auth-node": "workspace:^",
@@ -69,7 +70,7 @@
"@gitbeaker/node": "^35.1.0",
"@octokit/rest": "^19.0.3",
"azure-devops-node-api": "^11.0.1",
- "better-sqlite3": "^7.5.0",
+ "better-sqlite3": "^8.0.0",
"dockerode": "^3.3.1",
"example-app": "link:../app",
"express": "^4.17.1",
diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts
index 371ce40358..a721c443d6 100644
--- a/packages/backend/src/index.ts
+++ b/packages/backend/src/index.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Backstage Authors
+ * Copyright 2022 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.
@@ -61,6 +61,7 @@ import badges from './plugins/badges';
import jenkins from './plugins/jenkins';
import permission from './plugins/permission';
import playlist from './plugins/playlist';
+import adr from './plugins/adr';
import { PluginEnvironment } from './types';
import { ServerPermissionClient } from '@backstage/plugin-permission-node';
import { DefaultIdentityClient } from '@backstage/plugin-auth-node';
@@ -139,6 +140,7 @@ async function main() {
const appEnv = useHotMemoize(module, () => createEnv('app'));
const badgesEnv = useHotMemoize(module, () => createEnv('badges'));
const jenkinsEnv = useHotMemoize(module, () => createEnv('jenkins'));
+ const adrEnv = useHotMemoize(module, () => createEnv('adr'));
const techInsightsEnv = useHotMemoize(module, () =>
createEnv('tech-insights'),
);
@@ -175,6 +177,7 @@ async function main() {
apiRouter.use('/permission', await permission(permissionEnv));
apiRouter.use('/playlist', await playlist(playlistEnv));
apiRouter.use('/explore', await explore(exploreEnv));
+ apiRouter.use('/adr', await adr(adrEnv));
apiRouter.use(notFoundHandler());
const service = createServiceBuilder(module)
diff --git a/packages/backend/src/plugins/adr.ts b/packages/backend/src/plugins/adr.ts
new file mode 100644
index 0000000000..6fa0d72969
--- /dev/null
+++ b/packages/backend/src/plugins/adr.ts
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2022 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 { createRouter } from '@backstage/plugin-adr-backend';
+import { Router } from 'express';
+import { PluginEnvironment } from '../types';
+
+export default async function createPlugin(
+ env: PluginEnvironment,
+): Promise {
+ return await createRouter({
+ reader: env.reader,
+ cacheClient: env.cache.getClient(),
+ logger: env.logger,
+ });
+}
diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts
index 8587a5a2e1..2e9d2a0679 100644
--- a/packages/catalog-client/src/CatalogClient.test.ts
+++ b/packages/catalog-client/src/CatalogClient.test.ts
@@ -232,9 +232,9 @@ describe('CatalogClient', () => {
};
server.use(
rest.post(`${mockBaseUrl}/entities/by-refs`, async (req, res, ctx) => {
- expect(req.url.searchParams.get('fields')).toBe('a,b');
await expect(req.json()).resolves.toEqual({
entityRefs: ['k:n/a', 'k:n/b'],
+ fields: ['a', 'b'],
});
return res(ctx.json({ items: [entity, null] }));
}),
diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts
index 81f7343555..af4262b842 100644
--- a/packages/catalog-client/src/CatalogClient.ts
+++ b/packages/catalog-client/src/CatalogClient.ts
@@ -197,14 +197,13 @@ export class CatalogClient implements CatalogApi {
request: GetEntitiesByRefsRequest,
options?: CatalogRequestOptions,
): Promise {
- const params: string[] = [];
+ const body: any = { entityRefs: request.entityRefs };
if (request.fields?.length) {
- params.push(`fields=${request.fields.map(encodeURIComponent).join(',')}`);
+ body.fields = request.fields;
}
const baseUrl = await this.discoveryApi.getBaseUrl('catalog');
- const query = params.length ? `?${params.join('&')}` : '';
- const url = `${baseUrl}/entities/by-refs${query}`;
+ const url = `${baseUrl}/entities/by-refs`;
const response = await this.fetchApi.fetch(url, {
headers: {
@@ -212,7 +211,7 @@ export class CatalogClient implements CatalogApi {
...(options?.token && { Authorization: `Bearer ${options?.token}` }),
},
method: 'POST',
- body: JSON.stringify({ entityRefs: request.entityRefs }),
+ body: JSON.stringify(body),
});
if (!response.ok) {
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 76d9717759..119f08d338 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -156,8 +156,7 @@
"mock-fs": "^5.1.0",
"msw": "^0.49.0",
"nodemon": "^2.0.2",
- "ts-node": "^10.0.0",
- "type-fest": "^2.0.0"
+ "ts-node": "^10.0.0"
},
"peerDependencies": {
"@microsoft/api-extractor": "^7.21.2"
diff --git a/packages/cli/src/commands/start/startFrontend.ts b/packages/cli/src/commands/start/startFrontend.ts
index b7b81e6bff..991439c010 100644
--- a/packages/cli/src/commands/start/startFrontend.ts
+++ b/packages/cli/src/commands/start/startFrontend.ts
@@ -80,7 +80,7 @@ export async function startFrontend(options: StartAppOptions) {
`⚠️ Conflict between app baseUrl and backend baseUrl:
app.baseUrl: ${appBaseUrl}
- backend.baseUrl: ${appBaseUrl}
+ backend.baseUrl: ${backendBaseUrl}
Must have unique hostname and/or ports.
diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md
index c46b3637cb..4cdc42ee79 100644
--- a/packages/core-components/api-report.md
+++ b/packages/core-components/api-report.md
@@ -113,7 +113,7 @@ export type BottomLinkProps = {
onClick?: (event: React_2.MouseEvent) => void;
};
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Props_19" needs to be exported by the entry point index.d.ts
//
// @public
export function Breadcrumbs(props: Props_19): JSX.Element;
@@ -168,7 +168,7 @@ export interface CodeSnippetProps {
text: string;
}
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Props_13" needs to be exported by the entry point index.d.ts
//
// @public
export function Content(props: PropsWithChildren): JSX.Element;
@@ -320,7 +320,7 @@ export function DocsIcon(props: IconComponentProps): JSX.Element;
// @public (undocumented)
export function EmailIcon(props: IconComponentProps): JSX.Element;
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Props_2" needs to be exported by the entry point index.d.ts
//
// @public
export function EmptyState(props: Props_2): JSX.Element;
@@ -375,7 +375,7 @@ export type FeatureCalloutCircleClassKey =
| 'pulseCircle'
| 'text';
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Props_4" needs to be exported by the entry point index.d.ts
//
// @public
export function FeatureCalloutCircular(
@@ -388,7 +388,7 @@ export type FiltersContainerClassKey = 'root' | 'title';
// @public
export function Gauge(props: GaugeProps): JSX.Element;
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Props_10" needs to be exported by the entry point index.d.ts
//
// @public
export function GaugeCard(props: Props_10): JSX.Element;
@@ -432,7 +432,7 @@ export function GitHubIcon(props: IconComponentProps): JSX.Element;
// @public (undocumented)
export function GroupIcon(props: IconComponentProps): JSX.Element;
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Props_14" needs to be exported by the entry point index.d.ts
//
// @public
export function Header(props: PropsWithChildren): JSX.Element;
@@ -466,7 +466,7 @@ export type HeaderClassKey =
| 'breadcrumbType'
| 'breadcrumbTitle';
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Props_5" needs to be exported by the entry point index.d.ts
//
// @public
export function HeaderIconLinkRow(props: Props_5): JSX.Element;
@@ -497,7 +497,7 @@ export type HeaderTabsClassKey =
// @public (undocumented)
export function HelpIcon(props: IconComponentProps): JSX.Element;
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Props_6" needs to be exported by the entry point index.d.ts
//
// @public
export function HorizontalScrollGrid(
@@ -524,7 +524,7 @@ export type IconLinkVerticalClassKey =
| 'secondary'
| 'label';
-// Warning: (ae-missing-release-tag) "IconLinkVerticalProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "IconLinkVerticalProps" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type IconLinkVerticalProps = {
@@ -540,7 +540,7 @@ export type IconLinkVerticalProps = {
// @public (undocumented)
export type IdentityProviders = ('guest' | 'custom' | SignInProviderConfig)[];
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Props_15" needs to be exported by the entry point index.d.ts
//
// @public
export function InfoCard(props: Props_15): JSX.Element;
@@ -564,7 +564,7 @@ export type InfoCardVariants = 'flex' | 'fullHeight' | 'gridItem';
export function IntroCard(props: IntroCardProps): JSX.Element;
// Warning: (ae-forgotten-export) The symbol "ItemCardProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "ItemCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "ItemCard" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public @deprecated
export function ItemCard(props: ItemCardProps): JSX.Element;
@@ -588,7 +588,7 @@ export function ItemCardHeader(props: ItemCardHeaderProps): JSX.Element;
// @public (undocumented)
export type ItemCardHeaderClassKey = 'root';
-// Warning: (ae-forgotten-export) The symbol "styles" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "styles_2" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
export type ItemCardHeaderProps = Partial> & {
@@ -607,29 +607,29 @@ enum LabelPosition {
RIGHT = 'r',
}
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "Lifecycle" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-forgotten-export) The symbol "Props_7" needs to be exported by the entry point index.d.ts
+// Warning: (ae-missing-release-tag) "Lifecycle" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function Lifecycle(props: Props_7): JSX.Element;
-// Warning: (ae-missing-release-tag) "LifecycleClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "LifecycleClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type LifecycleClassKey = 'alpha' | 'beta';
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "LinearGauge" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-forgotten-export) The symbol "Props_11" needs to be exported by the entry point index.d.ts
+// Warning: (ae-missing-release-tag) "LinearGauge" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function LinearGauge(props: Props_11): JSX.Element | null;
-// Warning: (ae-missing-release-tag) "Link" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "Link" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export const Link: (props: LinkProps) => JSX.Element;
-// Warning: (ae-missing-release-tag) "LinkProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "LinkProps" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type LinkProps = Omit &
@@ -639,7 +639,7 @@ export type LinkProps = Omit &
noTrack?: boolean;
};
-// Warning: (ae-missing-release-tag) "LoginRequestListItemClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "LoginRequestListItemClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type LoginRequestListItemClassKey = 'root';
@@ -688,49 +688,49 @@ export interface LogViewerProps {
text: string;
}
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "MarkdownContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-forgotten-export) The symbol "Props_8" needs to be exported by the entry point index.d.ts
+// Warning: (ae-missing-release-tag) "MarkdownContent" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export function MarkdownContent(props: Props_8): JSX.Element;
-// Warning: (ae-missing-release-tag) "MarkdownContentClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MarkdownContentClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type MarkdownContentClassKey = 'markdown';
-// Warning: (ae-missing-release-tag) "MetadataTableCellClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MetadataTableCellClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type MetadataTableCellClassKey = 'root';
-// Warning: (ae-missing-release-tag) "MetadataTableListClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MetadataTableListClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type MetadataTableListClassKey = 'root';
-// Warning: (ae-missing-release-tag) "MetadataTableListItemClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MetadataTableListItemClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type MetadataTableListItemClassKey = 'root' | 'random';
-// Warning: (ae-missing-release-tag) "MetadataTableTitleCellClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MetadataTableTitleCellClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type MetadataTableTitleCellClassKey = 'root';
-// Warning: (ae-missing-release-tag) "MicDropClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MicDropClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type MicDropClassKey = 'micDrop';
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "MissingAnnotationEmptyState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-forgotten-export) The symbol "Props_3" needs to be exported by the entry point index.d.ts
+// Warning: (ae-missing-release-tag) "MissingAnnotationEmptyState" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function MissingAnnotationEmptyState(props: Props_3): JSX.Element;
-// Warning: (ae-missing-release-tag) "MissingAnnotationEmptyStateClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MissingAnnotationEmptyStateClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type MissingAnnotationEmptyStateClassKey = 'code';
@@ -743,12 +743,12 @@ export type MobileSidebarProps = {
children?: React_2.ReactNode;
};
-// Warning: (ae-missing-release-tag) "OAuthRequestDialog" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "OAuthRequestDialog" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function OAuthRequestDialog(_props: {}): JSX.Element;
-// Warning: (ae-missing-release-tag) "OAuthRequestDialogClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "OAuthRequestDialogClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type OAuthRequestDialogClassKey =
@@ -757,42 +757,42 @@ export type OAuthRequestDialogClassKey =
| 'contentList'
| 'actionButtons';
-// Warning: (ae-missing-release-tag) "OpenedDropdownClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "OpenedDropdownClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type OpenedDropdownClassKey = 'icon';
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "OverflowTooltip" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-forgotten-export) The symbol "Props_9" needs to be exported by the entry point index.d.ts
+// Warning: (ae-missing-release-tag) "OverflowTooltip" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function OverflowTooltip(props: Props_9): JSX.Element;
-// Warning: (ae-missing-release-tag) "OverflowTooltipClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "OverflowTooltipClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type OverflowTooltipClassKey = 'container';
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "Page" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-forgotten-export) The symbol "Props_16" needs to be exported by the entry point index.d.ts
+// Warning: (ae-missing-release-tag) "Page" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function Page(props: Props_16): JSX.Element;
-// Warning: (ae-missing-release-tag) "PageClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "PageClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type PageClassKey = 'root';
// Warning: (ae-forgotten-export) The symbol "PageWithHeaderProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "PageWithHeader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "PageWithHeader" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function PageWithHeader(
props: PropsWithChildren,
): JSX.Element;
-// Warning: (ae-missing-release-tag) "Progress" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "Progress" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function Progress(
@@ -810,7 +810,7 @@ export type ProxiedSignInPageProps = SignInPageProps & {
headers?: HeadersInit | (() => HeadersInit) | (() => Promise);
};
-// Warning: (ae-missing-release-tag) "Ranker" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "Ranker" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
enum Ranker {
@@ -819,14 +819,14 @@ enum Ranker {
TIGHT_TREE = 'tight-tree',
}
-// Warning: (ae-missing-release-tag) "RenderLabelFunction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "RenderLabelFunction" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
type RenderLabelFunction = (
props: RenderLabelProps,
) => React_2.ReactNode;
-// Warning: (ae-missing-release-tag) "RenderLabelProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "RenderLabelProps" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver
// Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver
//
@@ -835,7 +835,7 @@ type RenderLabelProps = {
edge: DependencyEdge;
};
-// Warning: (ae-missing-release-tag) "RenderNodeFunction" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "RenderNodeFunction" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver
//
// @public
@@ -843,7 +843,7 @@ type RenderNodeFunction = (
props: RenderNodeProps,
) => React_2.ReactNode;
-// Warning: (ae-missing-release-tag) "RenderNodeProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "RenderNodeProps" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
// Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver
// Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver
//
@@ -852,17 +852,17 @@ type RenderNodeProps = {
node: DependencyNode;
};
-// Warning: (ae-missing-release-tag) "ResponseErrorPanel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "ResponseErrorPanel" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export function ResponseErrorPanel(props: ErrorPanelProps): JSX.Element;
-// Warning: (ae-missing-release-tag) "ResponseErrorPanelClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "ResponseErrorPanelClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type ResponseErrorPanelClassKey = 'text' | 'divider';
-// Warning: (ae-missing-release-tag) "RoutedTabs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "RoutedTabs" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function RoutedTabs(props: { routes: SubRoute_2[] }): JSX.Element;
@@ -896,7 +896,7 @@ export type SelectItem = {
// @public
export const Sidebar: (props: SidebarProps) => JSX.Element;
-// Warning: (ae-missing-release-tag) "SIDEBAR_INTRO_LOCAL_STORAGE" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SIDEBAR_INTRO_LOCAL_STORAGE" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const SIDEBAR_INTRO_LOCAL_STORAGE =
@@ -905,7 +905,7 @@ export const SIDEBAR_INTRO_LOCAL_STORAGE =
// @public (undocumented)
export type SidebarClassKey = 'drawer' | 'drawerOpen';
-// Warning: (ae-missing-release-tag) "sidebarConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "sidebarConfig" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const sidebarConfig: {
@@ -933,7 +933,7 @@ export type SidebarContextType = {
setOpen: (open: boolean) => void;
};
-// Warning: (ae-missing-release-tag) "SidebarDivider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SidebarDivider" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const SidebarDivider: React_2.ComponentType<
@@ -942,7 +942,7 @@ export const SidebarDivider: React_2.ComponentType<
StyledComponentProps<'root'>
>;
-// Warning: (ae-missing-release-tag) "SidebarDividerClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SidebarDividerClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SidebarDividerClassKey = 'root';
@@ -960,7 +960,7 @@ export interface SidebarGroupProps extends BottomNavigationActionProps {
to?: string;
}
-// Warning: (ae-missing-release-tag) "SidebarIntro" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SidebarIntro" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SidebarIntro(_props: {}): JSX.Element | null;
@@ -974,7 +974,7 @@ export type SidebarIntroClassKey =
| 'introDismissIcon';
// Warning: (ae-forgotten-export) The symbol "SidebarItemProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "SidebarItem" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SidebarItem" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export const SidebarItem: (props: SidebarItemProps) => JSX.Element;
@@ -1018,12 +1018,12 @@ export type SidebarOptions = {
drawerWidthOpen?: number;
};
-// Warning: (ae-missing-release-tag) "SidebarPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SidebarPage" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SidebarPage(props: SidebarPageProps): JSX.Element;
-// Warning: (ae-missing-release-tag) "SidebarPageClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SidebarPageClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SidebarPageClassKey = 'root';
@@ -1066,7 +1066,7 @@ export type SidebarProps = {
children?: React_2.ReactNode;
};
-// Warning: (ae-missing-release-tag) "SidebarScrollWrapper" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SidebarScrollWrapper" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const SidebarScrollWrapper: React_2.ComponentType<
@@ -1076,12 +1076,12 @@ export const SidebarScrollWrapper: React_2.ComponentType<
>;
// Warning: (ae-forgotten-export) The symbol "SidebarSearchFieldProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "SidebarSearchField" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SidebarSearchField" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SidebarSearchField(props: SidebarSearchFieldProps): JSX.Element;
-// Warning: (ae-missing-release-tag) "SidebarSpace" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SidebarSpace" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const SidebarSpace: React_2.ComponentType<
@@ -1090,12 +1090,12 @@ export const SidebarSpace: React_2.ComponentType<
StyledComponentProps<'root'>
>;
-// Warning: (ae-missing-release-tag) "SidebarSpaceClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SidebarSpaceClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SidebarSpaceClassKey = 'root';
-// Warning: (ae-missing-release-tag) "SidebarSpacer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SidebarSpacer" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const SidebarSpacer: React_2.ComponentType<
@@ -1104,7 +1104,7 @@ export const SidebarSpacer: React_2.ComponentType<
StyledComponentProps<'root'>
>;
-// Warning: (ae-missing-release-tag) "SidebarSpacerClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SidebarSpacerClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SidebarSpacerClassKey = 'root';
@@ -1138,18 +1138,18 @@ export type SidebarSubmenuProps = {
children: ReactNode;
};
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "SignInPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-forgotten-export) The symbol "Props_17" needs to be exported by the entry point index.d.ts
+// Warning: (ae-missing-release-tag) "SignInPage" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SignInPage(props: Props_17): JSX.Element;
-// Warning: (ae-missing-release-tag) "SignInPageClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SignInPageClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SignInPageClassKey = 'container' | 'item';
-// Warning: (ae-missing-release-tag) "SignInProviderConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SignInProviderConfig" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SignInProviderConfig = {
@@ -1160,37 +1160,37 @@ export type SignInProviderConfig = {
};
// Warning: (ae-forgotten-export) The symbol "StepperProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "SimpleStepper" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SimpleStepper" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SimpleStepper(
props: PropsWithChildren,
): JSX.Element;
-// Warning: (ae-missing-release-tag) "SimpleStepperFooterClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SimpleStepperFooterClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SimpleStepperFooterClassKey = 'root';
// Warning: (ae-forgotten-export) The symbol "StepProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "SimpleStepperStep" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SimpleStepperStep" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SimpleStepperStep(
props: PropsWithChildren,
): JSX.Element;
-// Warning: (ae-missing-release-tag) "SimpleStepperStepClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SimpleStepperStepClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SimpleStepperStepClassKey = 'end';
-// Warning: (ae-missing-release-tag) "StatusAborted" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "StatusAborted" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function StatusAborted(props: PropsWithChildren<{}>): JSX.Element;
-// Warning: (ae-missing-release-tag) "StatusClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "StatusClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type StatusClassKey =
@@ -1202,43 +1202,43 @@ export type StatusClassKey =
| 'running'
| 'aborted';
-// Warning: (ae-missing-release-tag) "StatusError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "StatusError" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function StatusError(props: PropsWithChildren<{}>): JSX.Element;
-// Warning: (ae-missing-release-tag) "StatusOK" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "StatusOK" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function StatusOK(props: PropsWithChildren<{}>): JSX.Element;
-// Warning: (ae-missing-release-tag) "StatusPending" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "StatusPending" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function StatusPending(props: PropsWithChildren<{}>): JSX.Element;
-// Warning: (ae-missing-release-tag) "StatusRunning" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "StatusRunning" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function StatusRunning(props: PropsWithChildren<{}>): JSX.Element;
-// Warning: (ae-missing-release-tag) "StatusWarning" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "StatusWarning" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function StatusWarning(props: PropsWithChildren<{}>): JSX.Element;
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "StructuredMetadataTable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-forgotten-export) The symbol "Props_12" needs to be exported by the entry point index.d.ts
+// Warning: (ae-missing-release-tag) "StructuredMetadataTable" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function StructuredMetadataTable(props: Props_12): JSX.Element;
-// Warning: (ae-missing-release-tag) "StructuredMetadataTableListClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "StructuredMetadataTableListClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type StructuredMetadataTableListClassKey = 'root';
-// Warning: (ae-missing-release-tag) "StructuredMetadataTableNestedListClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "StructuredMetadataTableNestedListClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type StructuredMetadataTableNestedListClassKey = 'root';
@@ -1250,28 +1250,28 @@ export type SubmenuOptions = {
};
// Warning: (ae-forgotten-export) The symbol "SubvalueCellProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "SubvalueCell" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SubvalueCell" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SubvalueCell(props: SubvalueCellProps): JSX.Element;
-// Warning: (ae-missing-release-tag) "SubvalueCellClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SubvalueCellClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SubvalueCellClassKey = 'value' | 'subvalue';
// Warning: (ae-forgotten-export) The symbol "SupportButtonProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "SupportButton" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SupportButton" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function SupportButton(props: SupportButtonProps): JSX.Element;
-// Warning: (ae-missing-release-tag) "SupportButtonClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SupportButtonClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SupportButtonClassKey = 'popoverList';
-// Warning: (ae-missing-release-tag) "SupportConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SupportConfig" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SupportConfig = {
@@ -1279,7 +1279,7 @@ export type SupportConfig = {
items: SupportItem[];
};
-// Warning: (ae-missing-release-tag) "SupportItem" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SupportItem" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SupportItem = {
@@ -1288,7 +1288,7 @@ export type SupportItem = {
links: SupportItemLink[];
};
-// Warning: (ae-missing-release-tag) "SupportItemLink" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SupportItemLink" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type SupportItemLink = {
@@ -1296,7 +1296,7 @@ export type SupportItemLink = {
title: string;
};
-// Warning: (ae-missing-release-tag) "Tab" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "Tab" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type Tab = {
@@ -1310,24 +1310,24 @@ export type Tab = {
>;
};
-// Warning: (ae-missing-release-tag) "TabBarClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TabBarClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TabBarClassKey = 'indicator' | 'flexContainer' | 'root';
-// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "TabbedCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-forgotten-export) The symbol "Props_18" needs to be exported by the entry point index.d.ts
+// Warning: (ae-missing-release-tag) "TabbedCard" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function TabbedCard(props: PropsWithChildren): JSX.Element;
-// Warning: (ae-missing-release-tag) "TabbedCardClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TabbedCardClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TabbedCardClassKey = 'root' | 'indicator';
-// Warning: (ae-missing-release-tag) "TabbedLayout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-// Warning: (ae-missing-release-tag) "TabbedLayout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TabbedLayout" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TabbedLayout" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export function TabbedLayout(props: PropsWithChildren<{}>): JSX.Element;
@@ -1343,12 +1343,12 @@ export namespace TabbedLayout {
// @public (undocumented)
export type TabClassKey = 'root' | 'selected';
-// Warning: (ae-missing-release-tag) "TabIconClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TabIconClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TabIconClassKey = 'root';
-// Warning: (ae-missing-release-tag) "Table" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "Table" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function Table(props: TableProps): JSX.Element;
@@ -1359,12 +1359,12 @@ export namespace Table {
icons: Readonly;
}
-// Warning: (ae-missing-release-tag) "TableClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TableClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TableClassKey = 'root';
-// Warning: (ae-missing-release-tag) "TableColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TableColumn" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface TableColumn extends Column {
@@ -1374,7 +1374,7 @@ export interface TableColumn extends Column {
width?: string;
}
-// Warning: (ae-missing-release-tag) "TableFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TableFilter" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TableFilter = {
@@ -1382,17 +1382,17 @@ export type TableFilter = {
type: 'select' | 'multiple-select';
};
-// Warning: (ae-missing-release-tag) "TableFiltersClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TableFiltersClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TableFiltersClassKey = 'root' | 'value' | 'heder' | 'filters';
-// Warning: (ae-missing-release-tag) "TableHeaderClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TableHeaderClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TableHeaderClassKey = 'header';
-// Warning: (ae-missing-release-tag) "TableProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TableProps" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface TableProps
@@ -1411,7 +1411,7 @@ export interface TableProps
subtitle?: string;
}
-// Warning: (ae-missing-release-tag) "TableState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TableState" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TableState = {
@@ -1420,23 +1420,23 @@ export type TableState = {
filters?: SelectedFilters;
};
-// Warning: (ae-missing-release-tag) "TableToolbarClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TableToolbarClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TableToolbarClassKey = 'root' | 'title' | 'searchField';
// Warning: (ae-forgotten-export) The symbol "TabsProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "Tabs" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "Tabs" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function Tabs(props: TabsProps): JSX.Element;
-// Warning: (ae-missing-release-tag) "TabsClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TabsClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type TabsClassKey = 'root' | 'styledTabs' | 'appbar';
-// Warning: (ae-missing-release-tag) "TrendLine" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TrendLine" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function TrendLine(
@@ -1453,7 +1453,7 @@ export function useContent(): {
};
// Warning: (ae-forgotten-export) The symbol "SetQueryParams" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "useQueryParamState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "useQueryParamState" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function useQueryParamState(
@@ -1502,7 +1502,7 @@ export const useSidebarOpenState: () => SidebarOpenState;
// @public
export const useSidebarPinState: () => SidebarPinState;
-// Warning: (ae-missing-release-tag) "useSupportConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "useSupportConfig" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function useSupportConfig(): SupportConfig;
@@ -1511,12 +1511,12 @@ export function useSupportConfig(): SupportConfig;
export function WarningIcon(props: IconComponentProps): JSX.Element;
// Warning: (ae-forgotten-export) The symbol "WarningProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "WarningPanel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "WarningPanel" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
export function WarningPanel(props: WarningProps): JSX.Element;
-// Warning: (ae-missing-release-tag) "WarningPanelClassKey" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "WarningPanelClassKey" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type WarningPanelClassKey =
@@ -1530,7 +1530,7 @@ export type WarningPanelClassKey =
//
// src/components/DependencyGraph/types.d.ts:16:5 - (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/core-components" does not have an export "DependencyNode"
// src/components/DependencyGraph/types.d.ts:20:5 - (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/core-components" does not have an export "DependencyNode"
-// src/components/TabbedLayout/RoutedTabs.d.ts:9:5 - (ae-forgotten-export) The symbol "SubRoute" needs to be exported by the entry point index.d.ts
+// src/components/TabbedLayout/RoutedTabs.d.ts:9:5 - (ae-forgotten-export) The symbol "SubRoute_2" needs to be exported by the entry point index.d.ts
// src/components/Table/Table.d.ts:20:5 - (ae-forgotten-export) The symbol "SelectedFilters" needs to be exported by the entry point index.d.ts
// src/layout/ErrorBoundary/ErrorBoundary.d.ts:8:5 - (ae-forgotten-export) The symbol "SlackChannel" needs to be exported by the entry point index.d.ts
```
diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json
index 374eaa6d18..6bef34d633 100644
--- a/packages/e2e-test/package.json
+++ b/packages/e2e-test/package.json
@@ -40,7 +40,7 @@
"handlebars": "^4.7.3",
"nodemon": "^2.0.2",
"pgtools": "^0.3.0",
- "puppeteer": "^17.0.0",
+ "puppeteer": "^19.0.0",
"tree-kill": "^1.2.2",
"ts-node": "^10.0.0"
},
diff --git a/packages/e2e-test/src/lib/helpers.ts b/packages/e2e-test/src/lib/helpers.ts
index b3fd665fd2..2e9b355f4c 100644
--- a/packages/e2e-test/src/lib/helpers.ts
+++ b/packages/e2e-test/src/lib/helpers.ts
@@ -22,7 +22,7 @@ import {
ChildProcess,
} from 'child_process';
import { promisify } from 'util';
-import puppeteer from 'puppeteer';
+import * as puppeteer from 'puppeteer';
const execFile = promisify(execFileCb);
diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json
index cb0378363a..6d401366c4 100644
--- a/packages/repo-tools/package.json
+++ b/packages/repo-tools/package.json
@@ -33,8 +33,8 @@
"@backstage/cli-common": "workspace:^",
"@backstage/errors": "workspace:^",
"@manypkg/get-packages": "^1.1.3",
- "@microsoft/api-documenter": "^7.17.11",
- "@microsoft/api-extractor": "^7.23.0",
+ "@microsoft/api-documenter": "^7.19.27",
+ "@microsoft/api-extractor": "^7.33.7",
"chalk": "^4.0.0",
"commander": "^9.1.0",
"fs-extra": "10.1.0",
@@ -53,7 +53,6 @@
"@microsoft/api-extractor-model": "*",
"@microsoft/tsdoc": "*",
"@microsoft/tsdoc-config": "*",
- "@rushstack/node-core-library": "*",
"prettier": "^2.8.1",
"typescript": "> 3.0.0"
},
diff --git a/packages/repo-tools/src/commands/api-reports/api-extractor.ts b/packages/repo-tools/src/commands/api-reports/api-extractor.ts
index 9e844d97c8..b037f40be6 100644
--- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts
+++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts
@@ -18,11 +18,9 @@ import {
resolve as resolvePath,
relative as relativePath,
basename,
- dirname,
join,
} from 'path';
import { execFile } from 'child_process';
-import type prettierType from 'prettier';
import fs from 'fs-extra';
import {
Extractor,
@@ -70,32 +68,7 @@ const tmpDir = cliPaths.resolveTargetRoot(
);
/**
- * All of this monkey patching below is because MUI has these bare package.json file as a method
- * for making TypeScript accept imports like `@material-ui/core/Button`, and improve tree-shaking
- * by declaring them side effect free.
- *
- * The package.json lookup logic in api-extractor really doesn't like that though, as it enforces
- * that the 'name' field exists in all package.json files that it discovers. This below is just
- * making sure that we ignore those file package.json files instead of crashing.
- */
-const {
- PackageJsonLookup,
-} = require('@rushstack/node-core-library/lib/PackageJsonLookup');
-
-const old = PackageJsonLookup.prototype.tryGetPackageJsonFilePathFor;
-PackageJsonLookup.prototype.tryGetPackageJsonFilePathFor =
- function tryGetPackageJsonFilePathForPatch(path: string) {
- if (
- path.includes('@material-ui') &&
- !dirname(path).endsWith('@material-ui')
- ) {
- return undefined;
- }
- return old.call(this, path);
- };
-
-/**
- * Another monkey patch where we apply prettier to the API reports. This has to be patched into
+ * All of this monkey patching below is for apply prettier to the API reports. This has to be patched into
* the middle of the process as API Extractor does a comparison of the contents of the old
* and new files during generation. This inserts the formatting just before that comparison.
*/
@@ -134,7 +107,6 @@ ApiReportGenerator.generateReviewFileContent =
...moreArgs: any[]
) {
const program = collector.program as Program;
-
// The purpose of this override is to allow the @ignore tag to be used to ignore warnings
// of the form "Warning: (ae-forgotten-export) The symbol "FooBar" needs to be exported by the entry point index.d.ts"
patchFileMessageFetcher(
@@ -166,7 +138,16 @@ ApiReportGenerator.generateReviewFileContent =
}
// The local name of the symbol within the file, rather than the exported name
- const localName = (sourceFile as any).identifiers?.get(symbolName);
+ let localName = (sourceFile as any).identifiers?.get(symbolName);
+
+ if (!localName) {
+ // Sometimes the symbol name is suffixed with a number to disambiguate,
+ // e.g. "Props_14" instead of "Props" if there are multiple Props interfaces
+ // so we tyry to strip that suffix and look up the symbol again.
+ const [, trimmedSymbolName] = symbolName.match(/(.*)_\d+/) || [];
+ localName = (sourceFile as any).identifiers?.get(trimmedSymbolName);
+ }
+
if (!localName) {
throw new Error(
`Unable to find local name of "${symbolName}" in ${sourceFile.fileName}`,
@@ -213,7 +194,7 @@ ApiReportGenerator.generateReviewFileContent =
);
try {
- const prettier = require('prettier') as typeof prettierType;
+ const prettier = require('prettier') as typeof import('prettier');
const config = prettier.resolveConfig.sync(cliPaths.targetRoot) ?? {};
return prettier.format(content, {
@@ -221,7 +202,6 @@ ApiReportGenerator.generateReviewFileContent =
parser: 'markdown',
});
} catch (e) {
- // console.warn('Failed to format API report with prettier', e);
return content;
}
};
@@ -434,6 +414,7 @@ export async function runApiExtraction({
configObjectFullPath: projectFolder,
packageJsonFullPath: resolvePath(projectFolder, 'package.json'),
tsdocConfigFile: await getTsDocConfig(),
+ ignoreMissingEntryPoint: true,
});
// The `packageFolder` needs to point to the location within `dist-types` in order for relative
diff --git a/plugins/adr-backend/README.md b/plugins/adr-backend/README.md
index 79b5fe13ed..225f07fdf7 100644
--- a/plugins/adr-backend/README.md
+++ b/plugins/adr-backend/README.md
@@ -4,6 +4,8 @@ This ADR backend plugin is primarily responsible for the following:
- Provides a `DefaultAdrCollatorFactory`, which can be used in the search backend to index ADR documents associated with entities to your Backstage Search.
+- Provides endpoints that use UrlReaders for getting ADR documents (used in the [ADR frontend plugin](../adr/README.md)).
+
## Indexing ADR documents for search
Before you are able to start indexing ADR documents to search, you need to go through the [search getting started guide](https://backstage.io/docs/features/search/getting-started).
@@ -35,7 +37,7 @@ indexBuilder.addCollator({
### Parsing custom ADR document formats
-By default, the `DefaultAdrCollatorFactory` will parse and index documents that follow the [MADR](https://adr.github.io/madr/) standard file name and template format. If you use a different ADR format and file name convention, you can configure `DefaultAdrCollatorFactory` with custom `adrFilePathFilterFn` and `parser` options (see type definitions for details):
+By default, the `DefaultAdrCollatorFactory` will parse and index documents that follow the [MADR v2.x standard file name and template format](https://github.com/adr/madr/tree/2.1.2). If you use a different ADR format and file name convention, you can configure `DefaultAdrCollatorFactory` with custom `adrFilePathFilterFn` and `parser` options (see type definitions for details):
```ts
DefaultAdrCollatorFactory.fromConfig({
diff --git a/plugins/adr-backend/api-report.md b/plugins/adr-backend/api-report.md
index 5a671e9c8f..d5645ad3a7 100644
--- a/plugins/adr-backend/api-report.md
+++ b/plugins/adr-backend/api-report.md
@@ -7,10 +7,12 @@
import { AdrDocument } from '@backstage/plugin-adr-common';
import { AdrFilePathFilterFn } from '@backstage/plugin-adr-common';
+import { CacheClient } from '@backstage/backend-common';
import { CatalogApi } from '@backstage/catalog-client';
import { Config } from '@backstage/config';
import { DocumentCollatorFactory } from '@backstage/plugin-search-common';
import { Entity } from '@backstage/catalog-model';
+import express from 'express';
import { Logger } from 'winston';
import { PluginCacheManager } from '@backstage/backend-common';
import { PluginEndpointDiscovery } from '@backstage/backend-common';
@@ -41,9 +43,21 @@ export type AdrParserContext = {
path: string;
};
+// @public (undocumented)
+export type AdrRouterOptions = {
+ reader: UrlReader;
+ cacheClient: CacheClient;
+ logger: Logger;
+};
+
// @public
export const createMadrParser: (options?: MadrParserOptions) => AdrParser;
+// @public (undocumented)
+export function createRouter(
+ options: AdrRouterOptions,
+): Promise;
+
// @public
export class DefaultAdrCollatorFactory implements DocumentCollatorFactory {
// (undocumented)
diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json
index 73f9309972..033441372a 100644
--- a/plugins/adr-backend/package.json
+++ b/plugins/adr-backend/package.json
@@ -36,6 +36,9 @@
"@backstage/integration": "workspace:^",
"@backstage/plugin-adr-common": "workspace:^",
"@backstage/plugin-search-common": "workspace:^",
+ "@types/express": "^4.17.15",
+ "express": "^4.18.2",
+ "express-promise-router": "^4.1.1",
"luxon": "^3.0.0",
"marked": "^4.0.14",
"node-fetch": "^2.6.5",
diff --git a/plugins/adr-backend/src/index.ts b/plugins/adr-backend/src/index.ts
index 86e07943df..5cc8f50b72 100644
--- a/plugins/adr-backend/src/index.ts
+++ b/plugins/adr-backend/src/index.ts
@@ -21,3 +21,4 @@
*/
export * from './search';
+export * from './service';
diff --git a/packages/backend-plugin-api/src/services/helpers/index.ts b/plugins/adr-backend/src/service/index.ts
similarity index 86%
rename from packages/backend-plugin-api/src/services/helpers/index.ts
rename to plugins/adr-backend/src/service/index.ts
index 24336c1af2..3736acb188 100644
--- a/packages/backend-plugin-api/src/services/helpers/index.ts
+++ b/plugins/adr-backend/src/service/index.ts
@@ -14,4 +14,5 @@
* limitations under the License.
*/
-export { loggerToWinstonLogger } from './loggerToWinstonLogger';
+export { createRouter } from './router';
+export type { AdrRouterOptions } from './router';
diff --git a/plugins/adr-backend/src/service/router.test.ts b/plugins/adr-backend/src/service/router.test.ts
new file mode 100644
index 0000000000..fbbd6e8532
--- /dev/null
+++ b/plugins/adr-backend/src/service/router.test.ts
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2022 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 {
+ CacheClient,
+ ReadTreeResponse,
+ ReadTreeResponseFile,
+ ReadUrlResponse,
+ UrlReader,
+} from '@backstage/backend-common';
+import express from 'express';
+import request from 'supertest';
+import { createRouter } from './router';
+import { Logger } from 'winston';
+
+const listEndpointName = '/list';
+const fileEndpointName = '/file';
+
+const makeBufferFromString = (string: string) => async () =>
+ Buffer.from(string);
+
+const testingUrlFakeFileTree: ReadTreeResponseFile[] = [
+ {
+ path: 'folder/testFile001.txt',
+ content: makeBufferFromString('folder/testFile001.txt content'),
+ },
+ {
+ path: 'testFile001.txt',
+ content: makeBufferFromString('testFile002.txt content'),
+ },
+ {
+ path: 'testFile002.txt',
+ content: makeBufferFromString('testFile001.txt content'),
+ },
+];
+
+const makeFileContent = async (fileContent: string) => {
+ const result: ReadUrlResponse = {
+ buffer: makeBufferFromString(fileContent),
+ };
+ return result;
+};
+
+const testFileOneContent = 'testFileOne content';
+const testFileTwoContent = 'testFileTwo content';
+const genericFileContent = 'file content';
+
+const mockUrlReader: UrlReader = {
+ readUrl(url: string) {
+ switch (url) {
+ case 'testFileOne':
+ return makeFileContent(testFileOneContent);
+ case 'testFileTwo':
+ return makeFileContent(testFileTwoContent);
+ default:
+ return makeFileContent(genericFileContent);
+ }
+ },
+ readTree() {
+ const result: ReadTreeResponse = {
+ files: async () => testingUrlFakeFileTree,
+ archive() {
+ throw new Error('Function not implemented.');
+ },
+ dir() {
+ throw new Error('Function not implemented.');
+ },
+ etag: '',
+ };
+
+ const resultPromise = async () => result;
+ return resultPromise();
+ },
+ search() {
+ throw new Error('search not implemented.');
+ },
+};
+
+class MockCacheClient implements CacheClient {
+ private itemRegistry: { [key: string]: any };
+
+ constructor() {
+ this.itemRegistry = {};
+ }
+
+ async get(key: string) {
+ return this.itemRegistry[key];
+ }
+
+ async set(key: string, value: any) {
+ this.itemRegistry[key] = value;
+ }
+
+ async delete(key: string) {
+ delete this.itemRegistry[key];
+ }
+}
+
+describe('createRouter', () => {
+ let app: express.Express;
+
+ beforeEach(async () => {
+ jest.resetAllMocks();
+
+ const router = await createRouter({
+ reader: mockUrlReader,
+ cacheClient: new MockCacheClient(),
+ logger: {
+ error: (message: any) => message,
+ } as Logger,
+ });
+ app = express().use(router);
+ });
+
+ describe(`GET ${listEndpointName}`, () => {
+ it('returns bad request (400) when no url is provided', async () => {
+ const urlNotSpecifiedRequest = await request(app).get(listEndpointName);
+ const urlNotSpecifiedStatus = urlNotSpecifiedRequest.status;
+ const urlNotSpecifiedMessage = urlNotSpecifiedRequest.body.message;
+
+ const urlNotFilledRequest = await request(app).get(
+ `${listEndpointName}?url=`,
+ );
+ const urlNotFilledStatus = urlNotFilledRequest.status;
+ const urlNotFilledMessage = urlNotFilledRequest.body.message;
+
+ const expectedStatusCode = 400;
+ const expectedErrorMessage = 'No URL provided';
+
+ expect(urlNotSpecifiedStatus).toBe(expectedStatusCode);
+ expect(urlNotSpecifiedMessage).toBe(expectedErrorMessage);
+
+ expect(urlNotFilledStatus).toBe(expectedStatusCode);
+ expect(urlNotFilledMessage).toBe(expectedErrorMessage);
+ });
+
+ it('returns the correct listing when reading a url', async () => {
+ const result = await request(app).get(`${listEndpointName}?url=testing`);
+ const { status, body, error } = result;
+
+ const expectedStatusCode = 200;
+ const expectedBody = {
+ data: [
+ {
+ type: 'file',
+ name: 'testFile001.txt',
+ path: 'folder/testFile001.txt',
+ },
+ {
+ type: 'file',
+ name: 'testFile001.txt',
+ path: 'testFile001.txt',
+ },
+ {
+ type: 'file',
+ name: 'testFile002.txt',
+ path: 'testFile002.txt',
+ },
+ ],
+ };
+
+ expect(error).toBeFalsy();
+ expect(status).toBe(expectedStatusCode);
+ expect(body).toEqual(expectedBody);
+ });
+ });
+
+ describe(`GET ${fileEndpointName}`, () => {
+ it('returns bad request (400) when no url is provided', async () => {
+ const urlNotSpecifiedRequest = await request(app).get(fileEndpointName);
+ const urlNotSpecifiedStatus = urlNotSpecifiedRequest.status;
+ const urlNotSpecifiedMessage = urlNotSpecifiedRequest.body.message;
+
+ const urlNotFilledRequest = await request(app).get(
+ `${fileEndpointName}?url=`,
+ );
+ const urlNotFilledStatus = urlNotFilledRequest.status;
+ const urlNotFilledMessage = urlNotFilledRequest.body.message;
+
+ const expectedStatusCode = 400;
+ const expectedErrorMessage = 'No URL provided';
+
+ expect(urlNotSpecifiedStatus).toBe(expectedStatusCode);
+ expect(urlNotSpecifiedMessage).toBe(expectedErrorMessage);
+
+ expect(urlNotFilledStatus).toBe(expectedStatusCode);
+ expect(urlNotFilledMessage).toBe(expectedErrorMessage);
+ });
+
+ it('returns the correct file contents when reading a url', async () => {
+ const fileOneResponse = await request(app).get(
+ `${fileEndpointName}?url=testFileOne`,
+ );
+ const fileOneStatus = fileOneResponse.status;
+ const fileOneBody = fileOneResponse.body;
+ const fileOneError = fileOneResponse.error;
+
+ const fileTwoResponse = await request(app).get(
+ `${fileEndpointName}?url=testFileTwo`,
+ );
+ const fileTwoStatus = fileTwoResponse.status;
+ const fileTwoBody = fileTwoResponse.body;
+ const fileTwoError = fileTwoResponse.error;
+
+ const expectedStatusCode = 200;
+
+ expect(fileOneError).toBeFalsy();
+ expect(fileOneStatus).toBe(expectedStatusCode);
+ expect(fileOneBody.data).toBe(testFileOneContent);
+
+ expect(fileTwoError).toBeFalsy();
+ expect(fileTwoStatus).toBe(expectedStatusCode);
+ expect(fileTwoBody.data).toBe(testFileTwoContent);
+ });
+ });
+});
diff --git a/plugins/adr-backend/src/service/router.ts b/plugins/adr-backend/src/service/router.ts
new file mode 100644
index 0000000000..e6603ab346
--- /dev/null
+++ b/plugins/adr-backend/src/service/router.ts
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2022 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 { CacheClient, UrlReader } from '@backstage/backend-common';
+import { NotModifiedError, stringifyError } from '@backstage/errors';
+import { Logger } from 'winston';
+import express from 'express';
+import Router from 'express-promise-router';
+
+/** @public */
+export type AdrRouterOptions = {
+ reader: UrlReader;
+ cacheClient: CacheClient;
+ logger: Logger;
+};
+
+/** @public */
+export async function createRouter(
+ options: AdrRouterOptions,
+): Promise {
+ const { reader, cacheClient, logger } = options;
+
+ const router = Router();
+ router.use(express.json());
+
+ router.get('/list', async (req, res) => {
+ const urlToProcess = req.query.url as string;
+ if (!urlToProcess) {
+ res.statusCode = 400;
+ res.json({ message: 'No URL provided' });
+ return;
+ }
+
+ const cachedTree = (await cacheClient.get(urlToProcess)) as {
+ data: {
+ type: string;
+ name: string;
+ path: string;
+ }[];
+ etag: string;
+ };
+ const cachedData = cachedTree?.data;
+
+ try {
+ const treeGetResponse = await reader.readTree(urlToProcess, {
+ etag: cachedTree?.etag,
+ });
+ const files = await treeGetResponse.files();
+ const data = files.map(file => {
+ return {
+ type: 'file',
+ name: file.path.substring(file.path.lastIndexOf('/') + 1),
+ path: file.path,
+ };
+ });
+
+ await cacheClient.set(urlToProcess, {
+ data,
+ etag: treeGetResponse.etag,
+ });
+
+ res.json({ data });
+ } catch (error: any) {
+ if (cachedData && error.name === NotModifiedError.name) {
+ res.json({ data: cachedData });
+ return;
+ }
+
+ const message = stringifyError(error);
+ logger.error(`Unable to fetch ADRs from ${urlToProcess}: ${message}`);
+ res.statusCode = 500;
+ res.json({ message });
+ }
+ });
+
+ router.get('/file', async (req, res) => {
+ const urlToProcess = req.query.url as string;
+ if (!urlToProcess) {
+ res.statusCode = 400;
+ res.json({ message: 'No URL provided' });
+ return;
+ }
+
+ const cachedFileContent = (await cacheClient.get(urlToProcess)) as {
+ data: string;
+ etag: string;
+ };
+
+ try {
+ const fileGetResponse = await reader.readUrl(urlToProcess, {
+ etag: cachedFileContent?.etag,
+ });
+ const fileBuffer = await fileGetResponse.buffer();
+ const data = fileBuffer.toString();
+
+ await cacheClient.set(urlToProcess, {
+ data,
+ etag: fileGetResponse.etag,
+ });
+
+ res.json({ data });
+ } catch (error) {
+ if (cachedFileContent && error.name === NotModifiedError.name) {
+ res.json({ data: cachedFileContent.data });
+ return;
+ }
+
+ const message = stringifyError(error);
+ logger.error(`Unable to fetch ADRs from ${urlToProcess}: ${message}`);
+ res.statusCode = 500;
+ res.json({ message });
+ }
+ });
+
+ return router;
+}
diff --git a/plugins/adr/README.md b/plugins/adr/README.md
index 2888ff2f07..b9cc5d84ba 100644
--- a/plugins/adr/README.md
+++ b/plugins/adr/README.md
@@ -4,17 +4,19 @@ Welcome to the ADR plugin!
This plugin allows you to browse ADRs associated with your entities as well as a way to discover ADRs across others entities via Backstage Search. Use this to learn from the past experience of other projects to guide your own architecture decisions.
-NOTE: This plugin currently only supports entities/ADRs registered via GitHub integration.
-
## Setup
-Install this plugin:
+1. Install this plugin:
```bash
# From your Backstage root directory
yarn --cwd packages/app add @backstage/plugin-adr
```
+2. Make sure the [ADR backend plugin](../adr-backend/README.md) is installed.
+
+3. [Configure integrations](https://backstage.io/docs/integrations/) for all sites you would like to pull ADRs from.
+
### Entity Pages
1. Add the plugin as a tab to your Entity pages:
@@ -79,7 +81,7 @@ case 'adr':
## Custom ADR formats
-By default, this plugin will parse ADRs according to the format specified by the [Markdown Architecture Decision Record (MADR)](https://adr.github.io/madr/) template. If your ADRs are written using a different format, you can apply the following customizations to correctly identify and parse your documents:
+By default, this plugin will parse ADRs according to the format specified by the [Markdown Architecture Decision Record (MADR) v2.x template](https://github.com/adr/madr/tree/2.1.2). If your ADRs are written using a different format, you can apply the following customizations to correctly identify and parse your documents:
### Custom Filename/Path Format
diff --git a/plugins/adr/api-report.md b/plugins/adr/api-report.md
index ecec0c0dd5..d6480cd090 100644
--- a/plugins/adr/api-report.md
+++ b/plugins/adr/api-report.md
@@ -7,11 +7,37 @@
import { AdrDocument } from '@backstage/plugin-adr-common';
import { AdrFilePathFilterFn } from '@backstage/plugin-adr-common';
+import { ApiRef } from '@backstage/core-plugin-api';
import { BackstagePlugin } from '@backstage/core-plugin-api';
+import { DiscoveryApi } from '@backstage/core-plugin-api';
import { isAdrAvailable } from '@backstage/plugin-adr-common';
import { ResultHighlight } from '@backstage/plugin-search-common';
import { RouteRef } from '@backstage/core-plugin-api';
+// @public
+export interface AdrApi {
+ listAdrs(url: string): Promise;
+ readAdr(url: string): Promise;
+}
+
+// @public
+export const adrApiRef: ApiRef;
+
+// @public
+export class AdrClient implements AdrApi {
+ constructor(options: AdrClientOptions);
+ // (undocumented)
+ listAdrs(url: string): Promise;
+ // (undocumented)
+ readAdr(url: string): Promise;
+}
+
+// @public
+export interface AdrClientOptions {
+ // (undocumented)
+ discoveryApi: DiscoveryApi;
+}
+
// @public
export type AdrContentDecorator = (adrInfo: {
baseUrl: string;
@@ -20,6 +46,18 @@ export type AdrContentDecorator = (adrInfo: {
content: string;
};
+// @public
+export type AdrFileInfo = {
+ type: string;
+ path: string;
+ name: string;
+};
+
+// @public
+export type AdrListResult = {
+ data: AdrFileInfo[];
+};
+
// @public
export const adrPlugin: BackstagePlugin<
{
@@ -38,6 +76,11 @@ export const AdrReader: {
}>;
};
+// @public
+export type AdrReadResult = {
+ data: string;
+};
+
// @public
export function AdrSearchResultListItem(props: {
lineClamp?: number;
diff --git a/plugins/adr/package.json b/plugins/adr/package.json
index 00cf052365..30d0b846a3 100644
--- a/plugins/adr/package.json
+++ b/plugins/adr/package.json
@@ -34,8 +34,6 @@
"@material-ui/core": "^4.12.2",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.57",
- "git-url-parse": "^13.0.0",
- "octokit": "^2.0.0",
"react-markdown": "^8.0.0",
"react-use": "^17.2.4",
"remark-gfm": "^3.0.1"
diff --git a/plugins/adr/src/api/AdrClient.ts b/plugins/adr/src/api/AdrClient.ts
new file mode 100644
index 0000000000..da1adc04e4
--- /dev/null
+++ b/plugins/adr/src/api/AdrClient.ts
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2022 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 { DiscoveryApi } from '@backstage/core-plugin-api';
+import { AdrApi, AdrListResult, AdrReadResult } from './types';
+
+/**
+ * Options for creating an AdrClient.
+ *
+ * @public
+ */
+export interface AdrClientOptions {
+ discoveryApi: DiscoveryApi;
+}
+
+const readEndpoint = 'file';
+const listEndpoint = 'list';
+
+/**
+ * An implementation of the AdrApi that communicates with the ADR backend plugin.
+ *
+ * @public
+ */
+export class AdrClient implements AdrApi {
+ private readonly discoveryApi: DiscoveryApi;
+
+ constructor(options: AdrClientOptions) {
+ this.discoveryApi = options.discoveryApi;
+ }
+
+ private async fetchAdrApi(endpoint: string, fileUrl: string): Promise {
+ const baseUrl = await this.discoveryApi.getBaseUrl('adr');
+ const targetUrl = `${baseUrl}/${endpoint}?url=${encodeURIComponent(
+ fileUrl,
+ )}`;
+
+ const result = await fetch(targetUrl);
+ const data = await result.json();
+
+ if (!result.ok) {
+ throw new Error(`${data.message}`);
+ }
+ return data;
+ }
+
+ async listAdrs(url: string): Promise {
+ return this.fetchAdrApi(listEndpoint, url);
+ }
+
+ async readAdr(url: string): Promise {
+ return this.fetchAdrApi(readEndpoint, url);
+ }
+}
diff --git a/plugins/adr/src/api/index.ts b/plugins/adr/src/api/index.ts
new file mode 100644
index 0000000000..095da3519d
--- /dev/null
+++ b/plugins/adr/src/api/index.ts
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2022 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.
+ */
+
+export { AdrClient } from './AdrClient';
+export type { AdrClientOptions } from './AdrClient';
+export { adrApiRef } from './types';
+export type {
+ AdrApi,
+ AdrFileInfo,
+ AdrListResult,
+ AdrReadResult,
+} from './types';
diff --git a/plugins/adr/src/api/types.ts b/plugins/adr/src/api/types.ts
new file mode 100644
index 0000000000..e4632e171a
--- /dev/null
+++ b/plugins/adr/src/api/types.ts
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2022 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 { createApiRef } from '@backstage/core-plugin-api';
+
+/**
+ * Contains information about an ADR file.
+ *
+ * @public
+ */
+export type AdrFileInfo = {
+ /** The file type. */
+ type: string;
+
+ /** The relative path of the ADR file. */
+ path: string;
+
+ /** The name of the ADR file. */
+ name: string;
+};
+
+/**
+ * The result of listing ADRs.
+ *
+ * @public
+ */
+export type AdrListResult = {
+ data: AdrFileInfo[];
+};
+
+/**
+ * The result of reading an ADR.
+ *
+ * @public
+ */
+export type AdrReadResult = {
+ /** The contents of the read ADR file. */
+ data: string;
+};
+
+/**
+ * The API used by the adr plugin to list and read ADRs.
+ *
+ * @public
+ */
+export interface AdrApi {
+ /** Lists the ADRs at the provided url. */
+ listAdrs(url: string): Promise;
+
+ /** Reads the contents of the ADR at the provided url. */
+ readAdr(url: string): Promise;
+}
+
+/**
+ * ApiRef for the AdrApi.
+ *
+ * @public
+ */
+export const adrApiRef = createApiRef({
+ id: 'plugin.adr.api',
+});
diff --git a/plugins/adr/src/components/AdrReader/AdrReader.tsx b/plugins/adr/src/components/AdrReader/AdrReader.tsx
index 971dae0949..ad99ce3a5a 100644
--- a/plugins/adr/src/components/AdrReader/AdrReader.tsx
+++ b/plugins/adr/src/components/AdrReader/AdrReader.tsx
@@ -26,9 +26,10 @@ import { scmIntegrationsApiRef } from '@backstage/integration-react';
import { getAdrLocationUrl } from '@backstage/plugin-adr-common';
import { useEntity } from '@backstage/plugin-catalog-react';
-import { useOctokitRequest } from '../../hooks';
import { adrDecoratorFactories } from './decorators';
import { AdrContentDecorator } from './types';
+import { adrApiRef } from '../../api';
+import useAsync from 'react-use/lib/useAsync';
/**
* Component to fetch and render an ADR.
@@ -42,10 +43,13 @@ export const AdrReader = (props: {
const { adr, decorators } = props;
const { entity } = useEntity();
const scmIntegrations = useApi(scmIntegrationsApiRef);
+ const adrApi = useApi(adrApiRef);
const adrLocationUrl = getAdrLocationUrl(entity, scmIntegrations);
- const { value, loading, error } = useOctokitRequest(
- `${adrLocationUrl.replace(/\/$/, '')}/${adr}`,
+ const url = `${adrLocationUrl.replace(/\/$/, '')}/${adr}`;
+ const { value, loading, error } = useAsync(
+ async () => adrApi.readAdr(url),
+ [url],
);
const adrContent = useMemo(() => {
diff --git a/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx b/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx
index 37344cecca..a698cffd26 100644
--- a/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx
+++ b/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx
@@ -44,9 +44,10 @@ import {
Typography,
} from '@material-ui/core';
-import { useOctokitRequest } from '../../hooks';
import { rootRouteRef } from '../../routes';
import { AdrContentDecorator, AdrReader } from '../AdrReader';
+import { adrApiRef } from '../../api';
+import useAsync from 'react-use/lib/useAsync';
const useStyles = makeStyles((theme: Theme) => ({
adrMenu: {
@@ -69,10 +70,13 @@ export const EntityAdrContent = (props: {
const [adrList, setAdrList] = useState([]);
const [searchParams, setSearchParams] = useSearchParams();
const scmIntegrations = useApi(scmIntegrationsApiRef);
+ const adrApi = useApi(adrApiRef);
const entityHasAdrs = isAdrAvailable(entity);
- const { value, loading, error } = useOctokitRequest(
- getAdrLocationUrl(entity, scmIntegrations),
+ const url = getAdrLocationUrl(entity, scmIntegrations);
+ const { value, loading, error } = useAsync(
+ async () => adrApi.listAdrs(url),
+ [url],
);
const selectedAdr =
diff --git a/plugins/adr/src/hooks/useOctokitRequest.ts b/plugins/adr/src/hooks/useOctokitRequest.ts
deleted file mode 100644
index f160651169..0000000000
--- a/plugins/adr/src/hooks/useOctokitRequest.ts
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2022 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 parseGitUrl from 'git-url-parse';
-import useAsync from 'react-use/lib/useAsync';
-import { Octokit } from 'octokit';
-import { useApi } from '@backstage/core-plugin-api';
-import {
- scmAuthApiRef,
- scmIntegrationsApiRef,
-} from '@backstage/integration-react';
-
-/**
- * Hook for triggering authenticated Octokit requests against the GitHub Content API
- * @public
- */
-export const useOctokitRequest = (request: string): any => {
- const authApi = useApi(scmAuthApiRef);
- const scmIntegrations = useApi(scmIntegrationsApiRef);
-
- const { owner, name, ref, filepath } = parseGitUrl(request);
- const path = filepath.replace(/^\//, '');
- const baseUrl = scmIntegrations.github.byUrl(request)?.config.apiBaseUrl;
-
- return useAsync(async () => {
- const { token } = await authApi.getCredentials({
- url: request,
- additionalScope: {
- customScopes: {
- github: ['repo'],
- },
- },
- });
- const octokit = new Octokit({
- auth: token,
- baseUrl,
- });
-
- return octokit.request(
- `GET /repos/${owner}/${name}/contents/${path}?ref=${ref}`,
- {
- headers: { Accept: 'application/vnd.github.v3.raw' },
- },
- );
- }, [request]);
-};
diff --git a/plugins/adr/src/index.ts b/plugins/adr/src/index.ts
index 84012ccb7a..2ec76b0fd6 100644
--- a/plugins/adr/src/index.ts
+++ b/plugins/adr/src/index.ts
@@ -13,11 +13,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
/**
* ADR frontend plugin
*
* @packageDocumentation
*/
+
+export { adrApiRef, AdrClient } from './api';
+export type {
+ AdrApi,
+ AdrClientOptions,
+ AdrFileInfo,
+ AdrListResult,
+ AdrReadResult,
+} from './api';
export { isAdrAvailable } from '@backstage/plugin-adr-common';
export * from './components/AdrReader';
export { adrPlugin, EntityAdrContent } from './plugin';
diff --git a/plugins/adr/src/plugin.ts b/plugins/adr/src/plugin.ts
index 03437b1f0b..f23df826cd 100644
--- a/plugins/adr/src/plugin.ts
+++ b/plugins/adr/src/plugin.ts
@@ -14,11 +14,13 @@
* limitations under the License.
*/
+import { adrApiRef, AdrClient } from './api';
import {
+ createApiFactory,
createPlugin,
createRoutableExtension,
+ discoveryApiRef,
} from '@backstage/core-plugin-api';
-
import { rootRouteRef } from './routes';
/**
@@ -27,6 +29,17 @@ import { rootRouteRef } from './routes';
*/
export const adrPlugin = createPlugin({
id: 'adr',
+ apis: [
+ createApiFactory({
+ api: adrApiRef,
+ deps: {
+ discoveryApi: discoveryApiRef,
+ },
+ factory({ discoveryApi }) {
+ return new AdrClient({ discoveryApi });
+ },
+ }),
+ ],
routes: {
root: rootRouteRef,
},
diff --git a/plugins/app-backend/src/service/appPlugin.test.ts b/plugins/app-backend/src/service/appPlugin.test.ts
index 14921622c9..80408694d6 100644
--- a/plugins/app-backend/src/service/appPlugin.test.ts
+++ b/plugins/app-backend/src/service/appPlugin.test.ts
@@ -23,6 +23,7 @@ import { appPlugin } from './appPlugin';
import {
databaseFactory,
httpRouterFactory,
+ rootHttpRouterFactory,
loggerFactory,
rootLoggerFactory,
} from '@backstage/backend-app-api';
@@ -63,6 +64,7 @@ describe('appPlugin', () => {
rootLoggerFactory(),
databaseFactory(),
httpRouterFactory(),
+ rootHttpRouterFactory(),
],
features: [
appPlugin({
diff --git a/plugins/app-backend/src/service/appPlugin.ts b/plugins/app-backend/src/service/appPlugin.ts
index bfccf3cc02..2c0c73c71b 100644
--- a/plugins/app-backend/src/service/appPlugin.ts
+++ b/plugins/app-backend/src/service/appPlugin.ts
@@ -18,9 +18,9 @@ import express from 'express';
import {
coreServices,
createBackendPlugin,
- loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
import { createRouter } from './router';
+import { loggerToWinstonLogger } from '@backstage/backend-common';
/** @alpha */
export type AppPluginOptions = {
diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md
index cec3422d9c..88cb33863e 100644
--- a/plugins/auth-backend/api-report.md
+++ b/plugins/auth-backend/api-report.md
@@ -7,7 +7,7 @@
import { BackstageIdentityResponse } from '@backstage/plugin-auth-node';
import { BackstageSignInResult } from '@backstage/plugin-auth-node';
-import { CacheClient } from '@backstage/backend-common';
+import { CacheClient } from '@backstage/backend-plugin-api';
import { CatalogApi } from '@backstage/catalog-client';
import { Config } from '@backstage/config';
import { Entity } from '@backstage/catalog-model';
diff --git a/plugins/bitbucket-cloud-common/package.json b/plugins/bitbucket-cloud-common/package.json
index 1ea48b000e..985949c836 100644
--- a/plugins/bitbucket-cloud-common/package.json
+++ b/plugins/bitbucket-cloud-common/package.json
@@ -34,7 +34,7 @@
"@backstage/cli": "workspace:^",
"@openapitools/openapi-generator-cli": "^2.4.26",
"msw": "^0.49.0",
- "ts-morph": "^15.0.0"
+ "ts-morph": "^17.0.0"
},
"files": [
"dist"
diff --git a/plugins/catalog-backend-module-aws/src/service/AwsS3EntityProviderCatalogModule.ts b/plugins/catalog-backend-module-aws/src/service/AwsS3EntityProviderCatalogModule.ts
index fa49d1e4c7..cbc137ab40 100644
--- a/plugins/catalog-backend-module-aws/src/service/AwsS3EntityProviderCatalogModule.ts
+++ b/plugins/catalog-backend-module-aws/src/service/AwsS3EntityProviderCatalogModule.ts
@@ -14,10 +14,10 @@
* limitations under the License.
*/
+import { loggerToWinstonLogger } from '@backstage/backend-common';
import {
coreServices,
createBackendModule,
- loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';
import { AwsS3EntityProvider } from '../providers';
diff --git a/plugins/catalog-backend-module-azure/src/service/AzureDevOpsEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-azure/src/service/AzureDevOpsEntityProviderCatalogModule.ts
index 0d0ebdb591..bd59cec29b 100644
--- a/plugins/catalog-backend-module-azure/src/service/AzureDevOpsEntityProviderCatalogModule.ts
+++ b/plugins/catalog-backend-module-azure/src/service/AzureDevOpsEntityProviderCatalogModule.ts
@@ -14,9 +14,9 @@
* limitations under the License.
*/
+import { loggerToWinstonLogger } from '@backstage/backend-common';
import {
createBackendModule,
- loggerToWinstonLogger,
coreServices,
} from '@backstage/backend-plugin-api';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';
diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.ts
index 19b83b92b6..d17656a473 100644
--- a/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.ts
+++ b/plugins/catalog-backend-module-bitbucket-cloud/src/service/BitbucketCloudEntityProviderCatalogModule.ts
@@ -14,10 +14,10 @@
* limitations under the License.
*/
+import { loggerToWinstonLogger } from '@backstage/backend-common';
import {
coreServices,
createBackendModule,
- loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
import {
catalogProcessingExtensionPoint,
diff --git a/plugins/catalog-backend-module-bitbucket-server/src/service/BitbucketServerEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-bitbucket-server/src/service/BitbucketServerEntityProviderCatalogModule.ts
index e0f5a21ff9..46712d29dd 100644
--- a/plugins/catalog-backend-module-bitbucket-server/src/service/BitbucketServerEntityProviderCatalogModule.ts
+++ b/plugins/catalog-backend-module-bitbucket-server/src/service/BitbucketServerEntityProviderCatalogModule.ts
@@ -14,10 +14,10 @@
* limitations under the License.
*/
+import { loggerToWinstonLogger } from '@backstage/backend-common';
import {
coreServices,
createBackendModule,
- loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';
import { BitbucketServerEntityProvider } from '../providers';
diff --git a/plugins/catalog-backend-module-gerrit/src/service/GerritEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-gerrit/src/service/GerritEntityProviderCatalogModule.ts
index 674845862f..8c61038c8f 100644
--- a/plugins/catalog-backend-module-gerrit/src/service/GerritEntityProviderCatalogModule.ts
+++ b/plugins/catalog-backend-module-gerrit/src/service/GerritEntityProviderCatalogModule.ts
@@ -14,10 +14,10 @@
* limitations under the License.
*/
+import { loggerToWinstonLogger } from '@backstage/backend-common';
import {
coreServices,
createBackendModule,
- loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';
import { GerritEntityProvider } from '../providers/GerritEntityProvider';
diff --git a/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts
index e61543ea13..d9dc0a12aa 100644
--- a/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts
+++ b/plugins/catalog-backend-module-github/src/service/GithubEntityProviderCatalogModule.ts
@@ -16,9 +16,9 @@
import {
createBackendModule,
- loggerToWinstonLogger,
coreServices,
} from '@backstage/backend-plugin-api';
+import { loggerToWinstonLogger } from '@backstage/backend-common';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';
import { GithubEntityProvider } from '../providers/GithubEntityProvider';
diff --git a/plugins/catalog-backend-module-gitlab/src/service/GitlabDiscoveryEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-gitlab/src/service/GitlabDiscoveryEntityProviderCatalogModule.ts
index 75a8de263f..bb4fb656a8 100644
--- a/plugins/catalog-backend-module-gitlab/src/service/GitlabDiscoveryEntityProviderCatalogModule.ts
+++ b/plugins/catalog-backend-module-gitlab/src/service/GitlabDiscoveryEntityProviderCatalogModule.ts
@@ -16,9 +16,9 @@
import {
createBackendModule,
- loggerToWinstonLogger,
coreServices,
} from '@backstage/backend-plugin-api';
+import { loggerToWinstonLogger } from '@backstage/backend-common';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';
import { GitlabDiscoveryEntityProvider } from '../providers';
diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/module/WrapperProviders.ts b/plugins/catalog-backend-module-incremental-ingestion/src/module/WrapperProviders.ts
index a6cfe14df2..abe4cdb951 100644
--- a/plugins/catalog-backend-module-incremental-ingestion/src/module/WrapperProviders.ts
+++ b/plugins/catalog-backend-module-incremental-ingestion/src/module/WrapperProviders.ts
@@ -18,8 +18,8 @@ import {
ConfigService,
LoggerService,
SchedulerService,
- loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
+import { loggerToWinstonLogger } from '@backstage/backend-common';
import { stringifyError } from '@backstage/errors';
import {
EntityProvider,
diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json
index 5bfe4e35ea..4ff9952bc5 100644
--- a/plugins/catalog-backend-module-msgraph/package.json
+++ b/plugins/catalog-backend-module-msgraph/package.json
@@ -34,6 +34,7 @@
},
"dependencies": {
"@azure/identity": "^2.1.0",
+ "@backstage/backend-common": "workspace:^",
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/backend-tasks": "workspace:^",
"@backstage/catalog-model": "workspace:^",
diff --git a/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.ts b/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.ts
index 2643e6e937..fc63867a23 100644
--- a/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.ts
+++ b/plugins/catalog-backend-module-msgraph/src/service/MicrosoftGraphOrgEntityProviderCatalogModule.ts
@@ -17,8 +17,8 @@
import {
coreServices,
createBackendModule,
- loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
+import { loggerToWinstonLogger } from '@backstage/backend-common';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node';
import {
GroupTransformer,
diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json
index b45918dc43..93a5846bbf 100644
--- a/plugins/catalog-backend/package.json
+++ b/plugins/catalog-backend/package.json
@@ -80,7 +80,7 @@
"@types/lodash": "^4.14.151",
"@types/supertest": "^2.0.8",
"@types/uuid": "^8.0.0",
- "better-sqlite3": "^7.5.0",
+ "better-sqlite3": "^8.0.0",
"luxon": "^3.0.0",
"msw": "^0.49.0",
"supertest": "^6.1.3",
diff --git a/plugins/catalog-backend/src/service/CatalogPlugin.ts b/plugins/catalog-backend/src/service/CatalogPlugin.ts
index 6db54ed4fa..effed7f8f1 100644
--- a/plugins/catalog-backend/src/service/CatalogPlugin.ts
+++ b/plugins/catalog-backend/src/service/CatalogPlugin.ts
@@ -16,7 +16,6 @@
import {
createBackendPlugin,
coreServices,
- loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
import { CatalogBuilder } from './CatalogBuilder';
import {
@@ -25,6 +24,7 @@ import {
catalogProcessingExtensionPoint,
EntityProvider,
} from '@backstage/plugin-catalog-node';
+import { loggerToWinstonLogger } from '@backstage/backend-common';
class CatalogExtensionPointImpl implements CatalogProcessingExtensionPoint {
#processors = new Array();
diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts
index 541359feb6..6379d65043 100644
--- a/plugins/catalog-backend/src/service/createRouter.test.ts
+++ b/plugins/catalog-backend/src/service/createRouter.test.ts
@@ -268,6 +268,8 @@ describe('createRouter readonly disabled', () => {
'{"unknown":7}',
'{"entityRefs":7}',
'{"entityRefs":[7]}',
+ '{"entityRefs":[7],"fields":7}',
+ '{"entityRefs":[7],"fields":[7]}',
])('properly rejects malformed request body, %p', async p => {
await expect(
request(app)
@@ -283,8 +285,12 @@ describe('createRouter readonly disabled', () => {
const response = await request(app)
.post('/entities/by-refs')
.set('Content-Type', 'application/json')
- .send('{"entityRefs":["a"]}');
+ .send('{"entityRefs":["a"],"fields":["b"]}');
expect(entitiesCatalog.entitiesBatch).toHaveBeenCalledTimes(1);
+ expect(entitiesCatalog.entitiesBatch).toHaveBeenCalledWith({
+ entityRefs: ['a'],
+ fields: expect.any(Function),
+ });
expect(response.status).toEqual(200);
expect(response.body).toEqual({ items: [entity] });
});
diff --git a/plugins/catalog-backend/src/service/createRouter.ts b/plugins/catalog-backend/src/service/createRouter.ts
index 6a31fcd0b6..62a0f970c9 100644
--- a/plugins/catalog-backend/src/service/createRouter.ts
+++ b/plugins/catalog-backend/src/service/createRouter.ts
@@ -181,7 +181,7 @@ export async function createRouter(
const token = getBearerToken(req.header('authorization'));
const response = await entitiesCatalog.entitiesBatch({
entityRefs: request.entityRefs,
- fields: parseEntityTransformParams(req.query),
+ fields: parseEntityTransformParams(req.query, request.fields),
authorizationToken: token,
});
res.status(200).json(response);
diff --git a/plugins/catalog-backend/src/service/request/entitiesBatchRequest.ts b/plugins/catalog-backend/src/service/request/entitiesBatchRequest.ts
index b3a91f9491..d5469315be 100644
--- a/plugins/catalog-backend/src/service/request/entitiesBatchRequest.ts
+++ b/plugins/catalog-backend/src/service/request/entitiesBatchRequest.ts
@@ -20,9 +20,10 @@ import { z } from 'zod';
const schema = z.object({
entityRefs: z.array(z.string()),
+ fields: z.array(z.string()).optional(),
});
-export function entitiesBatchRequest(req: Request) {
+export function entitiesBatchRequest(req: Request): z.infer {
try {
return schema.parse(req.body);
} catch (error) {
diff --git a/plugins/catalog-backend/src/service/request/parseEntityTransformParams.test.ts b/plugins/catalog-backend/src/service/request/parseEntityTransformParams.test.ts
index 3dce579ae5..16141e401c 100644
--- a/plugins/catalog-backend/src/service/request/parseEntityTransformParams.test.ts
+++ b/plugins/catalog-backend/src/service/request/parseEntityTransformParams.test.ts
@@ -18,22 +18,26 @@ import { Entity } from '@backstage/catalog-model';
import { parseEntityTransformParams } from './parseEntityTransformParams';
describe('parseEntityTransformParams', () => {
- const entity: Entity = {
- apiVersion: 'av',
- kind: 'k',
- metadata: {
- name: 'n',
- tags: ['t1', 't2'],
- annotations: {
- 'example.test/url-like-key': 'ul1',
- 'example.com/other-url-like-key': 'ul2',
- 'other-example.test/next-url-like-key': 'ul3',
+ let entity: Entity;
+
+ beforeEach(() => {
+ entity = {
+ apiVersion: 'av',
+ kind: 'k',
+ metadata: {
+ name: 'n',
+ tags: ['t1', 't2'],
+ annotations: {
+ 'example.test/url-like-key': 'ul1',
+ 'example.com/other-url-like-key': 'ul2',
+ 'other-example.test/next-url-like-key': 'ul3',
+ },
},
- },
- spec: {
- type: 't',
- },
- };
+ spec: {
+ type: 't',
+ },
+ };
+ });
it('returns undefined when no fields given', () => {
expect(parseEntityTransformParams({})).toBeUndefined();
@@ -46,7 +50,9 @@ describe('parseEntityTransformParams', () => {
it('rejects attempts at array filtering', () => {
expect(() =>
parseEntityTransformParams({ fields: 'metadata.tags[0]' })!(entity),
- ).toThrow(/invalid fields, array type fields are not supported/i);
+ ).toThrow(
+ 'Invalid field "metadata.tags[0]", array type fields are not supported',
+ );
});
it('accepts both strings and arrays of strings as input', () => {
@@ -177,4 +183,18 @@ describe('parseEntityTransformParams', () => {
),
).toEqual({ kind: 'k' });
});
+
+ it('handles both query params and extras, dealing with overlaps', () => {
+ expect(
+ parseEntityTransformParams({ fields: 'kind' }, [
+ 'kind',
+ 'metadata.name',
+ ])!(entity),
+ ).toEqual({
+ kind: 'k',
+ metadata: {
+ name: 'n',
+ },
+ });
+ });
});
diff --git a/plugins/catalog-backend/src/service/request/parseEntityTransformParams.ts b/plugins/catalog-backend/src/service/request/parseEntityTransformParams.ts
index cef6e5ef64..e203450103 100644
--- a/plugins/catalog-backend/src/service/request/parseEntityTransformParams.ts
+++ b/plugins/catalog-backend/src/service/request/parseEntityTransformParams.ts
@@ -38,24 +38,28 @@ function getPathArrayAndValue(input: Entity, field: string) {
export function parseEntityTransformParams(
params: Record,
+ extra?: string[],
): ((entity: Entity) => Entity) | undefined {
- const fieldsStrings = parseStringsParam(params.fields, 'fields');
- if (!fieldsStrings) {
- return undefined;
- }
+ const queryFields = parseStringsParam(params.fields, 'fields');
- const fields = fieldsStrings
- .map(s => s.split(','))
- .flat()
- .map(s => s.trim())
- .filter(Boolean);
+ const fields = Array.from(
+ new Set(
+ [...(extra ?? []), ...(queryFields?.map(s => s.split(',')) ?? [])]
+ .flat()
+ .map(s => s.trim())
+ .filter(Boolean),
+ ),
+ );
if (!fields.length) {
return undefined;
}
- if (fields.some(f => f.includes('['))) {
- throw new InputError('invalid fields, array type fields are not supported');
+ const arrayTypeField = fields.find(f => f.includes('['));
+ if (arrayTypeField) {
+ throw new InputError(
+ `Invalid field "${arrayTypeField}", array type fields are not supported`,
+ );
}
return input => {
diff --git a/plugins/catalog-import/api-report.md b/plugins/catalog-import/api-report.md
index 90c01255b0..b4c8e854aa 100644
--- a/plugins/catalog-import/api-report.md
+++ b/plugins/catalog-import/api-report.md
@@ -193,7 +193,7 @@ export interface ImportInfoCardProps {
}
// Warning: (ae-forgotten-export) The symbol "State" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "ImportState" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "ImportState" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type ImportState = State & {
@@ -346,7 +346,7 @@ export interface StepPrepareCreatePullRequestProps {
notRepeatable?: boolean;
},
) => void;
- // Warning: (ae-forgotten-export) The symbol "FormData" needs to be exported by the entry point index.d.ts
+ // Warning: (ae-forgotten-export) The symbol "FormData_2" needs to be exported by the entry point index.d.ts
//
// (undocumented)
renderFormFields: (
diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md
index 92bfc4de96..9528c55326 100644
--- a/plugins/catalog-react/api-report.md
+++ b/plugins/catalog-react/api-report.md
@@ -254,6 +254,17 @@ export class EntityOwnerFilter implements EntityFilter {
// @public (undocumented)
export const EntityOwnerPicker: () => JSX.Element | null;
+// @public
+export const EntityPeekAheadPopover: (
+ props: EntityPeekAheadPopoverProps,
+) => JSX.Element;
+
+// @public
+export type EntityPeekAheadPopoverProps = PropsWithChildren<{
+ entityRef: string;
+ delayTime?: number;
+}>;
+
// @public (undocumented)
export const EntityProcessingStatusPicker: () => JSX.Element;
diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json
index 9c9757f161..14a3ce8df5 100644
--- a/plugins/catalog-react/package.json
+++ b/plugins/catalog-react/package.json
@@ -51,6 +51,7 @@
"classnames": "^2.2.6",
"jwt-decode": "^3.1.0",
"lodash": "^4.17.21",
+ "material-ui-popup-state": "^1.9.3",
"qs": "^6.9.4",
"react-use": "^17.2.4",
"yaml": "^2.0.0",
diff --git a/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/EmailCardAction.tsx b/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/EmailCardAction.tsx
new file mode 100644
index 0000000000..2fcb89eed1
--- /dev/null
+++ b/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/EmailCardAction.tsx
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2022 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 { IconButton } from '@material-ui/core';
+import EmailIcon from '@material-ui/icons/Email';
+import React from 'react';
+import { Link } from '@backstage/core-components';
+
+/**
+ * Email Card action link
+ *
+ * @private
+ */
+export const EmailCardAction = ({ email }: { email: string }) => {
+ return (
+
+
+
+ );
+};
diff --git a/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/EntityCardActions.tsx b/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/EntityCardActions.tsx
new file mode 100644
index 0000000000..fc8b5f4007
--- /dev/null
+++ b/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/EntityCardActions.tsx
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2022 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 { entityRouteRef } from '../../../routes';
+import { IconButton } from '@material-ui/core';
+import InfoIcon from '@material-ui/icons/Info';
+import React from 'react';
+import { useRouteRef } from '@backstage/core-plugin-api';
+import { Entity } from '@backstage/catalog-model';
+import { Link } from '@backstage/core-components';
+
+/**
+ * Card actions that show for all entities
+ *
+ * @private
+ */
+export const EntityCardActions = ({ entity }: { entity: Entity }) => {
+ const entityRoute = useRouteRef(entityRouteRef);
+
+ return (
+
+
+
+ );
+};
diff --git a/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/GroupCardActions.tsx b/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/GroupCardActions.tsx
new file mode 100644
index 0000000000..fca0763703
--- /dev/null
+++ b/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/GroupCardActions.tsx
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2022 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 { EmailCardAction } from './EmailCardAction';
+import React from 'react';
+import { GroupEntity } from '@backstage/catalog-model';
+
+/**
+ * Card actions that show for a group
+ *
+ * @private
+ */
+export const GroupCardActions = ({ entity }: { entity: GroupEntity }) => {
+ return (
+ <>
+ {entity.spec.profile?.email && (
+
+ )}
+ >
+ );
+};
diff --git a/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/UserCardActions.tsx b/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/UserCardActions.tsx
new file mode 100644
index 0000000000..57801497f6
--- /dev/null
+++ b/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/UserCardActions.tsx
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2022 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 { EmailCardAction } from './EmailCardAction';
+import React from 'react';
+import { UserEntity } from '@backstage/catalog-model';
+
+/**
+ * Card actions that show for a user
+ *
+ * @private
+ */
+export const UserCardActions = ({ entity }: { entity: UserEntity }) => {
+ return (
+ <>
+ {entity.spec.profile?.email && (
+
+ )}
+ >
+ );
+};
diff --git a/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/index.ts b/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/index.ts
new file mode 100644
index 0000000000..75959026f7
--- /dev/null
+++ b/plugins/catalog-react/src/components/EntityPeekAheadPopover/CardActionComponents/index.ts
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2022 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.
+ */
+export { EntityCardActions } from './EntityCardActions';
+export { GroupCardActions } from './GroupCardActions';
+export { UserCardActions } from './UserCardActions';
diff --git a/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.stories.tsx b/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.stories.tsx
new file mode 100644
index 0000000000..132042452b
--- /dev/null
+++ b/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.stories.tsx
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2022 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 React, { ComponentType } from 'react';
+import {
+ EntityPeekAheadPopover,
+ EntityPeekAheadPopoverProps,
+} from './EntityPeekAheadPopover';
+import Button from '@material-ui/core/Button';
+import { wrapInTestApp, TestApiProvider } from '@backstage/test-utils';
+import { catalogApiRef } from '../../api';
+import {
+ CompoundEntityRef,
+ parseEntityRef,
+ stringifyEntityRef,
+} from '@backstage/catalog-model';
+import { entityRouteRef } from '../../routes';
+import { CatalogApi } from '@backstage/catalog-client';
+import { Table, TableColumn } from '@backstage/core-components';
+import { EntityRefLink } from '../EntityRefLink';
+
+const mockCatalogApi = {
+ getEntityByRef: async (entityRef: CompoundEntityRef) => {
+ if (
+ entityRef.namespace === 'default' &&
+ entityRef.name === 'playback' &&
+ entityRef.kind === 'component'
+ ) {
+ return {
+ kind: 'Component',
+ metadata: {
+ name: 'playback',
+ namespace: 'default',
+ description: 'Details about the playback service',
+ },
+ };
+ }
+ if (
+ entityRef.namespace === 'default' &&
+ entityRef.name === 'fname.lname' &&
+ entityRef.kind === 'user'
+ ) {
+ return {
+ kind: 'User',
+ metadata: {
+ name: 'fname.lname',
+ namespace: 'default',
+ },
+ spec: {
+ profile: {
+ email: 'fname.lname@example.com',
+ },
+ },
+ };
+ }
+ if (
+ entityRef.namespace === 'default' &&
+ entityRef.name === 'slow.catalog.item' &&
+ entityRef.kind === 'component'
+ ) {
+ await new Promise(resolve => setTimeout(resolve, 3000));
+ return {
+ kind: 'Component',
+ metadata: {
+ name: 'slow.catalog.item',
+ namespace: 'default',
+ description: 'Details about the slow.catalog.item service',
+ },
+ };
+ }
+ return undefined;
+ },
+};
+
+const defaultArgs = {
+ entityRef: 'component:default/playback',
+};
+
+export default {
+ title: 'Catalog /PeekAheadPopover',
+ decorators: [
+ (Story: ComponentType<{}>) =>
+ wrapInTestApp(
+ <>
+
+
+
+ >,
+ {
+ mountedRoutes: {
+ '/catalog/:namespace/:kind/:name': entityRouteRef,
+ },
+ },
+ ),
+ ],
+};
+
+export const Default = (args: EntityPeekAheadPopoverProps) => (
+
+
+
+);
+Default.args = defaultArgs;
+
+export const User = (args: EntityPeekAheadPopoverProps) => (
+
+
+
+);
+User.args = {
+ entityRef: 'user:default/fname.lname',
+};
+
+export const NotFound = (args: EntityPeekAheadPopoverProps) => (
+
+
+
+);
+NotFound.args = {
+ entityRef: 'user:default/doesnt.exist',
+};
+
+export const SlowCatalogItem = (args: EntityPeekAheadPopoverProps) => (
+
+
+
+);
+SlowCatalogItem.args = {
+ entityRef: 'component:default/slow.catalog.item',
+};
+
+const columns: TableColumn[] = [
+ {
+ title: 'entity',
+ render: entityRef => {
+ return (
+
+
+
+ );
+ },
+ },
+ {
+ title: 'owner',
+ render: () => {
+ return (
+
+
+
+ );
+ },
+ },
+ {
+ title: 'name',
+ render: entityRef => stringifyEntityRef(entityRef),
+ },
+];
+export const TableOfItems = (args: { data: CompoundEntityRef[] }) => (
+
+);
+
+TableOfItems.args = {
+ data: [
+ {
+ name: 'playback',
+ kind: 'component',
+ namespace: 'default',
+ },
+ {
+ name: 'playback',
+ kind: 'component',
+ namespace: 'default',
+ },
+ {
+ name: 'playback',
+ kind: 'component',
+ namespace: 'default',
+ },
+ ],
+};
diff --git a/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.test.tsx b/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.test.tsx
new file mode 100644
index 0000000000..2fc630313f
--- /dev/null
+++ b/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.test.tsx
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2021 The Backstage Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { fireEvent, screen } from '@testing-library/react';
+import React from 'react';
+import { EntityPeekAheadPopover } from './EntityPeekAheadPopover';
+import { ApiProvider } from '@backstage/core-app-api';
+import { TestApiRegistry, renderInTestApp } from '@backstage/test-utils';
+import { catalogApiRef } from '../../api';
+import { CompoundEntityRef, Entity } from '@backstage/catalog-model';
+import { CatalogApi } from '@backstage/catalog-client';
+import { Button } from '@material-ui/core';
+import { entityRouteRef } from '../../routes';
+
+const catalogApi: Partial = {
+ getEntityByRef: async (
+ entityRef: CompoundEntityRef,
+ ): Promise => {
+ if (
+ entityRef.name === 'service1' &&
+ entityRef.namespace === 'default' &&
+ entityRef.kind === 'component'
+ ) {
+ return {
+ apiVersion: '',
+ kind: 'Component',
+ metadata: {
+ namespace: 'default',
+ name: 'service1',
+ },
+ spec: {
+ tags: ['java'],
+ },
+ };
+ }
+ return undefined;
+ },
+};
+
+const apis = TestApiRegistry.from([catalogApiRef, catalogApi]);
+
+describe('', () => {
+ it('renders all owners', async () => {
+ renderInTestApp(
+
+
+
+
+
+
+
+ ,
+ {
+ mountedRoutes: {
+ '/catalog/:namespace/:kind/:name': entityRouteRef,
+ },
+ },
+ );
+ expect(screen.getByText('s1')).toBeInTheDocument();
+ expect(screen.queryByText('service1')).toBeNull();
+ fireEvent.mouseOver(screen.getByTestId('popover1'));
+ expect(await screen.findByText('service1')).toBeInTheDocument();
+
+ expect(screen.getByText('s2')).toBeInTheDocument();
+ expect(screen.queryByText('service2')).toBeNull();
+ fireEvent.mouseOver(screen.getByTestId('popover2'));
+ expect(
+ await screen.findByText('Error: service2 was not found'),
+ ).toBeInTheDocument();
+ });
+});
diff --git a/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.tsx b/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.tsx
new file mode 100644
index 0000000000..05a818fa1f
--- /dev/null
+++ b/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.tsx
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2022 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 useAsyncFn from 'react-use/lib/useAsyncFn';
+import { catalogApiRef } from '../../api';
+import React, { PropsWithChildren, useEffect, useState } from 'react';
+import HoverPopover from 'material-ui-popup-state/HoverPopover';
+import {
+ bindHover,
+ bindPopover,
+ usePopupState,
+} from 'material-ui-popup-state/hooks';
+import {
+ Box,
+ Card,
+ CardActions,
+ CardContent,
+ Chip,
+ makeStyles,
+ Tooltip,
+ Typography,
+} from '@material-ui/core';
+import { useApiHolder } from '@backstage/core-plugin-api';
+import {
+ isGroupEntity,
+ isUserEntity,
+ parseEntityRef,
+} from '@backstage/catalog-model';
+import { Progress, ResponseErrorPanel } from '@backstage/core-components';
+import {
+ EntityCardActions,
+ UserCardActions,
+ GroupCardActions,
+} from './CardActionComponents';
+import { debounce } from 'lodash';
+
+/**
+ * Properties for an entity popover on hover of a component.
+ *
+ * @public
+ */
+export type EntityPeekAheadPopoverProps = PropsWithChildren<{
+ entityRef: string;
+ delayTime?: number;
+}>;
+
+const useStyles = makeStyles(() => {
+ return {
+ trigger: {
+ display: 'inline-block',
+ },
+ popoverPaper: {
+ width: '30em',
+ },
+ descriptionTypography: {
+ overflow: 'hidden',
+ textOverflow: 'ellipsis',
+ display: '-webkit-box',
+ WebkitLineClamp: 2,
+ WebkitBoxOrient: 'vertical',
+ },
+ };
+});
+
+const maxTagChips = 4;
+
+/**
+ * Shows an entity popover on hover of a component.
+ *
+ * @public
+ */
+export const EntityPeekAheadPopover = (props: EntityPeekAheadPopoverProps) => {
+ const { entityRef, children, delayTime = 500 } = props;
+
+ const classes = useStyles();
+ const apiHolder = useApiHolder();
+ const popupState = usePopupState({
+ variant: 'popover',
+ popupId: 'entity-peek-ahead',
+ });
+ const compoundEntityRef = parseEntityRef(entityRef);
+ const [isHovered, setIsHovered] = useState(false);
+
+ const debouncedHandleMouseEnter = debounce(
+ () => setIsHovered(true),
+ delayTime,
+ );
+
+ const [{ loading, error, value: entity }, load] = useAsyncFn(async () => {
+ const catalogApi = apiHolder.get(catalogApiRef);
+ if (catalogApi) {
+ const retrievedEntity = await catalogApi.getEntityByRef(
+ compoundEntityRef,
+ );
+ if (!retrievedEntity) {
+ throw new Error(`${compoundEntityRef.name} was not found`);
+ }
+ return retrievedEntity;
+ }
+ return undefined;
+ }, [apiHolder, compoundEntityRef]);
+
+ const handleOnMouseLeave = () => {
+ setIsHovered(false);
+ debouncedHandleMouseEnter.cancel();
+ };
+
+ useEffect(() => {
+ if (popupState.isOpen && !entity && !error && !loading) {
+ load();
+ }
+ }, [popupState.isOpen, load, entity, error, loading]);
+
+ return (
+ <>
+
+
+ {children}
+
+
+ {isHovered && (
+
+ <>
+ {error && }
+
+ {loading && }
+
+
+ {entity && (
+ <>
+
+ {compoundEntityRef.namespace}
+
+
+ {compoundEntityRef.name}
+
+ {entity.kind}
+
+ {entity.metadata.description}
+
+ {entity.spec?.type}
+
+ {(entity.metadata.tags || [])
+ .slice(0, maxTagChips)
+ .map(tag => {
+ return ;
+ })}
+ {entity.metadata.tags?.length &&
+ entity.metadata.tags?.length > maxTagChips && (
+
+
+
+ )}
+
+ >
+ )}
+
+ {!error && (
+
+ {entity && (
+ <>
+ {isUserEntity(entity) && (
+
+ )}
+ {isGroupEntity(entity) && (
+
+ )}
+
+ >
+ )}
+
+ )}
+
+ >
+
+ )}
+ >
+ );
+};
diff --git a/plugins/adr/src/hooks/index.ts b/plugins/catalog-react/src/components/EntityPeekAheadPopover/index.ts
similarity index 93%
rename from plugins/adr/src/hooks/index.ts
rename to plugins/catalog-react/src/components/EntityPeekAheadPopover/index.ts
index d5aa102fb8..6630f6f555 100644
--- a/plugins/adr/src/hooks/index.ts
+++ b/plugins/catalog-react/src/components/EntityPeekAheadPopover/index.ts
@@ -13,4 +13,4 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-export * from './useOctokitRequest';
+export * from './EntityPeekAheadPopover';
diff --git a/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.stories.tsx b/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.stories.tsx
new file mode 100644
index 0000000000..e82c4ab963
--- /dev/null
+++ b/plugins/catalog-react/src/components/EntityRefLink/EntityRefLink.stories.tsx
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2022 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 React, { ComponentType } from 'react';
+import { EntityRefLink, EntityRefLinkProps } from './EntityRefLink';
+import { wrapInTestApp } from '@backstage/test-utils';
+import { entityRouteRef } from '../../routes';
+
+const defaultArgs = {
+ entityRef: 'component:default/playback',
+};
+
+export default {
+ title: 'Catalog /EntityRefLink',
+ decorators: [
+ (Story: ComponentType<{}>) =>
+ wrapInTestApp(, {
+ mountedRoutes: {
+ '/catalog/:namespace/:kind/:name': entityRouteRef,
+ },
+ }),
+ ],
+};
+
+export const Default = (args: EntityRefLinkProps) => (
+
+);
+Default.args = defaultArgs;
diff --git a/plugins/catalog-react/src/components/EntityRefLink/EntityRefLinks.stories.tsx b/plugins/catalog-react/src/components/EntityRefLink/EntityRefLinks.stories.tsx
new file mode 100644
index 0000000000..176dd24530
--- /dev/null
+++ b/plugins/catalog-react/src/components/EntityRefLink/EntityRefLinks.stories.tsx
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2022 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 React, { ComponentType } from 'react';
+import { EntityRefLinks, EntityRefLinksProps } from './EntityRefLinks';
+import { wrapInTestApp } from '@backstage/test-utils';
+import { CompoundEntityRef } from '@backstage/catalog-model';
+import { entityRouteRef } from '../../routes';
+
+const defaultArgs = {
+ entityRefs: ['component:default/playback', 'user:default/fname.lname'],
+};
+
+export default {
+ title: 'Catalog /EntityRefLinks',
+ decorators: [
+ (Story: ComponentType<{}>) =>
+ wrapInTestApp(, {
+ mountedRoutes: {
+ '/catalog/:namespace/:kind/:name': entityRouteRef,
+ },
+ }),
+ ],
+};
+
+export const Default = (
+ args: EntityRefLinksProps,
+) => ;
+Default.args = defaultArgs;
diff --git a/plugins/catalog-react/src/components/index.ts b/plugins/catalog-react/src/components/index.ts
index c604306ead..a4380ddef0 100644
--- a/plugins/catalog-react/src/components/index.ts
+++ b/plugins/catalog-react/src/components/index.ts
@@ -19,6 +19,7 @@ export * from './EntityKindPicker';
export * from './EntityLifecyclePicker';
export * from './EntityOwnerPicker';
export * from './EntityRefLink';
+export * from './EntityPeekAheadPopover';
export * from './EntitySearchBar';
export * from './EntityTable';
export * from './EntityTagPicker';
diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json
index 62e897a42e..c01c706f67 100644
--- a/plugins/events-backend-module-aws-sqs/package.json
+++ b/plugins/events-backend-module-aws-sqs/package.json
@@ -24,6 +24,7 @@
},
"dependencies": {
"@aws-sdk/client-sqs": "^3.208.0",
+ "@backstage/backend-common": "workspace:^",
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/backend-tasks": "workspace:^",
"@backstage/config": "workspace:^",
diff --git a/plugins/events-backend-module-aws-sqs/src/service/AwsSqsConsumingEventPublisherEventsModule.ts b/plugins/events-backend-module-aws-sqs/src/service/AwsSqsConsumingEventPublisherEventsModule.ts
index a6c43d4046..50812f321b 100644
--- a/plugins/events-backend-module-aws-sqs/src/service/AwsSqsConsumingEventPublisherEventsModule.ts
+++ b/plugins/events-backend-module-aws-sqs/src/service/AwsSqsConsumingEventPublisherEventsModule.ts
@@ -17,8 +17,8 @@
import {
coreServices,
createBackendModule,
- loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
+import { loggerToWinstonLogger } from '@backstage/backend-common';
import { eventsExtensionPoint } from '@backstage/plugin-events-node';
import { AwsSqsConsumingEventPublisher } from '../publisher/AwsSqsConsumingEventPublisher';
diff --git a/plugins/events-backend/src/service/EventsPlugin.ts b/plugins/events-backend/src/service/EventsPlugin.ts
index 63d0d0b02a..29456d71f7 100644
--- a/plugins/events-backend/src/service/EventsPlugin.ts
+++ b/plugins/events-backend/src/service/EventsPlugin.ts
@@ -17,8 +17,8 @@
import {
createBackendPlugin,
coreServices,
- loggerToWinstonLogger,
} from '@backstage/backend-plugin-api';
+import { loggerToWinstonLogger } from '@backstage/backend-common';
import {
EventBroker,
EventPublisher,
diff --git a/plugins/git-release-manager/api-report.md b/plugins/git-release-manager/api-report.md
index d34b6c07fb..edc2e56ad9 100644
--- a/plugins/git-release-manager/api-report.md
+++ b/plugins/git-release-manager/api-report.md
@@ -12,23 +12,72 @@ import { default as React_2 } from 'react';
import { ReactNode } from 'react';
import { RouteRef } from '@backstage/core-plugin-api';
-// Warning: (ae-missing-release-tag) "A_CALVER_VERSION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "A_CALVER_VERSION" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const A_CALVER_VERSION = '2020.01.01_1';
-// Warning: (ae-missing-release-tag) "A_SEMVER_VERSION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "A_SEMVER_VERSION" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const A_SEMVER_VERSION = '1.2.3';
-// Warning: (ae-missing-release-tag) "calverRegexp" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "AlertError" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export interface AlertError {
+ // (undocumented)
+ subtitle: string;
+ // (undocumented)
+ title?: string;
+}
+
+// Warning: (ae-missing-release-tag) "calverRegexp" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const calverRegexp: RegExp;
+// Warning: (ae-missing-release-tag) "CalverTagParts" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+type CalverTagParts = {
+ prefix: string;
+ calver: string;
+ patch: number;
+};
+
+// Warning: (ae-missing-release-tag) "ComponentConfig" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export type ComponentConfig = {
+ omit?: boolean;
+ onSuccess?: (args: OnSuccessArgs) => Promise | void;
+};
+
+declare namespace components {
+ export {
+ Differ,
+ Divider,
+ InfoCardPlus,
+ LinearProgressWithLabel,
+ NoLatestRelease,
+ ResponseStepDialog,
+ ResponseStepList,
+ ResponseStepListItem,
+ };
+}
+
+declare namespace constants {
+ export {
+ SEMVER_PARTS,
+ DISABLE_CACHE,
+ VERSIONING_STRATEGIES,
+ TAG_OBJECT_MESSAGE,
+ };
+}
+
// Warning: (ae-forgotten-export) The symbol "GetBranchResult" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "createMockBranch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "createMockBranch" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
const createMockBranch: ({
@@ -36,7 +85,7 @@ const createMockBranch: ({
}?: Partial) => GetBranchResult['branch'];
// Warning: (ae-forgotten-export) The symbol "GetCommitResult" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "createMockCommit" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "createMockCommit" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const createMockCommit: (
@@ -44,7 +93,7 @@ const createMockCommit: (
) => GetCommitResult;
// Warning: (ae-forgotten-export) The symbol "GetRecentCommitsResultSingle" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "createMockRecentCommit" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "createMockRecentCommit" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
const createMockRecentCommit: ({
@@ -52,7 +101,7 @@ const createMockRecentCommit: ({
}: Partial) => GetRecentCommitsResultSingle;
// Warning: (ae-forgotten-export) The symbol "GetLatestReleaseResult" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "createMockRelease" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "createMockRelease" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public
const createMockRelease: ({
@@ -64,18 +113,38 @@ const createMockRelease: ({
>) => NonNullable;
// Warning: (ae-forgotten-export) The symbol "GetTagResult" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "createMockTag" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "createMockTag" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const createMockTag: (overrides: Partial) => GetTagResult;
+// Warning: (ae-missing-release-tag) "CreateRcOnSuccessArgs" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export interface CreateRcOnSuccessArgs {
+ // (undocumented)
+ comparisonUrl: string;
+ // (undocumented)
+ createdTag: string;
+ // (undocumented)
+ gitReleaseName: string | null;
+ // (undocumented)
+ gitReleaseUrl: string;
+ // Warning: (ae-forgotten-export) The symbol "UseCreateReleaseCandidate" needs to be exported by the entry point index.d.ts
+ //
+ // (undocumented)
+ input: Omit;
+ // (undocumented)
+ previousTag?: string;
+}
+
// Warning: (ae-forgotten-export) The symbol "DifferProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "Differ" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "Differ" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const Differ: ({ current, next, icon }: DifferProps) => JSX.Element;
-// Warning: (ae-missing-release-tag) "DISABLE_CACHE" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "DISABLE_CACHE" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const DISABLE_CACHE: {
@@ -84,7 +153,7 @@ const DISABLE_CACHE: {
};
};
-// Warning: (ae-missing-release-tag) "Divider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "Divider" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const Divider: () => JSX.Element;
@@ -129,7 +198,7 @@ function getBumpedTag(options: {
error: AlertError;
};
-// Warning: (ae-missing-release-tag) "getCalverTagParts" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "getCalverTagParts" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
function getCalverTagParts(tag: string):
@@ -142,7 +211,7 @@ function getCalverTagParts(tag: string):
error?: undefined;
};
-// Warning: (ae-missing-release-tag) "getSemverTagParts" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "getSemverTagParts" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
function getSemverTagParts(tag: string):
@@ -155,7 +224,7 @@ function getSemverTagParts(tag: string):
error?: undefined;
};
-// Warning: (ae-missing-release-tag) "getShortCommitHash" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "getShortCommitHash" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
function getShortCommitHash(hash: string): string;
@@ -176,18 +245,18 @@ function getTagParts(options: { project: Project; tag: string }):
};
// Warning: (ae-forgotten-export) The symbol "GitReleaseApi" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "gitReleaseManagerApiRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "gitReleaseManagerApiRef" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const gitReleaseManagerApiRef: ApiRef;
// Warning: (ae-forgotten-export) The symbol "GitReleaseManager" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "GitReleaseManagerPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "GitReleaseManagerPage" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const GitReleaseManagerPage: GitReleaseManager;
-// Warning: (ae-missing-release-tag) "gitReleaseManagerPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "gitReleaseManagerPlugin" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const gitReleaseManagerPlugin: BackstagePlugin<
@@ -198,20 +267,32 @@ export const gitReleaseManagerPlugin: BackstagePlugin<
{}
>;
+declare namespace helpers {
+ export {
+ calverRegexp,
+ getCalverTagParts,
+ CalverTagParts,
+ getBumpedSemverTagParts,
+ getBumpedTag,
+ getSemverTagParts,
+ semverRegexp,
+ getShortCommitHash,
+ getTagParts,
+ isCalverTagParts,
+ isProjectValid,
+ validateTagName,
+ };
+}
+
// @public (undocumented)
const InfoCardPlus: (props: { children?: React_2.ReactNode }) => JSX.Element;
-// Warning: (ae-missing-release-tag) "internals" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
-// @public (undocumented)
-export const internals: {
- components: typeof components;
- constants: typeof constants;
- helpers: typeof helpers;
- testHelpers: typeof testHelpers;
-};
+declare namespace internals {
+ export { components, constants, helpers, testHelpers };
+}
+export { internals };
-// Warning: (ae-missing-release-tag) "isCalverTagParts" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "isCalverTagParts" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
function isCalverTagParts(
@@ -219,12 +300,12 @@ function isCalverTagParts(
_tagParts: unknown,
): _tagParts is CalverTagParts;
-// Warning: (ae-missing-release-tag) "isProjectValid" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "isProjectValid" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
function isProjectValid(project: any): project is Project;
-// Warning: (ae-missing-release-tag) "LinearProgressWithLabel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "LinearProgressWithLabel" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
function LinearProgressWithLabel(props: {
@@ -232,88 +313,88 @@ function LinearProgressWithLabel(props: {
responseSteps: ResponseStep[];
}): JSX.Element;
-// Warning: (ae-missing-release-tag) "MOCK_RELEASE_BRANCH_NAME_CALVER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MOCK_RELEASE_BRANCH_NAME_CALVER" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const MOCK_RELEASE_BRANCH_NAME_CALVER: string;
-// Warning: (ae-missing-release-tag) "MOCK_RELEASE_BRANCH_NAME_SEMVER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MOCK_RELEASE_BRANCH_NAME_SEMVER" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const MOCK_RELEASE_BRANCH_NAME_SEMVER: string;
-// Warning: (ae-missing-release-tag) "MOCK_RELEASE_CANDIDATE_TAG_NAME_CALVER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MOCK_RELEASE_CANDIDATE_TAG_NAME_CALVER" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const MOCK_RELEASE_CANDIDATE_TAG_NAME_CALVER: string;
-// Warning: (ae-missing-release-tag) "MOCK_RELEASE_CANDIDATE_TAG_NAME_SEMVER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MOCK_RELEASE_CANDIDATE_TAG_NAME_SEMVER" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const MOCK_RELEASE_CANDIDATE_TAG_NAME_SEMVER: string;
-// Warning: (ae-missing-release-tag) "MOCK_RELEASE_NAME_CALVER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MOCK_RELEASE_NAME_CALVER" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const MOCK_RELEASE_NAME_CALVER: string;
-// Warning: (ae-missing-release-tag) "MOCK_RELEASE_NAME_SEMVER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MOCK_RELEASE_NAME_SEMVER" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const MOCK_RELEASE_NAME_SEMVER: string;
-// Warning: (ae-missing-release-tag) "MOCK_RELEASE_VERSION_TAG_NAME_CALVER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MOCK_RELEASE_VERSION_TAG_NAME_CALVER" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const MOCK_RELEASE_VERSION_TAG_NAME_CALVER: string;
-// Warning: (ae-missing-release-tag) "MOCK_RELEASE_VERSION_TAG_NAME_SEMVER" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "MOCK_RELEASE_VERSION_TAG_NAME_SEMVER" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const MOCK_RELEASE_VERSION_TAG_NAME_SEMVER: string;
-// Warning: (ae-missing-release-tag) "mockBumpedTag" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockBumpedTag" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockBumpedTag = 'rc-2020.01.01_1337';
-// Warning: (ae-missing-release-tag) "mockCalverProject" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockCalverProject" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockCalverProject: Project;
-// Warning: (ae-missing-release-tag) "mockCtaMessage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockCtaMessage" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockCtaMessage = 'Patch Release Candidate';
-// Warning: (ae-missing-release-tag) "mockDefaultBranch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockDefaultBranch" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockDefaultBranch = 'mock_defaultBranch';
-// Warning: (ae-missing-release-tag) "mockEmail" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockEmail" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockEmail = 'mock_email';
// Warning: (ae-forgotten-export) The symbol "getReleaseCandidateGitInfo" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "mockNextGitInfoCalver" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockNextGitInfoCalver" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockNextGitInfoCalver: ReturnType;
-// Warning: (ae-missing-release-tag) "mockNextGitInfoSemver" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockNextGitInfoSemver" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockNextGitInfoSemver: ReturnType;
-// Warning: (ae-missing-release-tag) "mockOwner" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockOwner" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockOwner = 'mock_owner';
-// Warning: (ae-missing-release-tag) "mockReleaseBranch" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockReleaseBranch" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockReleaseBranch: {
@@ -331,7 +412,7 @@ const mockReleaseBranch: {
};
};
-// Warning: (ae-missing-release-tag) "mockReleaseCandidateCalver" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockReleaseCandidateCalver" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockReleaseCandidateCalver: {
@@ -343,7 +424,7 @@ const mockReleaseCandidateCalver: {
body?: string | null | undefined;
};
-// Warning: (ae-missing-release-tag) "mockReleaseCandidateSemver" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockReleaseCandidateSemver" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockReleaseCandidateSemver: {
@@ -356,12 +437,12 @@ const mockReleaseCandidateSemver: {
};
// Warning: (ae-forgotten-export) The symbol "ReleaseStats" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "mockReleaseStats" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockReleaseStats" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockReleaseStats: ReleaseStats;
-// Warning: (ae-missing-release-tag) "mockReleaseVersionCalver" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockReleaseVersionCalver" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockReleaseVersionCalver: {
@@ -373,7 +454,7 @@ const mockReleaseVersionCalver: {
body?: string | null | undefined;
};
-// Warning: (ae-missing-release-tag) "mockReleaseVersionSemver" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockReleaseVersionSemver" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockReleaseVersionSemver: {
@@ -385,22 +466,22 @@ const mockReleaseVersionSemver: {
body?: string | null | undefined;
};
-// Warning: (ae-missing-release-tag) "mockRepo" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockRepo" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockRepo = 'mock_repo';
-// Warning: (ae-missing-release-tag) "mockSearchCalver" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockSearchCalver" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockSearchCalver: string;
-// Warning: (ae-missing-release-tag) "mockSearchSemver" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockSearchSemver" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockSearchSemver: string;
-// Warning: (ae-missing-release-tag) "mockSelectedPatchCommit" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockSelectedPatchCommit" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockSelectedPatchCommit: {
@@ -416,17 +497,17 @@ const mockSelectedPatchCommit: {
firstParentSha?: string | undefined;
};
-// Warning: (ae-missing-release-tag) "mockSemverProject" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockSemverProject" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockSemverProject: Project;
-// Warning: (ae-missing-release-tag) "mockTagParts" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockTagParts" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockTagParts: CalverTagParts;
-// Warning: (ae-missing-release-tag) "mockUser" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockUser" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockUser: {
@@ -434,18 +515,86 @@ const mockUser: {
email: string;
};
-// Warning: (ae-missing-release-tag) "mockUsername" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "mockUsername" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const mockUsername = 'mock_username';
-// Warning: (ae-missing-release-tag) "NoLatestRelease" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "NoLatestRelease" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const NoLatestRelease: () => JSX.Element;
+// Warning: (ae-missing-release-tag) "PatchOnSuccessArgs" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export interface PatchOnSuccessArgs {
+ // Warning: (ae-forgotten-export) The symbol "UsePatch" needs to be exported by the entry point index.d.ts
+ //
+ // (undocumented)
+ input: Omit;
+ // (undocumented)
+ patchCommitMessage: string;
+ // (undocumented)
+ patchCommitUrl: string;
+ // (undocumented)
+ patchedTag: string;
+ // (undocumented)
+ previousTag: string;
+ // (undocumented)
+ updatedReleaseName: string | null;
+ // (undocumented)
+ updatedReleaseUrl: string;
+}
+
+// Warning: (ae-missing-release-tag) "Project" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export interface Project {
+ isProvidedViaProps: boolean;
+ owner: string;
+ repo: string;
+ versioningStrategy: keyof typeof VERSIONING_STRATEGIES;
+}
+
+// Warning: (ae-missing-release-tag) "PromoteRcOnSuccessArgs" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export interface PromoteRcOnSuccessArgs {
+ // (undocumented)
+ gitReleaseName: string | null;
+ // (undocumented)
+ gitReleaseUrl: string;
+ // Warning: (ae-forgotten-export) The symbol "UsePromoteRc" needs to be exported by the entry point index.d.ts
+ //
+ // (undocumented)
+ input: Omit;
+ // (undocumented)
+ previousTag: string;
+ // (undocumented)
+ previousTagUrl: string;
+ // (undocumented)
+ updatedTag: string;
+ // (undocumented)
+ updatedTagUrl: string;
+}
+
+// Warning: (ae-missing-release-tag) "ResponseStep" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export interface ResponseStep {
+ // (undocumented)
+ icon?: 'success' | 'failure';
+ // (undocumented)
+ link?: string;
+ // (undocumented)
+ message: React.ReactNode;
+ // (undocumented)
+ secondaryMessage?: string | React.ReactNode;
+}
+
// Warning: (ae-forgotten-export) The symbol "DialogProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "ResponseStepDialog" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "ResponseStepDialog" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const ResponseStepDialog: ({
@@ -455,7 +604,7 @@ const ResponseStepDialog: ({
}: DialogProps) => JSX.Element;
// Warning: (ae-forgotten-export) The symbol "ResponseStepListProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "ResponseStepList" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "ResponseStepList" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const ResponseStepList: ({
@@ -467,7 +616,7 @@ const ResponseStepList: ({
}: PropsWithChildren) => JSX.Element;
// Warning: (ae-forgotten-export) The symbol "ResponseStepListItemProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "ResponseStepListItem" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "ResponseStepListItem" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const ResponseStepListItem: ({
@@ -475,7 +624,7 @@ const ResponseStepListItem: ({
animationDelay,
}: ResponseStepListItemProps) => JSX.Element;
-// Warning: (ae-missing-release-tag) "SEMVER_PARTS" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "SEMVER_PARTS" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const SEMVER_PARTS: {
@@ -484,7 +633,7 @@ const SEMVER_PARTS: {
patch: 'patch';
};
-// Warning: (ae-missing-release-tag) "semverRegexp" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "semverRegexp" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const semverRegexp: RegExp;
@@ -493,13 +642,13 @@ declare namespace stats {
export { mockReleaseStats };
}
-// Warning: (ae-missing-release-tag) "TAG_OBJECT_MESSAGE" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TAG_OBJECT_MESSAGE" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const TAG_OBJECT_MESSAGE =
'Tag generated by your friendly neighborhood Backstage Release Manager';
-// Warning: (ae-missing-release-tag) "TEST_IDS" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "TEST_IDS" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const TEST_IDS: {
@@ -565,6 +714,10 @@ const TEST_IDS: {
};
};
+declare namespace testHelpers {
+ export { stats, testHelpers_2 as testHelpers, testIds };
+}
+
declare namespace testHelpers_2 {
export {
mockUsername,
@@ -619,22 +772,11 @@ const validateTagName: (options: { project: Project; tagName?: string }) =>
tagNameError: AlertError | undefined;
};
-// Warning: (ae-missing-release-tag) "VERSIONING_STRATEGIES" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "VERSIONING_STRATEGIES" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const VERSIONING_STRATEGIES: {
semver: 'semver';
calver: 'calver';
};
-
-// Warnings were encountered during analysis:
-//
-// src/components/ResponseStepDialog/LinearProgressWithLabel.d.ts:5:5 - (ae-forgotten-export) The symbol "ResponseStep" needs to be exported by the entry point index.d.ts
-// src/helpers/getBumpedTag.d.ts:16:5 - (ae-forgotten-export) The symbol "Project" needs to be exported by the entry point index.d.ts
-// src/helpers/getBumpedTag.d.ts:21:5 - (ae-forgotten-export) The symbol "CalverTagParts" needs to be exported by the entry point index.d.ts
-// src/helpers/getBumpedTag.d.ts:33:5 - (ae-forgotten-export) The symbol "AlertError" needs to be exported by the entry point index.d.ts
-// src/index.d.ts:9:5 - (ae-forgotten-export) The symbol "components" needs to be exported by the entry point index.d.ts
-// src/index.d.ts:10:5 - (ae-forgotten-export) The symbol "constants" needs to be exported by the entry point index.d.ts
-// src/index.d.ts:11:5 - (ae-forgotten-export) The symbol "helpers" needs to be exported by the entry point index.d.ts
-// src/index.d.ts:12:5 - (ae-forgotten-export) The symbol "testHelpers" needs to be exported by the entry point index.d.ts
```
diff --git a/plugins/git-release-manager/src/helpers/index.tsx b/plugins/git-release-manager/src/helpers/index.tsx
index 1516e192a1..6589596114 100644
--- a/plugins/git-release-manager/src/helpers/index.tsx
+++ b/plugins/git-release-manager/src/helpers/index.tsx
@@ -15,6 +15,7 @@
*/
export { calverRegexp, getCalverTagParts } from './tagParts/getCalverTagParts';
+export type { CalverTagParts } from './tagParts/getCalverTagParts';
export { getBumpedSemverTagParts, getBumpedTag } from './getBumpedTag';
export { getSemverTagParts, semverRegexp } from './tagParts/getSemverTagParts';
export { getShortCommitHash } from './getShortCommitHash';
diff --git a/plugins/git-release-manager/src/index.ts b/plugins/git-release-manager/src/index.ts
index ac6b294cbc..e8fa661c21 100644
--- a/plugins/git-release-manager/src/index.ts
+++ b/plugins/git-release-manager/src/index.ts
@@ -26,11 +26,17 @@ export {
gitReleaseManagerApiRef,
} from './plugin';
-import { components, constants, helpers, testHelpers } from './plugin';
+import * as internals from './internals';
-export const internals = {
- components,
- constants,
- helpers,
- testHelpers,
-};
+export { internals };
+
+export type {
+ ComponentConfig,
+ CreateRcOnSuccessArgs,
+ PatchOnSuccessArgs,
+ PromoteRcOnSuccessArgs,
+ ResponseStep,
+ AlertError,
+} from './types/types';
+
+export type { Project } from './contexts/ProjectContext';
diff --git a/plugins/git-release-manager/src/internals.ts b/plugins/git-release-manager/src/internals.ts
new file mode 100644
index 0000000000..2cd7863bac
--- /dev/null
+++ b/plugins/git-release-manager/src/internals.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2023 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.
+ */
+export { components, constants, helpers, testHelpers } from './plugin';
diff --git a/plugins/jenkins/api-report.md b/plugins/jenkins/api-report.md
index 59e3dc636e..a2ae16988b 100644
--- a/plugins/jenkins/api-report.md
+++ b/plugins/jenkins/api-report.md
@@ -28,12 +28,12 @@ const isJenkinsAvailable: (entity: Entity) => boolean;
export { isJenkinsAvailable };
export { isJenkinsAvailable as isPluginApplicableToEntity };
-// Warning: (ae-missing-release-tag) "JENKINS_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "JENKINS_ANNOTATION" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const JENKINS_ANNOTATION = 'jenkins.io/job-full-name';
-// Warning: (ae-missing-release-tag) "JenkinsApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "JenkinsApi" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface JenkinsApi {
@@ -58,12 +58,12 @@ export interface JenkinsApi {
}): Promise;
}
-// Warning: (ae-missing-release-tag) "jenkinsApiRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "jenkinsApiRef" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const jenkinsApiRef: ApiRef;
-// Warning: (ae-missing-release-tag) "JenkinsClient" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "JenkinsClient" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export class JenkinsClient implements JenkinsApi {
@@ -103,7 +103,7 @@ const jenkinsPlugin: BackstagePlugin<
export { jenkinsPlugin };
export { jenkinsPlugin as plugin };
-// Warning: (ae-missing-release-tag) "LatestRunCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "LatestRunCard" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const LatestRunCard: (props: {
@@ -111,12 +111,12 @@ export const LatestRunCard: (props: {
variant?: InfoCardVariants;
}) => JSX.Element;
-// Warning: (ae-missing-release-tag) "LEGACY_JENKINS_ANNOTATION" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "LEGACY_JENKINS_ANNOTATION" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const LEGACY_JENKINS_ANNOTATION = 'jenkins.io/github-folder';
-// Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "Router" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const Router: () => JSX.Element;
diff --git a/plugins/kubernetes/api-report.md b/plugins/kubernetes/api-report.md
index 3e1b2f0198..463b4126eb 100644
--- a/plugins/kubernetes/api-report.md
+++ b/plugins/kubernetes/api-report.md
@@ -36,7 +36,7 @@ import { V1StatefulSet } from '@kubernetes/client-node';
import { WorkloadsByEntityRequest } from '@backstage/plugin-kubernetes-common';
// Warning: (ae-forgotten-export) The symbol "ClusterProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "Cluster" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "Cluster" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const Cluster: ({
@@ -44,19 +44,19 @@ export const Cluster: ({
podsWithErrors,
}: ClusterProps) => JSX.Element;
-// Warning: (ae-missing-release-tag) "ClusterContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "ClusterContext" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const ClusterContext: React_2.Context;
-// Warning: (ae-missing-release-tag) "ClusterLinksFormatter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "ClusterLinksFormatter" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export type ClusterLinksFormatter = (
options: ClusterLinksFormatterOptions,
) => URL;
-// Warning: (ae-missing-release-tag) "ClusterLinksFormatterOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "ClusterLinksFormatterOptions" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface ClusterLinksFormatterOptions {
@@ -70,24 +70,24 @@ export interface ClusterLinksFormatterOptions {
object: any;
}
-// Warning: (ae-missing-release-tag) "clusterLinksFormatters" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "clusterLinksFormatters" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const clusterLinksFormatters: Record;
// Warning: (ae-forgotten-export) The symbol "CronJobsAccordionsProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "CronJobsAccordions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "CronJobsAccordions" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const CronJobsAccordions: ({}: CronJobsAccordionsProps) => JSX.Element;
// Warning: (ae-forgotten-export) The symbol "CustomResourcesProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "CustomResources" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "CustomResources" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const CustomResources: ({}: CustomResourcesProps) => JSX.Element;
-// Warning: (ae-missing-release-tag) "DeploymentResources" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "DeploymentResources" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface DeploymentResources {
@@ -125,7 +125,7 @@ export const detectErrors: (
objects: ObjectsByEntityResponse,
) => DetectedErrorsByCluster;
-// Warning: (ae-missing-release-tag) "EntityKubernetesContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "EntityKubernetesContent" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const EntityKubernetesContent: (
@@ -144,7 +144,7 @@ export type ErrorDetectableKind =
| 'HorizontalPodAutoscaler';
// Warning: (ae-forgotten-export) The symbol "ErrorPanelProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "ErrorPanel" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "ErrorPanel" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const ErrorPanel: ({
@@ -154,7 +154,7 @@ export const ErrorPanel: ({
}: ErrorPanelProps) => JSX.Element;
// Warning: (ae-forgotten-export) The symbol "ErrorReportingProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "ErrorReporting" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "ErrorReporting" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const ErrorReporting: ({
@@ -165,7 +165,7 @@ export const ErrorReporting: ({
export type ErrorSeverity = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
// Warning: (ae-forgotten-export) The symbol "FormatClusterLinkOptions" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "formatClusterLink" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "formatClusterLink" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function formatClusterLink(
@@ -173,7 +173,7 @@ export function formatClusterLink(
): string | undefined;
// Warning: (ae-forgotten-export) The symbol "KubernetesAuthProvider" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "GoogleKubernetesAuthProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "GoogleKubernetesAuthProvider" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export class GoogleKubernetesAuthProvider implements KubernetesAuthProvider {
@@ -186,7 +186,7 @@ export class GoogleKubernetesAuthProvider implements KubernetesAuthProvider {
): Promise;
}
-// Warning: (ae-missing-release-tag) "GroupedResponses" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "GroupedResponses" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface GroupedResponses extends DeploymentResources {
@@ -206,7 +206,7 @@ export interface GroupedResponses extends DeploymentResources {
statefulsets: V1StatefulSet[];
}
-// Warning: (ae-missing-release-tag) "GroupedResponsesContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "GroupedResponsesContext" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const GroupedResponsesContext: React_2.Context;
@@ -219,23 +219,23 @@ export const HorizontalPodAutoscalerDrawer: (props: {
}) => JSX.Element;
// Warning: (ae-forgotten-export) The symbol "IngressesAccordionsProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "IngressesAccordions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "IngressesAccordions" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const IngressesAccordions: ({}: IngressesAccordionsProps) => JSX.Element;
-// Warning: (ae-missing-release-tag) "isKubernetesAvailable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "isKubernetesAvailable" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const isKubernetesAvailable: (entity: Entity) => boolean;
// Warning: (ae-forgotten-export) The symbol "JobsAccordionsProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "JobsAccordions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "JobsAccordions" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const JobsAccordions: ({ jobs }: JobsAccordionsProps) => JSX.Element;
-// Warning: (ae-missing-release-tag) "KubernetesApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "KubernetesApi" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface KubernetesApi {
@@ -261,12 +261,12 @@ export interface KubernetesApi {
): Promise;
}
-// Warning: (ae-missing-release-tag) "kubernetesApiRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "kubernetesApiRef" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const kubernetesApiRef: ApiRef;
-// Warning: (ae-missing-release-tag) "KubernetesAuthProviders" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "KubernetesAuthProviders" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export class KubernetesAuthProviders implements KubernetesAuthProvidersApi {
@@ -283,7 +283,7 @@ export class KubernetesAuthProviders implements KubernetesAuthProvidersApi {
): Promise;
}
-// Warning: (ae-missing-release-tag) "KubernetesAuthProvidersApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "KubernetesAuthProvidersApi" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface KubernetesAuthProvidersApi {
@@ -294,12 +294,12 @@ export interface KubernetesAuthProvidersApi {
): Promise;
}
-// Warning: (ae-missing-release-tag) "kubernetesAuthProvidersApiRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "kubernetesAuthProvidersApiRef" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const kubernetesAuthProvidersApiRef: ApiRef;
-// Warning: (ae-missing-release-tag) "KubernetesBackendClient" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "KubernetesBackendClient" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export class KubernetesBackendClient implements KubernetesApi {
@@ -329,7 +329,7 @@ export class KubernetesBackendClient implements KubernetesApi {
}
// Warning: (ae-forgotten-export) The symbol "KubernetesContentProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "KubernetesContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "KubernetesContent" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const KubernetesContent: ({
@@ -339,7 +339,7 @@ export const KubernetesContent: ({
// Warning: (ae-forgotten-export) The symbol "KubernetesDrawerable" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "KubernetesDrawerProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "KubernetesDrawer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "KubernetesDrawer" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const KubernetesDrawer: ({
@@ -351,7 +351,7 @@ export const KubernetesDrawer: ({
children,
}: KubernetesDrawerProps) => JSX.Element;
-// Warning: (ae-missing-release-tag) "KubernetesObjects" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "KubernetesObjects" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface KubernetesObjects {
@@ -363,7 +363,7 @@ export interface KubernetesObjects {
loading: boolean;
}
-// Warning: (ae-missing-release-tag) "kubernetesPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "kubernetesPlugin" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
const kubernetesPlugin: BackstagePlugin<
@@ -382,12 +382,12 @@ export const PodDrawer: (props: {
expanded?: boolean;
}) => JSX.Element;
-// Warning: (ae-missing-release-tag) "PodNamesWithErrorsContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "PodNamesWithErrorsContext" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const PodNamesWithErrorsContext: React_2.Context>;
-// Warning: (ae-missing-release-tag) "PodNamesWithMetricsContext" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "PodNamesWithMetricsContext" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const PodNamesWithMetricsContext: React_2.Context<
@@ -395,7 +395,7 @@ export const PodNamesWithMetricsContext: React_2.Context<
>;
// Warning: (ae-forgotten-export) The symbol "PodsTablesProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "PodsTable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "PodsTable" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const PodsTable: ({
@@ -403,7 +403,7 @@ export const PodsTable: ({
extraColumns,
}: PodsTablesProps) => JSX.Element;
-// Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "Router" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const Router: (props: { refreshIntervalMs?: number }) => JSX.Element;
@@ -419,7 +419,7 @@ export class ServerSideKubernetesAuthProvider
}
// Warning: (ae-forgotten-export) The symbol "ServicesAccordionsProps" needs to be exported by the entry point index.d.ts
-// Warning: (ae-missing-release-tag) "ServicesAccordions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "ServicesAccordions" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const ServicesAccordions: ({}: ServicesAccordionsProps) => JSX.Element;
@@ -431,7 +431,7 @@ export const useCustomResources: (
intervalMs?: number,
) => KubernetesObjects;
-// Warning: (ae-missing-release-tag) "useKubernetesObjects" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+// Warning: (ae-missing-release-tag) "useKubernetesObjects" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const useKubernetesObjects: (
diff --git a/plugins/lighthouse/src/components/AuditView/index.test.tsx b/plugins/lighthouse/src/components/AuditView/index.test.tsx
index c68daddc67..d555133f3e 100644
--- a/plugins/lighthouse/src/components/AuditView/index.test.tsx
+++ b/plugins/lighthouse/src/components/AuditView/index.test.tsx
@@ -16,6 +16,8 @@
/* eslint-disable jest/no-disabled-tests */
+import { configApiRef } from '@backstage/core-plugin-api';
+
jest.mock('react-router-dom', () => {
const actual = jest.requireActual('react-router-dom');
const mockNavigation = jest.fn();
@@ -28,6 +30,7 @@ jest.mock('react-router-dom', () => {
import {
setupRequestMockHandlers,
+ TestApiProvider,
TestApiRegistry,
wrapInTestApp,
} from '@backstage/test-utils';
@@ -39,13 +42,18 @@ import { Audit, lighthouseApiRef, LighthouseRestApi, Website } from '../../api';
import { formatTime } from '../../utils';
import * as data from '../../__fixtures__/website-response.json';
import AuditView from './index';
-import { ApiProvider } from '@backstage/core-app-api';
+import { ApiProvider, ConfigReader } from '@backstage/core-app-api';
+import { rootRouteRef } from '../../plugin';
const { useParams }: { useParams: jest.Mock } =
jest.requireMock('react-router-dom');
const websiteResponse = data as Website;
describe('AuditView', () => {
+ const lighthouseRestApiMock = new LighthouseRestApi('https://lighthouse');
+ const testAppOptions = {
+ mountedRoutes: { '/': rootRouteRef },
+ };
let apis: TestApiRegistry;
let id: string;
@@ -59,10 +67,7 @@ describe('AuditView', () => {
),
);
- apis = TestApiRegistry.from([
- lighthouseApiRef,
- new LighthouseRestApi('https://lighthouse'),
- ]);
+ apis = TestApiRegistry.from([lighthouseApiRef, lighthouseRestApiMock]);
id = websiteResponse.audits.find(a => a.status === 'COMPLETED')
?.id as string;
useParams.mockReturnValue({ id });
@@ -74,6 +79,7 @@ describe('AuditView', () => {
,
+ testAppOptions,
),
);
@@ -91,6 +97,7 @@ describe('AuditView', () => {
,
+ testAppOptions,
),
);
@@ -109,6 +116,7 @@ describe('AuditView', () => {
,
+ testAppOptions,
),
);
@@ -137,6 +145,7 @@ describe('AuditView', () => {
,
+ testAppOptions,
),
);
@@ -149,6 +158,36 @@ describe('AuditView', () => {
).toHaveAttribute('href', `/audit/${a.id}`);
});
});
+
+ it('navigates to the next report with respect to the base path', async () => {
+ const configApiMock = new ConfigReader({
+ app: { baseUrl: `http://localhost:3000/example` },
+ });
+ const rendered = render(
+ wrapInTestApp(
+
+
+ ,
+ {
+ mountedRoutes: { [`/example/lighthouse`]: rootRouteRef },
+ },
+ ),
+ );
+
+ await rendered.findByTestId('audit-sidebar');
+
+ websiteResponse.audits.forEach(a => {
+ expect(
+ rendered.getByText(formatTime(a.timeCreated)).parentElement
+ ?.parentElement,
+ ).toHaveAttribute('href', `/example/lighthouse/audit/${a.id}`);
+ });
+ });
});
describe('when the request for the website by id is pending', () => {
@@ -159,6 +198,7 @@ describe('AuditView', () => {
,
+ testAppOptions,
),
);
expect(await rendered.findByTestId('progress')).toBeInTheDocument();
@@ -177,6 +217,7 @@ describe('AuditView', () => {
,
+ testAppOptions,
),
);
expect(await rendered.findByText(/failed to fetch/)).toBeInTheDocument();
@@ -194,6 +235,7 @@ describe('AuditView', () => {
,
+ testAppOptions,
),
);
@@ -214,6 +256,7 @@ describe('AuditView', () => {
,
+ testAppOptions,
),
);
diff --git a/plugins/lighthouse/src/components/AuditView/index.tsx b/plugins/lighthouse/src/components/AuditView/index.tsx
index e377894c90..ade485b09a 100644
--- a/plugins/lighthouse/src/components/AuditView/index.tsx
+++ b/plugins/lighthouse/src/components/AuditView/index.tsx
@@ -47,7 +47,8 @@ import {
Page,
Progress,
} from '@backstage/core-components';
-import { useApi } from '@backstage/core-plugin-api';
+import { useApi, useRouteRef } from '@backstage/core-plugin-api';
+import { rootRouteRef } from '../../plugin';
// TODO(freben): move all of this out of index
@@ -67,29 +68,35 @@ interface AuditLinkListProps {
audits?: Audit[];
selectedId: string;
}
-const AuditLinkList = ({ audits = [], selectedId }: AuditLinkListProps) => (
-
- {audits.map(audit => (
-
-
-
-
-
-
- ))}
-
-);
+const AuditLinkList = ({ audits = [], selectedId }: AuditLinkListProps) => {
+ const fromPath = useRouteRef(rootRouteRef)?.() ?? '../';
+ return (
+
+ {audits.map(audit => (
+
+
+
+
+
+
+ ))}
+
+ );
+};
const AuditView = ({ audit }: { audit?: Audit }) => {
const classes = useStyles();
@@ -119,6 +126,7 @@ const AuditView = ({ audit }: { audit?: Audit }) => {
export const AuditViewContent = () => {
const lighthouseApi = useApi(lighthouseApiRef);
+ const fromPath = useRouteRef(rootRouteRef)?.() ?? '../';
const params = useParams() as { id: string };
const classes = useStyles();
const navigate = useNavigate();
@@ -178,7 +186,7 @@ export const AuditViewContent = () => {
diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json
index 7801bcbbba..ca23474ba3 100644
--- a/plugins/permission-react/package.json
+++ b/plugins/permission-react/package.json
@@ -36,7 +36,7 @@
"@backstage/plugin-permission-common": "workspace:^",
"cross-fetch": "^3.1.5",
"react-use": "^17.2.4",
- "swr": "^1.1.2"
+ "swr": "^2.0.0"
},
"peerDependencies": {
"@types/react": "^16.13.1 || ^17.0.0",
diff --git a/plugins/permission-react/src/hooks/usePermission.test.tsx b/plugins/permission-react/src/hooks/usePermission.test.tsx
index cbf3b22ae7..1987382f47 100644
--- a/plugins/permission-react/src/hooks/usePermission.test.tsx
+++ b/plugins/permission-react/src/hooks/usePermission.test.tsx
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-import React, { FC } from 'react';
+import React from 'react';
import { render } from '@testing-library/react';
import { usePermission } from './usePermission';
import {
@@ -30,7 +30,7 @@ const permission = createPermission({
attributes: { action: 'read' },
});
-const TestComponent: FC = () => {
+const TestComponent = () => {
const { loading, allowed, error } = usePermission({ permission });
return (