diff --git a/.changeset/angry-eagles-end.md b/.changeset/angry-eagles-end.md new file mode 100644 index 0000000000..eec1e7b710 --- /dev/null +++ b/.changeset/angry-eagles-end.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-test-utils': patch +--- + +Added `createExtensionTester` for rendering extensions in tests. diff --git a/.changeset/angry-gorillas-unite.md b/.changeset/angry-gorillas-unite.md new file mode 100644 index 0000000000..73d5a6c88b --- /dev/null +++ b/.changeset/angry-gorillas-unite.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-atlassian-provider': minor +--- + +New module for `@backstage/plugin-auth-backend` that adds an atlassian auth provider diff --git a/.changeset/big-swans-guess.md b/.changeset/big-swans-guess.md new file mode 100644 index 0000000000..c2ea795b21 --- /dev/null +++ b/.changeset/big-swans-guess.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-backstage-openapi': patch +--- + +Support authenticated backends diff --git a/.changeset/blue-meals-chew.md b/.changeset/blue-meals-chew.md new file mode 100644 index 0000000000..479e77a982 --- /dev/null +++ b/.changeset/blue-meals-chew.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +`oauth2-proxy` auth implementation has been moved to `@backstage/plugin-auth-backend-module-oauth2-proxy-provider` diff --git a/.changeset/brave-beers-happen.md b/.changeset/brave-beers-happen.md new file mode 100644 index 0000000000..34bbb95666 --- /dev/null +++ b/.changeset/brave-beers-happen.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +Update alpha component ref type to be more specific than any, delete boot page component and use new plugin type for error boundary component extensions. diff --git a/.changeset/brave-parents-stare.md b/.changeset/brave-parents-stare.md new file mode 100644 index 0000000000..bb98799456 --- /dev/null +++ b/.changeset/brave-parents-stare.md @@ -0,0 +1,6 @@ +--- +'@backstage/frontend-plugin-api': patch +'@backstage/frontend-app-api': patch +--- + +Added the nav logo extension for customization of sidebar logo diff --git a/.changeset/brave-socks-raise.md b/.changeset/brave-socks-raise.md new file mode 100644 index 0000000000..e8df72f4f5 --- /dev/null +++ b/.changeset/brave-socks-raise.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-addons-test-utils': patch +--- + +Move `@testing-library/react` to be a `peerDependency` diff --git a/.changeset/breezy-houses-eat.md b/.changeset/breezy-houses-eat.md new file mode 100644 index 0000000000..184f7ecf45 --- /dev/null +++ b/.changeset/breezy-houses-eat.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Add support for translation extensions. diff --git a/.changeset/breezy-pans-glow.md b/.changeset/breezy-pans-glow.md new file mode 100644 index 0000000000..026465aef7 --- /dev/null +++ b/.changeset/breezy-pans-glow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Added pagination support to `EntityListProvider`. diff --git a/.changeset/bright-eyes-film.md b/.changeset/bright-eyes-film.md new file mode 100644 index 0000000000..503079ad00 --- /dev/null +++ b/.changeset/bright-eyes-film.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-test-utils': minor +--- + +New testing utility library for `@backstage/frontend-app-api` and `@backstage/frontend-plugin-api`. diff --git a/.changeset/brown-books-carry.md b/.changeset/brown-books-carry.md new file mode 100644 index 0000000000..1299354445 --- /dev/null +++ b/.changeset/brown-books-carry.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Create a core components extension that allows adopters to override core app components such as `Progress`, `BootErrorPage`, `NotFoundErrorPage` and `ErrorBoundaryFallback`. diff --git a/.changeset/chatty-actors-live.md b/.changeset/chatty-actors-live.md new file mode 100644 index 0000000000..dcf308edec --- /dev/null +++ b/.changeset/chatty-actors-live.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +Add dependency on `graphql-config` to compensate for `graphql-language-service` needing it but not shipping the dep properly diff --git a/.changeset/chilled-buses-love.md b/.changeset/chilled-buses-love.md new file mode 100644 index 0000000000..6c67d3cc63 --- /dev/null +++ b/.changeset/chilled-buses-love.md @@ -0,0 +1,5 @@ +--- +'@backstage/eslint-plugin': patch +--- + +The `no-undeclared-imports` rule will now prefer using version queries that already exist en the repo for the same dependency type when installing new packages. diff --git a/.changeset/chilly-bikes-kick.md b/.changeset/chilly-bikes-kick.md new file mode 100644 index 0000000000..f5eb5380d3 --- /dev/null +++ b/.changeset/chilly-bikes-kick.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Added a new `/testUtils` sub-path that initially exports a `mockBreakpoint` helper. diff --git a/.changeset/chilly-lies-collect.md b/.changeset/chilly-lies-collect.md new file mode 100644 index 0000000000..c84e6cebd4 --- /dev/null +++ b/.changeset/chilly-lies-collect.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-oauth2-proxy-provider': patch +--- + +Exported the provider as default so it gets discovered when using `featureDiscoveryServiceFactory()` diff --git a/.changeset/clean-clouds-fry.md b/.changeset/clean-clouds-fry.md new file mode 100644 index 0000000000..77b1c97131 --- /dev/null +++ b/.changeset/clean-clouds-fry.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Enable the `tsx` loader to work on Node 18.19 and up diff --git a/.changeset/clever-wombats-sneeze.md b/.changeset/clever-wombats-sneeze.md new file mode 100644 index 0000000000..ffd94aa9f0 --- /dev/null +++ b/.changeset/clever-wombats-sneeze.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +Create factories for overriding default core components extensions. diff --git a/.changeset/cold-pans-crash.md b/.changeset/cold-pans-crash.md new file mode 100644 index 0000000000..85858fd270 --- /dev/null +++ b/.changeset/cold-pans-crash.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Migrate the atlassian auth provider to be implemented using the new `@backstage/plugin-auth-backend-module-atlassian-provider` module diff --git a/.changeset/cool-knives-argue.md b/.changeset/cool-knives-argue.md new file mode 100644 index 0000000000..74890a0a9b --- /dev/null +++ b/.changeset/cool-knives-argue.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-oauth2-proxy-provider': minor +--- + +Release of `oauth2-proxy-provider` plugin diff --git a/.changeset/create-app-1700579510.md b/.changeset/create-app-1700579510.md new file mode 100644 index 0000000000..b50d431d4b --- /dev/null +++ b/.changeset/create-app-1700579510.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Bumped create-app version. diff --git a/.changeset/create-app-1700607979.md b/.changeset/create-app-1700607979.md new file mode 100644 index 0000000000..b50d431d4b --- /dev/null +++ b/.changeset/create-app-1700607979.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Bumped create-app version. diff --git a/.changeset/curly-walls-relate.md b/.changeset/curly-walls-relate.md new file mode 100644 index 0000000000..40cacca907 --- /dev/null +++ b/.changeset/curly-walls-relate.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Add missing export for IconLinkVertical diff --git a/.changeset/dirty-turkeys-reflect.md b/.changeset/dirty-turkeys-reflect.md new file mode 100644 index 0000000000..eac601f75c --- /dev/null +++ b/.changeset/dirty-turkeys-reflect.md @@ -0,0 +1,5 @@ +--- +'@backstage/theme': patch +--- + +Align Material UI v5 `Paper` component background color in dark mode to v4. diff --git a/.changeset/dry-readers-raise.md b/.changeset/dry-readers-raise.md new file mode 100644 index 0000000000..c13e830062 --- /dev/null +++ b/.changeset/dry-readers-raise.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Added `headerOptions` to `TemplateListPage` to optionally override default values. +Changed `themeId` of TemplateListPage from `website` to `home`. diff --git a/.changeset/eighty-dodos-sing.md b/.changeset/eighty-dodos-sing.md new file mode 100644 index 0000000000..b7af0da473 --- /dev/null +++ b/.changeset/eighty-dodos-sing.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-node': minor +--- + +Added `EntitiesSearchFilter` and `EntityFilter` from `@backstage/plugin-catalog-backend`, for reuse diff --git a/.changeset/eighty-phones-peel.md b/.changeset/eighty-phones-peel.md new file mode 100644 index 0000000000..954553427a --- /dev/null +++ b/.changeset/eighty-phones-peel.md @@ -0,0 +1,5 @@ +--- +'@backstage/config-loader': minor +--- + +Add "path" to `TransformFunc` context diff --git a/.changeset/eleven-ants-pretend.md b/.changeset/eleven-ants-pretend.md new file mode 100644 index 0000000000..6b188117ba --- /dev/null +++ b/.changeset/eleven-ants-pretend.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Minor improvements to `Table` component. diff --git a/.changeset/empty-dingos-grow.md b/.changeset/empty-dingos-grow.md new file mode 100644 index 0000000000..8a43cd210f --- /dev/null +++ b/.changeset/empty-dingos-grow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Fix copy entity url function in http contexts. diff --git a/.changeset/empty-fireants-study.md b/.changeset/empty-fireants-study.md new file mode 100644 index 0000000000..4f5508ac9b --- /dev/null +++ b/.changeset/empty-fireants-study.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-vmware-cloud-provider': minor +--- + +Add VMware Cloud auth backend module provider diff --git a/.changeset/fair-plants-attack.md b/.changeset/fair-plants-attack.md new file mode 100644 index 0000000000..2e36ba6284 --- /dev/null +++ b/.changeset/fair-plants-attack.md @@ -0,0 +1,9 @@ +--- +'@backstage/plugin-kubernetes-react': minor +'@backstage/plugin-kubernetes': patch +--- + +Change `formatClusterLink` to be an API and make it async for further customization possibilities. + +**BREAKING** +If you have a custom k8s page and used `formatClusterLink` directly, you need to migrate to new `kubernetesClusterLinkFormatterApiRef` diff --git a/.changeset/famous-flies-kick.md b/.changeset/famous-flies-kick.md new file mode 100644 index 0000000000..abbd18f9c3 --- /dev/null +++ b/.changeset/famous-flies-kick.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-plugin-api': patch +--- + +The `createTranslationRef` function from the `/alpha` subpath can now also accept a nested object structure of default translation messages, which will be flatted using `.` separators. diff --git a/.changeset/famous-peas-reflect.md b/.changeset/famous-peas-reflect.md new file mode 100644 index 0000000000..c8aed3c16b --- /dev/null +++ b/.changeset/famous-peas-reflect.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Toned down the warning message when git is not found diff --git a/.changeset/fifty-cameras-share.md b/.changeset/fifty-cameras-share.md new file mode 100644 index 0000000000..8aa103b218 --- /dev/null +++ b/.changeset/fifty-cameras-share.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-catalog-react': patch +'@backstage/plugin-catalog': patch +--- + +Ensure that passed-in icons are taken advantage of in the presentation API diff --git a/.changeset/fifty-seas-grab.md b/.changeset/fifty-seas-grab.md new file mode 100644 index 0000000000..587ac5606d --- /dev/null +++ b/.changeset/fifty-seas-grab.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': minor +--- + +Updated core extension structure to make space for the sign-in page by adding `core.router`. diff --git a/.changeset/five-feet-call.md b/.changeset/five-feet-call.md new file mode 100644 index 0000000000..528c21a932 --- /dev/null +++ b/.changeset/five-feet-call.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Update the OpenAPI spec to support the use of `openapi-generator`. diff --git a/.changeset/forty-clocks-hug.md b/.changeset/forty-clocks-hug.md new file mode 100644 index 0000000000..ea0fd2480f --- /dev/null +++ b/.changeset/forty-clocks-hug.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-client': minor +--- + +The internals of `CatalogClient` are now auto-generated using the `backstage-repo-tools schema openapi generate-client` command. diff --git a/.changeset/forty-insects-drop.md b/.changeset/forty-insects-drop.md new file mode 100644 index 0000000000..e2a94662ed --- /dev/null +++ b/.changeset/forty-insects-drop.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-test-utils': patch +--- + +Updates for compatibility with the new extension IDs. diff --git a/.changeset/forty-mirrors-carry.md b/.changeset/forty-mirrors-carry.md new file mode 100644 index 0000000000..d31d635329 --- /dev/null +++ b/.changeset/forty-mirrors-carry.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-test-utils': patch +--- + +Migrate `renderInTestApp` to `@backstage/frontend-test-utils` for testing individual React components in an app. diff --git a/.changeset/four-foxes-juggle.md b/.changeset/four-foxes-juggle.md new file mode 100644 index 0000000000..13cd5f0937 --- /dev/null +++ b/.changeset/four-foxes-juggle.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': patch +--- + +Includes templates in @backstage/repo-tools package and use them in the CLI diff --git a/.changeset/four-needles-watch.md b/.changeset/four-needles-watch.md new file mode 100644 index 0000000000..9c74bce5ad --- /dev/null +++ b/.changeset/four-needles-watch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-bazaar': patch +--- + +Internalize 'AboutField' to break catalog dependency diff --git a/.changeset/funny-bobcats-try.md b/.changeset/funny-bobcats-try.md new file mode 100644 index 0000000000..c8dd2384a6 --- /dev/null +++ b/.changeset/funny-bobcats-try.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +Fixed bug in `ReviewState` where `enum` value was displayed in step review instead of the corresponding label when using `enumNames` diff --git a/.changeset/gentle-timers-fail.md b/.changeset/gentle-timers-fail.md new file mode 100644 index 0000000000..3ac6e207a8 --- /dev/null +++ b/.changeset/gentle-timers-fail.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': patch +--- + +Updates the `schema openapi generate-client` command to export all generated types from the generated directory. diff --git a/.changeset/giant-files-fry.md b/.changeset/giant-files-fry.md new file mode 100644 index 0000000000..b01cfbc980 --- /dev/null +++ b/.changeset/giant-files-fry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-addons-test-utils': patch +--- + +Remove unnecessary catalog dependency diff --git a/.changeset/gold-humans-tease.md b/.changeset/gold-humans-tease.md new file mode 100644 index 0000000000..b3b40d0a7f --- /dev/null +++ b/.changeset/gold-humans-tease.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +Add feature flags to plugins and extension overrides. diff --git a/.changeset/gold-shirts-yell.md b/.changeset/gold-shirts-yell.md new file mode 100644 index 0000000000..ac03ce3362 --- /dev/null +++ b/.changeset/gold-shirts-yell.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-org': patch +--- + +Support member list scrollable when parent has specified height diff --git a/.changeset/good-wolves-leave.md b/.changeset/good-wolves-leave.md new file mode 100644 index 0000000000..51ac99a55a --- /dev/null +++ b/.changeset/good-wolves-leave.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Use the new plugin type for error boundary components. diff --git a/.changeset/gorgeous-snails-admire.md b/.changeset/gorgeous-snails-admire.md new file mode 100644 index 0000000000..45875ed366 --- /dev/null +++ b/.changeset/gorgeous-snails-admire.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': minor +--- + +**BREAKING**: API Reports generated for sub-path exports now place the name as a suffix rather than prefix, for example `api-report-alpha.md` instead of `alpha-api-report.md`. When upgrading to this version you'll need to re-create any such API reports and delete the old ones. diff --git a/.changeset/great-rings-type.md b/.changeset/great-rings-type.md new file mode 100644 index 0000000000..0b10c51651 --- /dev/null +++ b/.changeset/great-rings-type.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Use `Readable.from` to fix some of the stream issues diff --git a/.changeset/green-seals-play.md b/.changeset/green-seals-play.md new file mode 100644 index 0000000000..5c5a31afcd --- /dev/null +++ b/.changeset/green-seals-play.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Collect and register feature flags from plugins and extension overrides. diff --git a/.changeset/healthy-feet-kick.md b/.changeset/healthy-feet-kick.md new file mode 100644 index 0000000000..732f2164c3 --- /dev/null +++ b/.changeset/healthy-feet-kick.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-home': minor +--- + +Added view of entities grouped by kind to make it easier to distinguish entities with different kind but same name diff --git a/.changeset/healthy-poets-search.md b/.changeset/healthy-poets-search.md new file mode 100644 index 0000000000..dfd223b379 --- /dev/null +++ b/.changeset/healthy-poets-search.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Add default icon for kind resource. diff --git a/.changeset/hip-berries-begin.md b/.changeset/hip-berries-begin.md new file mode 100644 index 0000000000..43d176cbcf --- /dev/null +++ b/.changeset/hip-berries-begin.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-test-utils': patch +--- + +Updates for `core.router` addition. diff --git a/.changeset/hip-cars-repair.md b/.changeset/hip-cars-repair.md new file mode 100644 index 0000000000..de46860b03 --- /dev/null +++ b/.changeset/hip-cars-repair.md @@ -0,0 +1,11 @@ +--- +'@backstage/repo-tools': patch +--- + +The `api-reports` command now checks for api report files that no longer apply. +If it finds such files, it's treated basically the same as report errors do, and +the check fails. + +For example, if you had an `api-report-alpha.md` but then removed the alpha +export, the reports generator would now report that this file needs to be +deleted. diff --git a/.changeset/honest-houses-hide.md b/.changeset/honest-houses-hide.md new file mode 100644 index 0000000000..7f2508184f --- /dev/null +++ b/.changeset/honest-houses-hide.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Added a warning when starting a standalone backend plugin that hasn't been updated to the new backend system. diff --git a/.changeset/hot-wolves-flash.md b/.changeset/hot-wolves-flash.md new file mode 100644 index 0000000000..84c4d34f37 --- /dev/null +++ b/.changeset/hot-wolves-flash.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +Step titles in the Stepper are now clickable and redirect the user to the corresponding step, as an alternative to using the back buttons. diff --git a/.changeset/hungry-buckets-compare.md b/.changeset/hungry-buckets-compare.md new file mode 100644 index 0000000000..c70f38bfb7 --- /dev/null +++ b/.changeset/hungry-buckets-compare.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +Ensure redaction of secrets that have accidental extra whitespace around them diff --git a/.changeset/itchy-camels-cough.md b/.changeset/itchy-camels-cough.md new file mode 100644 index 0000000000..2ec70c945c --- /dev/null +++ b/.changeset/itchy-camels-cough.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-oauth2-proxy-provider': patch +--- + +Change provider id from `oauth2ProxyProvider` to `oauth2Proxy` diff --git a/.changeset/khaki-clocks-happen.md b/.changeset/khaki-clocks-happen.md new file mode 100644 index 0000000000..ac20e42dfa --- /dev/null +++ b/.changeset/khaki-clocks-happen.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +Add redacting for secrets in stack traces of logs diff --git a/.changeset/khaki-hounds-think.md b/.changeset/khaki-hounds-think.md new file mode 100644 index 0000000000..9c7145fc89 --- /dev/null +++ b/.changeset/khaki-hounds-think.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-github-actions': patch +--- + +Github Workflow Runs UI is modified to show in optional Card view instead of table, with branch selection option diff --git a/.changeset/kind-badgers-rush.md b/.changeset/kind-badgers-rush.md new file mode 100644 index 0000000000..4ec19bd17b --- /dev/null +++ b/.changeset/kind-badgers-rush.md @@ -0,0 +1,8 @@ +--- +'@backstage/backend-openapi-utils': patch +'@backstage/plugin-scaffolder-react': patch +'@backstage/plugin-catalog-react': patch +'@backstage/plugin-scaffolder': patch +--- + +Minor updates for TypeScript 5.2.2+ compatibility diff --git a/.changeset/kind-cycles-happen.md b/.changeset/kind-cycles-happen.md new file mode 100644 index 0000000000..7ebe870d46 --- /dev/null +++ b/.changeset/kind-cycles-happen.md @@ -0,0 +1,6 @@ +--- +'@backstage/core-app-api': patch +'@backstage/cli': patch +--- + +Added deprecation warning for React Router v6 beta, please make sure you have migrated your apps to use React Router v6 stable as support for the beta version will be removed. See the [migration tutorial](https://backstage.io/docs/tutorials/react-router-stable-migration) for more information. diff --git a/.changeset/large-weeks-accept.md b/.changeset/large-weeks-accept.md new file mode 100644 index 0000000000..b640c44d42 --- /dev/null +++ b/.changeset/large-weeks-accept.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes-react': patch +--- + +Add ID property to the table displaying kubernetes pods to avoid closing the info sidebar when the data reloads and needs to rerender. diff --git a/.changeset/late-eyes-serve.md b/.changeset/late-eyes-serve.md new file mode 100644 index 0000000000..37d8e7a22a --- /dev/null +++ b/.changeset/late-eyes-serve.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Wrap single `pipelineLoop` of TaskPipeline in a span for better traces diff --git a/.changeset/late-hats-beam.md b/.changeset/late-hats-beam.md new file mode 100644 index 0000000000..7ba20d743a --- /dev/null +++ b/.changeset/late-hats-beam.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': patch +--- + +Fixed a bug where `schema openapi init` created an invalid test command. diff --git a/.changeset/light-beers-cheer.md b/.changeset/light-beers-cheer.md new file mode 100644 index 0000000000..7d732edae8 --- /dev/null +++ b/.changeset/light-beers-cheer.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-compat-api': patch +--- + +Added `compatWrapper`, which can be used to wrap any React element to provide bi-directional interoperability between the `@backstage/core-*-api` and `@backstage/frontend-*-api` APIs. diff --git a/.changeset/little-suits-collect.md b/.changeset/little-suits-collect.md new file mode 100644 index 0000000000..2a1eb4c833 --- /dev/null +++ b/.changeset/little-suits-collect.md @@ -0,0 +1,5 @@ +--- +'@backstage/test-utils': patch +--- + +Deprecated `mockBreakpoint`, as it is now available from `@backstage/core-components/testUtils` instead. diff --git a/.changeset/long-cycles-grow.md b/.changeset/long-cycles-grow.md new file mode 100644 index 0000000000..4edc1905fe --- /dev/null +++ b/.changeset/long-cycles-grow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-lighthouse': patch +--- + +Updated README diff --git a/.changeset/long-wolves-return.md b/.changeset/long-wolves-return.md new file mode 100644 index 0000000000..8d4d78792f --- /dev/null +++ b/.changeset/long-wolves-return.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Bringing over apis from core-plugin-api diff --git a/.changeset/lucky-kids-cough.md b/.changeset/lucky-kids-cough.md new file mode 100644 index 0000000000..5ab1856e35 --- /dev/null +++ b/.changeset/lucky-kids-cough.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-catalog': patch +--- + +- Fixes bug where after unregistering an entity you are redirected to `/`. +- Adds an optional external route `unregisterRedirect` to override this behaviour to another route. diff --git a/.changeset/metal-eggs-smile.md b/.changeset/metal-eggs-smile.md new file mode 100644 index 0000000000..1a7e86d6f0 --- /dev/null +++ b/.changeset/metal-eggs-smile.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-okta-provider': patch +--- + +Adds okta-provider backend module for the auth plugin diff --git a/.changeset/modern-mails-live.md b/.changeset/modern-mails-live.md new file mode 100644 index 0000000000..f8e12e8815 --- /dev/null +++ b/.changeset/modern-mails-live.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-test-utils': patch +--- + +Re-export mock API implementations as well as `TestApiProvider`, `TestApiRegistry`, `withLogCollector`, and `setupRequestMockHandlers` from `@backstage/test-utils`. diff --git a/.changeset/nasty-rockets-bathe.md b/.changeset/nasty-rockets-bathe.md new file mode 100644 index 0000000000..1320b000b7 --- /dev/null +++ b/.changeset/nasty-rockets-bathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-compat-api': minor +--- + +Discover plugins and routes recursively beneath the root routes in `collectLecacyRoutes` diff --git a/.changeset/nervous-dancers-wait.md b/.changeset/nervous-dancers-wait.md new file mode 100644 index 0000000000..388d995487 --- /dev/null +++ b/.changeset/nervous-dancers-wait.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +Added `createSignInPageExtension`. diff --git a/.changeset/nervous-ladybugs-end.md b/.changeset/nervous-ladybugs-end.md new file mode 100644 index 0000000000..5ee94ec637 --- /dev/null +++ b/.changeset/nervous-ladybugs-end.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +fix static token issuer not being able to initialize diff --git a/.changeset/nervous-penguins-sort.md b/.changeset/nervous-penguins-sort.md new file mode 100644 index 0000000000..0c3ae4fcbe --- /dev/null +++ b/.changeset/nervous-penguins-sort.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-catalog-react': patch +'@backstage/plugin-search-react': patch +'@backstage/plugin-catalog': patch +--- + +Internal refactor of alpha exports due to a change in how extension factories are defined. diff --git a/.changeset/ninety-otters-report.md b/.changeset/ninety-otters-report.md new file mode 100644 index 0000000000..fbccc481f4 --- /dev/null +++ b/.changeset/ninety-otters-report.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-lighthouse-backend': minor +--- + +Fixed crashes faced with custom schedule configuration. The configuration schema has been update to leverage the TaskScheduleDefinition interface. It is highly recommended to move the `lighthouse.shedule` and `lighthouse.timeout` respectively to `lighthouse.schedule.frequency` and `lighthouse.schedule.timeout`. diff --git a/.changeset/orange-boats-hunt.md b/.changeset/orange-boats-hunt.md new file mode 100644 index 0000000000..1a3d9b1682 --- /dev/null +++ b/.changeset/orange-boats-hunt.md @@ -0,0 +1,6 @@ +--- +'@backstage/frontend-app-api': patch +'@backstage/core-compat-api': patch +--- + +Updates to match the new extension input wrapping. diff --git a/.changeset/perfect-apes-sing.md b/.changeset/perfect-apes-sing.md new file mode 100644 index 0000000000..fede777057 --- /dev/null +++ b/.changeset/perfect-apes-sing.md @@ -0,0 +1,7 @@ +--- +'@backstage/core-components': patch +'@backstage/plugin-catalog-react': patch +'@backstage/plugin-catalog': patch +--- + +Register component overrides in the global `OverrideComponentNameToClassKeys` provided by `@backstage/theme`. This will in turn will provide component style override types for `createUnifiedTheme`. diff --git a/.changeset/perfect-crabs-help.md b/.changeset/perfect-crabs-help.md new file mode 100644 index 0000000000..831649ffe7 --- /dev/null +++ b/.changeset/perfect-crabs-help.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +Add horizontal slider if stepper overflows diff --git a/.changeset/pink-dryers-repair.md b/.changeset/pink-dryers-repair.md new file mode 100644 index 0000000000..42720c635a --- /dev/null +++ b/.changeset/pink-dryers-repair.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +The Okta provider implementation is moved to the new module diff --git a/.changeset/polite-crabs-build.md b/.changeset/polite-crabs-build.md new file mode 100644 index 0000000000..5975ac3c4e --- /dev/null +++ b/.changeset/polite-crabs-build.md @@ -0,0 +1,12 @@ +--- +'@backstage/plugin-catalog-import': patch +'@backstage/plugin-user-settings': patch +'@backstage/plugin-tech-radar': patch +'@backstage/plugin-graphiql': patch +'@backstage/plugin-techdocs': patch +'@backstage/plugin-catalog': patch +'@backstage/plugin-search': patch +'@backstage/plugin-home': patch +--- + +Wrap `/alpha` export extension elements in backwards compatibility wrapper. diff --git a/.changeset/poor-pandas-dream.md b/.changeset/poor-pandas-dream.md new file mode 100644 index 0000000000..2804fa6926 --- /dev/null +++ b/.changeset/poor-pandas-dream.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Tweaked Node.js version check for when to use the new module register API with the new backend `package start` command. diff --git a/.changeset/pre.json b/.changeset/pre.json index 8dfa80eca3..245e7d7dd1 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -106,7 +106,6 @@ "@backstage/plugin-catalog-backend-module-unprocessed": "0.3.4", "@backstage/plugin-catalog-common": "1.0.18", "@backstage/plugin-catalog-graph": "0.3.0", - "@backstage/plugin-catalog-graphql": "0.4.1", "@backstage/plugin-catalog-import": "0.10.2", "@backstage/plugin-catalog-node": "1.5.0", "@backstage/plugin-catalog-react": "1.9.0", @@ -158,7 +157,6 @@ "@backstage/plugin-gitops-profiles": "0.3.42", "@backstage/plugin-gocd": "0.1.32", "@backstage/plugin-graphiql": "0.3.0", - "@backstage/plugin-graphql-backend": "0.2.1", "@backstage/plugin-graphql-voyager": "0.1.9", "@backstage/plugin-home": "0.5.10", "@backstage/plugin-home-react": "0.1.5", @@ -254,7 +252,181 @@ "@backstage/plugin-vault": "0.1.21", "@backstage/plugin-vault-backend": "0.4.0", "@backstage/plugin-vault-node": "0.1.0", - "@backstage/plugin-xcmetrics": "0.2.45" + "@backstage/plugin-xcmetrics": "0.2.45", + "@backstage/frontend-test-utils": "0.0.0", + "@backstage/plugin-auth-backend-module-atlassian-provider": "0.0.0", + "@backstage/plugin-auth-backend-module-okta-provider": "0.0.0", + "@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "0.0.0", + "@backstage/plugin-auth-backend-module-vmware-cloud-provider": "0.0.0" }, - "changesets": [] + "changesets": [ + "angry-eagles-end", + "angry-gorillas-unite", + "angry-walls-despacito", + "angry-walls-juggle", + "big-swans-guess", + "blue-meals-chew", + "brave-beers-happen", + "brave-parents-stare", + "brave-socks-raise", + "breezy-houses-eat", + "breezy-pans-glow", + "bright-eyes-film", + "brown-books-carry", + "chatty-actors-live", + "chilled-buses-love", + "chilled-terms-breathe", + "chilly-bikes-kick", + "chilly-lies-collect", + "clean-clouds-fry", + "clever-wombats-sneeze", + "cold-pans-crash", + "cool-knives-argue", + "create-app-1700579510", + "create-app-1700607979", + "curly-walls-relate", + "dirty-turkeys-reflect", + "dry-readers-raise", + "eighty-dodos-sing", + "eighty-phones-peel", + "eleven-ants-pretend", + "empty-dingos-grow", + "empty-fireants-study", + "fair-plants-attack", + "famous-flies-kick", + "famous-peas-reflect", + "fifty-cameras-share", + "fifty-seas-grab", + "five-feet-call", + "forty-clocks-hug", + "forty-insects-drop", + "forty-mirrors-carry", + "four-foxes-juggle", + "four-needles-watch", + "funny-bobcats-try", + "gentle-lies-greet", + "gentle-timers-fail", + "giant-files-fry", + "gold-humans-tease", + "gold-shirts-yell", + "good-wolves-leave", + "gorgeous-snails-admire", + "great-rings-type", + "green-seals-play", + "healthy-feet-kick", + "healthy-poets-search", + "hip-berries-begin", + "hip-cars-repair", + "honest-houses-hide", + "hot-wolves-flash", + "hungry-buckets-compare", + "itchy-camels-cough", + "khaki-clocks-happen", + "khaki-hounds-think", + "kind-badgers-rush", + "kind-cycles-happen", + "large-weeks-accept", + "late-eyes-serve", + "late-hats-beam", + "light-beers-cheer", + "little-suits-collect", + "long-cycles-grow", + "long-wolves-return", + "lovely-terms-search", + "lucky-kids-cough", + "metal-eggs-smile", + "mighty-beans-wink", + "modern-mails-live", + "nasty-rockets-bathe", + "nasty-tips-exercise", + "nervous-dancers-wait", + "nervous-ladybugs-end", + "nervous-penguins-sort", + "ninety-otters-report", + "orange-boats-hunt", + "perfect-apes-sing", + "perfect-crabs-help", + "pink-dryers-repair", + "plenty-numbers-enjoy", + "polite-crabs-build", + "polite-knives-build", + "poor-pandas-dream", + "pretty-onions-knock", + "pretty-ravens-serve", + "proud-flies-travel", + "proud-seahorses-explain", + "quick-horses-reply", + "quick-lions-care", + "real-bees-thank", + "red-readers-search", + "renovate-0392ef9", + "renovate-07b1766", + "renovate-0c44581", + "renovate-1252136", + "renovate-12c95fb", + "renovate-169bdc2", + "renovate-19742c3", + "renovate-1ed81a0", + "renovate-240982c", + "renovate-4891ee7", + "renovate-4b1eded", + "renovate-522261c", + "renovate-6075f87", + "renovate-6c0fb81", + "renovate-6e5c790", + "renovate-796bd6f", + "renovate-8d8b90d", + "renovate-9d2d52e", + "renovate-a277605", + "renovate-a6399d6", + "renovate-b193efa", + "renovate-c4e012c", + "renovate-c7270d5", + "renovate-c727667", + "renovate-dee7ad1", + "renovate-ead3ba6", + "renovate-f5b18be", + "rich-bees-breathe", + "rich-singers-join", + "rude-beans-drop", + "rude-ears-greet", + "sharp-dingos-learn", + "shiny-books-search", + "silent-rats-reflect", + "silly-numbers-wash", + "silver-rocks-deliver", + "six-cooks-attack", + "sixty-adults-kiss", + "sixty-houses-agree", + "slow-bottles-cross", + "slow-trees-warn", + "smooth-frogs-decide", + "sour-pumas-reply", + "spotty-olives-share", + "spotty-terms-occur", + "stale-bats-end", + "stale-frogs-agree", + "stale-walls-cross", + "strange-brooms-poke", + "strange-suits-glow", + "stupid-wasps-fold", + "tame-pants-end", + "tasty-dolphins-unite", + "ten-snakes-wait", + "tender-peas-smoke", + "thick-snails-travel", + "thirty-fireants-cheer", + "tiny-cobras-look", + "tricky-donkeys-do", + "tricky-islands-wonder", + "twenty-beans-laugh", + "unlucky-clouds-build", + "violet-zebras-thank", + "warm-plums-beg", + "wet-bananas-agree", + "wicked-elephants-think", + "wicked-pants-end", + "wild-knives-wait", + "witty-cars-wash" + ] } diff --git a/.changeset/pretty-onions-knock.md b/.changeset/pretty-onions-knock.md new file mode 100644 index 0000000000..701024cba4 --- /dev/null +++ b/.changeset/pretty-onions-knock.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-azure-devops-backend': patch +'@backstage/plugin-azure-devops-common': patch +'@backstage/plugin-azure-devops': patch +--- + +Introduced new `AzureDevOpsAnnotatorProcessor` that adds the needed annotations automatically. Also, moved constants to common package so they can be shared more easily diff --git a/.changeset/pretty-ravens-serve.md b/.changeset/pretty-ravens-serve.md new file mode 100644 index 0000000000..95d1b629fd --- /dev/null +++ b/.changeset/pretty-ravens-serve.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Migrate analytics route tracker component. diff --git a/.changeset/proud-flies-travel.md b/.changeset/proud-flies-travel.md new file mode 100644 index 0000000000..41f40e2e90 --- /dev/null +++ b/.changeset/proud-flies-travel.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-compat-api': patch +--- + +Made package public so it can be published diff --git a/.changeset/proud-seahorses-explain.md b/.changeset/proud-seahorses-explain.md new file mode 100644 index 0000000000..328e4bf838 --- /dev/null +++ b/.changeset/proud-seahorses-explain.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': minor +--- + +Updates the ESLint config to ignore issues created by generated files in `**/src/generated/**`. diff --git a/.changeset/quick-horses-reply.md b/.changeset/quick-horses-reply.md new file mode 100644 index 0000000000..3469ef1d89 --- /dev/null +++ b/.changeset/quick-horses-reply.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Fix creating env secret in github:environment:create action diff --git a/.changeset/quick-lions-care.md b/.changeset/quick-lions-care.md new file mode 100644 index 0000000000..aa5caada05 --- /dev/null +++ b/.changeset/quick-lions-care.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Include the `` for group entities by default diff --git a/.changeset/real-bees-thank.md b/.changeset/real-bees-thank.md new file mode 100644 index 0000000000..e89dfc7a68 --- /dev/null +++ b/.changeset/real-bees-thank.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Adding in spec.type chip to search results for clarity diff --git a/.changeset/red-readers-search.md b/.changeset/red-readers-search.md new file mode 100644 index 0000000000..c18d9672ba --- /dev/null +++ b/.changeset/red-readers-search.md @@ -0,0 +1,10 @@ +--- +'@backstage/plugin-catalog-react': patch +'@backstage/plugin-user-settings': patch +'@backstage/plugin-graphiql': patch +'@backstage/plugin-catalog': patch +'@backstage/plugin-search': patch +'@backstage/plugin-home': patch +--- + +Updates to the `/alpha` exports to match the extension input wrapping change. diff --git a/.changeset/renovate-0392ef9.md b/.changeset/renovate-0392ef9.md new file mode 100644 index 0000000000..3ee3fb0361 --- /dev/null +++ b/.changeset/renovate-0392ef9.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Updated dependency `vite-plugin-node-polyfills` to `^0.17.0`. diff --git a/.changeset/renovate-07b1766.md b/.changeset/renovate-07b1766.md new file mode 100644 index 0000000000..245f827d08 --- /dev/null +++ b/.changeset/renovate-07b1766.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-apollo-explorer': patch +--- + +Updated dependency `@apollo/explorer` to `^3.0.0`. diff --git a/.changeset/renovate-0c44581.md b/.changeset/renovate-0c44581.md new file mode 100644 index 0000000000..afddf45fed --- /dev/null +++ b/.changeset/renovate-0c44581.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Updated dependency `@rollup/plugin-node-resolve` to `^15.0.0`. diff --git a/.changeset/renovate-1252136.md b/.changeset/renovate-1252136.md new file mode 100644 index 0000000000..0be5143b30 --- /dev/null +++ b/.changeset/renovate-1252136.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': patch +--- + +Updated dependency `@stoplight/types` to `^14.0.0`. diff --git a/.changeset/renovate-12c95fb.md b/.changeset/renovate-12c95fb.md new file mode 100644 index 0000000000..814817b8c2 --- /dev/null +++ b/.changeset/renovate-12c95fb.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-common': patch +--- + +Updated dependency `archiver` to `^6.0.0`. +Updated dependency `@types/archiver` to `^6.0.0`. diff --git a/.changeset/renovate-169bdc2.md b/.changeset/renovate-169bdc2.md new file mode 100644 index 0000000000..6a54230a28 --- /dev/null +++ b/.changeset/renovate-169bdc2.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +Updated dependency `graphiql` to `3.0.10`. diff --git a/.changeset/renovate-19742c3.md b/.changeset/renovate-19742c3.md new file mode 100644 index 0000000000..2dfee1ad96 --- /dev/null +++ b/.changeset/renovate-19742c3.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Updated dependency `@rollup/plugin-json` to `^6.0.0`. diff --git a/.changeset/renovate-1ed81a0.md b/.changeset/renovate-1ed81a0.md new file mode 100644 index 0000000000..ae2e061f24 --- /dev/null +++ b/.changeset/renovate-1ed81a0.md @@ -0,0 +1,11 @@ +--- +'@backstage/plugin-home-react': patch +'@backstage/plugin-home': patch +'@backstage/plugin-scaffolder-react': patch +'@backstage/plugin-scaffolder': patch +--- + +Updated dependency `@rjsf/utils` to `5.14.3`. +Updated dependency `@rjsf/core` to `5.14.3`. +Updated dependency `@rjsf/material-ui` to `5.14.3`. +Updated dependency `@rjsf/validator-ajv8` to `5.14.3`. diff --git a/.changeset/renovate-240982c.md b/.changeset/renovate-240982c.md new file mode 100644 index 0000000000..f68e583388 --- /dev/null +++ b/.changeset/renovate-240982c.md @@ -0,0 +1,11 @@ +--- +'@backstage/plugin-home-react': patch +'@backstage/plugin-home': patch +'@backstage/plugin-scaffolder-react': patch +'@backstage/plugin-scaffolder': patch +--- + +Updated dependency `@rjsf/utils` to `5.14.1`. +Updated dependency `@rjsf/core` to `5.14.1`. +Updated dependency `@rjsf/material-ui` to `5.14.1`. +Updated dependency `@rjsf/validator-ajv8` to `5.14.1`. diff --git a/.changeset/renovate-2613384.md b/.changeset/renovate-2613384.md new file mode 100644 index 0000000000..50d01354de --- /dev/null +++ b/.changeset/renovate-2613384.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Updated dependency `bfj` to `^8.0.0`. diff --git a/.changeset/renovate-4891ee7.md b/.changeset/renovate-4891ee7.md new file mode 100644 index 0000000000..031e42d111 --- /dev/null +++ b/.changeset/renovate-4891ee7.md @@ -0,0 +1,9 @@ +--- +'@backstage/backend-common': patch +'@backstage/plugin-kubernetes-backend': patch +'@backstage/plugin-kubernetes-common': patch +'@backstage/plugin-kubernetes-react': patch +'@backstage/plugin-kubernetes': patch +--- + +Updated dependency `@kubernetes/client-node` to `0.20.0`. diff --git a/.changeset/renovate-4b1eded.md b/.changeset/renovate-4b1eded.md new file mode 100644 index 0000000000..290e647895 --- /dev/null +++ b/.changeset/renovate-4b1eded.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +Updated dependency `@asyncapi/react-component` to `1.2.2`. diff --git a/.changeset/renovate-522261c.md b/.changeset/renovate-522261c.md new file mode 100644 index 0000000000..fb25fe0078 --- /dev/null +++ b/.changeset/renovate-522261c.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Updated dependency `@types/glob` to `^8.0.0`. diff --git a/.changeset/renovate-5644299.md b/.changeset/renovate-5644299.md new file mode 100644 index 0000000000..04ba4c47a4 --- /dev/null +++ b/.changeset/renovate-5644299.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +Updated dependency `@asyncapi/react-component` to `1.2.6`. diff --git a/.changeset/renovate-6075f87.md b/.changeset/renovate-6075f87.md new file mode 100644 index 0000000000..8997cb080b --- /dev/null +++ b/.changeset/renovate-6075f87.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes-backend': patch +--- + +Updated dependency `@aws-crypto/sha256-js` to `^5.0.0`. diff --git a/.changeset/renovate-6e5c790.md b/.changeset/renovate-6e5c790.md new file mode 100644 index 0000000000..e8be20623c --- /dev/null +++ b/.changeset/renovate-6e5c790.md @@ -0,0 +1,9 @@ +--- +'@backstage/integration': patch +'@backstage/plugin-azure-sites-backend': patch +'@backstage/plugin-catalog-backend-module-msgraph': patch +'@backstage/plugin-kubernetes-backend': patch +'@backstage/plugin-techdocs-node': patch +--- + +Updated dependency `@azure/identity` to `^4.0.0`. diff --git a/.changeset/renovate-796bd6f.md b/.changeset/renovate-796bd6f.md new file mode 100644 index 0000000000..561f6b8b03 --- /dev/null +++ b/.changeset/renovate-796bd6f.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Updated dependency `@typescript-eslint/eslint-plugin` to `6.12.0`. diff --git a/.changeset/renovate-8d8b90d.md b/.changeset/renovate-8d8b90d.md new file mode 100644 index 0000000000..169d480dec --- /dev/null +++ b/.changeset/renovate-8d8b90d.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Updated dependency `linkifyjs` to `4.1.3`. diff --git a/.changeset/renovate-9d2d52e.md b/.changeset/renovate-9d2d52e.md new file mode 100644 index 0000000000..e7a02f8f41 --- /dev/null +++ b/.changeset/renovate-9d2d52e.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Updated dependency `@typescript-eslint/eslint-plugin` to `6.11.0`. diff --git a/.changeset/renovate-a277605.md b/.changeset/renovate-a277605.md new file mode 100644 index 0000000000..2bb2274e49 --- /dev/null +++ b/.changeset/renovate-a277605.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Updated dependency `@rollup/plugin-commonjs` to `^25.0.0`. diff --git a/.changeset/renovate-a6399d6.md b/.changeset/renovate-a6399d6.md new file mode 100644 index 0000000000..d26cd717b3 --- /dev/null +++ b/.changeset/renovate-a6399d6.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-common': patch +'@backstage/plugin-techdocs-node': patch +--- + +Updated dependency `@google-cloud/storage` to `^7.0.0`. diff --git a/.changeset/renovate-b193efa.md b/.changeset/renovate-b193efa.md new file mode 100644 index 0000000000..dfb2430162 --- /dev/null +++ b/.changeset/renovate-b193efa.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +Updated dependency `@asyncapi/react-component` to `1.1.0`. diff --git a/.changeset/renovate-c4e012c.md b/.changeset/renovate-c4e012c.md new file mode 100644 index 0000000000..eb26b9fb58 --- /dev/null +++ b/.changeset/renovate-c4e012c.md @@ -0,0 +1,10 @@ +--- +'@backstage/core-components': patch +'@backstage/plugin-entity-validation': patch +'@backstage/plugin-gcp-projects': patch +'@backstage/plugin-scaffolder-react': patch +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-techdocs-module-addons-contrib': patch +--- + +Updated dependency `@react-hookz/web` to `^23.0.0`. diff --git a/.changeset/renovate-c7270d5.md b/.changeset/renovate-c7270d5.md new file mode 100644 index 0000000000..e38e9ba816 --- /dev/null +++ b/.changeset/renovate-c7270d5.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-catalog-backend-module-gcp': patch +'@backstage/plugin-kubernetes-backend': patch +--- + +Updated dependency `@google-cloud/container` to `^5.0.0`. diff --git a/.changeset/renovate-c727667.md b/.changeset/renovate-c727667.md new file mode 100644 index 0000000000..82b7d0a8f5 --- /dev/null +++ b/.changeset/renovate-c727667.md @@ -0,0 +1,12 @@ +--- +'@backstage/plugin-auth-backend-module-atlassian-provider': patch +'@backstage/plugin-auth-backend-module-gitlab-provider': patch +'@backstage/plugin-auth-backend-module-microsoft-provider': patch +'@backstage/plugin-auth-backend-module-oauth2-provider': patch +'@backstage/plugin-auth-backend-module-okta-provider': patch +'@backstage/plugin-auth-backend-module-pinniped-provider': patch +'@backstage/plugin-auth-backend': patch +'@backstage/plugin-auth-node': patch +--- + +Updated dependency `passport` to `^0.7.0`. diff --git a/.changeset/renovate-dee7ad1.md b/.changeset/renovate-dee7ad1.md new file mode 100644 index 0000000000..8f98f255f6 --- /dev/null +++ b/.changeset/renovate-dee7ad1.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Updated dependency `@google-cloud/firestore` to `^7.0.0`. diff --git a/.changeset/renovate-ead3ba6.md b/.changeset/renovate-ead3ba6.md new file mode 100644 index 0000000000..f62d2cf0ed --- /dev/null +++ b/.changeset/renovate-ead3ba6.md @@ -0,0 +1,11 @@ +--- +'@backstage/plugin-home-react': patch +'@backstage/plugin-home': patch +'@backstage/plugin-scaffolder-react': patch +'@backstage/plugin-scaffolder': patch +--- + +Updated dependency `@rjsf/utils` to `5.14.2`. +Updated dependency `@rjsf/core` to `5.14.2`. +Updated dependency `@rjsf/material-ui` to `5.14.2`. +Updated dependency `@rjsf/validator-ajv8` to `5.14.2`. diff --git a/.changeset/renovate-f5b18be.md b/.changeset/renovate-f5b18be.md new file mode 100644 index 0000000000..82bcbd724f --- /dev/null +++ b/.changeset/renovate-f5b18be.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-azure-sites-backend': patch +--- + +Updated dependency `@azure/arm-appservice` to `^14.0.0`. diff --git a/.changeset/rich-bees-breathe.md b/.changeset/rich-bees-breathe.md new file mode 100644 index 0000000000..7a40e3df2f --- /dev/null +++ b/.changeset/rich-bees-breathe.md @@ -0,0 +1,17 @@ +--- +'@backstage/plugin-catalog-import': patch +'@backstage/plugin-stack-overflow': patch +'@backstage/plugin-catalog-react': patch +'@backstage/plugin-user-settings': patch +'@backstage/plugin-search-react': patch +'@backstage/plugin-tech-radar': patch +'@backstage/plugin-graphiql': patch +'@backstage/plugin-techdocs': patch +'@backstage/plugin-catalog': patch +'@backstage/plugin-explore': patch +'@backstage/plugin-search': patch +'@backstage/plugin-home': patch +'@backstage/plugin-adr': patch +--- + +Refactor of the alpha exports due to API change in how extension IDs are constructed. diff --git a/.changeset/rich-singers-join.md b/.changeset/rich-singers-join.md new file mode 100644 index 0000000000..1a21fa9fc8 --- /dev/null +++ b/.changeset/rich-singers-join.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +--- + +Ensure that cursors always come back as JSON on sqlite too diff --git a/.changeset/rude-beans-drop.md b/.changeset/rude-beans-drop.md new file mode 100644 index 0000000000..63f10af55d --- /dev/null +++ b/.changeset/rude-beans-drop.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Update `linkify-react` to version `4.1.3` diff --git a/.changeset/rude-ears-greet.md b/.changeset/rude-ears-greet.md new file mode 100644 index 0000000000..b5dd684c16 --- /dev/null +++ b/.changeset/rude-ears-greet.md @@ -0,0 +1,6 @@ +--- +'@backstage/create-app': patch +'@backstage/plugin-circleci': patch +--- + +CircelCI plugin moved permanently diff --git a/.changeset/sharp-dingos-learn.md b/.changeset/sharp-dingos-learn.md new file mode 100644 index 0000000000..9447ca9698 --- /dev/null +++ b/.changeset/sharp-dingos-learn.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-compat-api': patch +--- + +Delete alpha DI compatibility helper for components, migrating components should be simple without a helper. diff --git a/.changeset/shiny-books-search.md b/.changeset/shiny-books-search.md new file mode 100644 index 0000000000..1d743565b9 --- /dev/null +++ b/.changeset/shiny-books-search.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': minor +--- + +The app no longer provides the `AppContext` from `@backstage/core-plugin-api`. Components that require this context to be available should use the `compatWrapper` helper from `@backstage/core-compat-api`. diff --git a/.changeset/silent-rats-reflect.md b/.changeset/silent-rats-reflect.md new file mode 100644 index 0000000000..b7884f06d0 --- /dev/null +++ b/.changeset/silent-rats-reflect.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': minor +--- + +Adds a new command `schema openapi generate-client` that creates a Typescript client with Backstage flavor, including the discovery API and fetch API. This command doesn't currently generate a complete client and needs to be wrapped or exported manually by a separate Backstage plugin. See `@backstage/catalog-client/src/generated` for example output. diff --git a/.changeset/silly-numbers-wash.md b/.changeset/silly-numbers-wash.md new file mode 100644 index 0000000000..25df8b12c1 --- /dev/null +++ b/.changeset/silly-numbers-wash.md @@ -0,0 +1,20 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Added pagination support to `CatalogIndexPage` + +`CatalogIndexPage` now offers an optional pagination feature, designed to accommodate adopters managing extensive catalogs. This new capability allows for better handling of large amounts of data. + +To activate the pagination mode, simply update your `App.tsx` as follows: + +```diff + const routes = ( + + ... +- } /> ++ } /> + ... +``` + +In case you have a custom catalog page and you want to enable pagination, you need to pass the `pagination` prop to `EntityListProvider` instead. diff --git a/.changeset/silver-rocks-deliver.md b/.changeset/silver-rocks-deliver.md new file mode 100644 index 0000000000..eb132199f3 --- /dev/null +++ b/.changeset/silver-rocks-deliver.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-user-settings': patch +'@backstage/plugin-catalog': patch +'@backstage/plugin-adr': patch +--- + +Updated alpha translation message keys to use nested format and camel case. diff --git a/.changeset/six-cooks-attack.md b/.changeset/six-cooks-attack.md new file mode 100644 index 0000000000..0182f1e06a --- /dev/null +++ b/.changeset/six-cooks-attack.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +Added translation APIs as well as `createTranslationExtension`. diff --git a/.changeset/sixty-adults-kiss.md b/.changeset/sixty-adults-kiss.md new file mode 100644 index 0000000000..eb73387308 --- /dev/null +++ b/.changeset/sixty-adults-kiss.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Added `createSpecializedApp`, which is a synchronous version of `createApp` where config and features already need to be loaded. diff --git a/.changeset/slow-bottles-cross.md b/.changeset/slow-bottles-cross.md new file mode 100644 index 0000000000..32446f1554 --- /dev/null +++ b/.changeset/slow-bottles-cross.md @@ -0,0 +1,6 @@ +--- +'@backstage/frontend-plugin-api': patch +'@backstage/frontend-app-api': patch +--- + +Forward ` node`` instead of `extensionId` to resolved extension inputs. diff --git a/.changeset/slow-trees-warn.md b/.changeset/slow-trees-warn.md new file mode 100644 index 0000000000..5a05f9a07f --- /dev/null +++ b/.changeset/slow-trees-warn.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Updated alpha plugin to include the `unregisterRedirect` external route. diff --git a/.changeset/smooth-frogs-decide.md b/.changeset/smooth-frogs-decide.md new file mode 100644 index 0000000000..942a3a80bf --- /dev/null +++ b/.changeset/smooth-frogs-decide.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +Migrate analytics api and context files. diff --git a/.changeset/sour-pumas-reply.md b/.changeset/sour-pumas-reply.md new file mode 100644 index 0000000000..99b812acdd --- /dev/null +++ b/.changeset/sour-pumas-reply.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Fixing `headerOptions` not being passed through the `TemplatePage` component diff --git a/.changeset/spotty-olives-share.md b/.changeset/spotty-olives-share.md new file mode 100644 index 0000000000..7437b3af00 --- /dev/null +++ b/.changeset/spotty-olives-share.md @@ -0,0 +1,7 @@ +--- +'@techdocs/cli': minor +'@backstage/plugin-techdocs-node': minor +'@backstage/backend-common': patch +--- + +Add command `--runAsDefaultUser` for `@techdocs/cli generate` to bypass running the docker builds as host user for macOS and Linux. diff --git a/.changeset/spotty-terms-occur.md b/.changeset/spotty-terms-occur.md new file mode 100644 index 0000000000..471ba6d0dc --- /dev/null +++ b/.changeset/spotty-terms-occur.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': patch +--- + +Execute `openapi-generator-cli` from `@backstage/repo-tools` directory to force it to use our openapitools.json config file. diff --git a/.changeset/stale-bats-end.md b/.changeset/stale-bats-end.md new file mode 100644 index 0000000000..e6715deba9 --- /dev/null +++ b/.changeset/stale-bats-end.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-node': patch +--- + +Bumped the default TechDocs docker image version to the latest which was released several month ago diff --git a/.changeset/stale-frogs-agree.md b/.changeset/stale-frogs-agree.md new file mode 100644 index 0000000000..84052bded8 --- /dev/null +++ b/.changeset/stale-frogs-agree.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Updates to match the introduction of `ExtensionDefinition` and new extension ID naming patterns. diff --git a/.changeset/stale-walls-cross.md b/.changeset/stale-walls-cross.md new file mode 100644 index 0000000000..79d682631b --- /dev/null +++ b/.changeset/stale-walls-cross.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Updates to provide `node` to extension factories instead of `id` and `source`. diff --git a/.changeset/strange-brooms-poke.md b/.changeset/strange-brooms-poke.md new file mode 100644 index 0000000000..35b7d48360 --- /dev/null +++ b/.changeset/strange-brooms-poke.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-client': patch +--- + +Fixes a bug where some query parameters were double URL encoded. diff --git a/.changeset/strange-suits-glow.md b/.changeset/strange-suits-glow.md new file mode 100644 index 0000000000..6f1ba31127 --- /dev/null +++ b/.changeset/strange-suits-glow.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Switched the `@typescript-eslint/eslint-plugin` dependency back to using a `^` version range. diff --git a/.changeset/stupid-wasps-fold.md b/.changeset/stupid-wasps-fold.md new file mode 100644 index 0000000000..260dd9f5f1 --- /dev/null +++ b/.changeset/stupid-wasps-fold.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-compat-api': patch +--- + +Updates for compatibility with the new extension IDs. diff --git a/.changeset/tame-pants-end.md b/.changeset/tame-pants-end.md new file mode 100644 index 0000000000..b80fcb7fe3 --- /dev/null +++ b/.changeset/tame-pants-end.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-pagerduty': minor +--- + +This package has been deprecated, consider using [@pagerduty/backstage-plugin](https://github.com/pagerduty/backstage-plugin) instead. diff --git a/.changeset/tasty-dolphins-unite.md b/.changeset/tasty-dolphins-unite.md new file mode 100644 index 0000000000..b367b0c554 --- /dev/null +++ b/.changeset/tasty-dolphins-unite.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': minor +--- + +Extension inputs are now wrapped into an additional object when passed to the extension factory, with the previous values being available at the `output` property. The `ExtensionInputValues` type has also been replaced by `ResolvedExtensionInputs`. diff --git a/.changeset/ten-snakes-wait.md b/.changeset/ten-snakes-wait.md new file mode 100644 index 0000000000..1c15cb8d33 --- /dev/null +++ b/.changeset/ten-snakes-wait.md @@ -0,0 +1,7 @@ +--- +'@backstage/frontend-plugin-api': minor +--- + +**BREAKING**: This version changes how extensions are created and how their IDs are determined. The `createExtension` function now accepts `kind`, `namespace` and `name` instead of `id`. All of the new options are optional, and are used to construct the final extension ID. By convention extension creators should set the `kind` to match their own name, for example `createNavItemExtension` sets the kind `nav-item`. + +The `createExtension` function as well as all extension creators now also return an `ExtensionDefinition` rather than an `Extension`, which in turn needs to be passed to `createPlugin` or `createExtensionOverrides` to be used. diff --git a/.changeset/tender-peas-smoke.md b/.changeset/tender-peas-smoke.md new file mode 100644 index 0000000000..5c84e1a131 --- /dev/null +++ b/.changeset/tender-peas-smoke.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-sentry': patch +--- + +Added examples for `sentry:project:create` scaffolder action and unit tests. diff --git a/.changeset/thick-snails-travel.md b/.changeset/thick-snails-travel.md new file mode 100644 index 0000000000..bfd14d55e1 --- /dev/null +++ b/.changeset/thick-snails-travel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': minor +--- + +Properly support both function- and string-form visibility filter expressions in the new extensions exported via `/alpha`. diff --git a/.changeset/thirty-fireants-cheer.md b/.changeset/thirty-fireants-cheer.md new file mode 100644 index 0000000000..abda872570 --- /dev/null +++ b/.changeset/thirty-fireants-cheer.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Breaking alpha-API change to entity visibility filter functions to accept a bare entity as their first argument, instead of an object with an entity property. + +Functions that accept such filters now also support the string expression form of filters. diff --git a/.changeset/tiny-cobras-look.md b/.changeset/tiny-cobras-look.md new file mode 100644 index 0000000000..1c5acc6c4a --- /dev/null +++ b/.changeset/tiny-cobras-look.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Expose an `onAuth` handler for `git` actions to provide custom credentials diff --git a/.changeset/tricky-donkeys-do.md b/.changeset/tricky-donkeys-do.md new file mode 100644 index 0000000000..1a810e9f3b --- /dev/null +++ b/.changeset/tricky-donkeys-do.md @@ -0,0 +1,5 @@ +--- +'@techdocs/cli': minor +--- + +Support passing additional `mkdocs-server` CLI parameters (`--dirtyreload`, `--strict` and `--clean`) when run in containerized mode. diff --git a/.changeset/tricky-islands-wonder.md b/.changeset/tricky-islands-wonder.md new file mode 100644 index 0000000000..5b9c37281b --- /dev/null +++ b/.changeset/tricky-islands-wonder.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': minor +--- + +The `columns` prop can be an array or a function that returns an array in order to override the default columns of the `CatalogIndexPage`. diff --git a/.changeset/twenty-beans-laugh.md b/.changeset/twenty-beans-laugh.md new file mode 100644 index 0000000000..5dc537d93b --- /dev/null +++ b/.changeset/twenty-beans-laugh.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Fixed a issue where `CatalogPage` wasn't using the chosen `initiallySelectedFilter` as intended. diff --git a/.changeset/unlucky-clouds-build.md b/.changeset/unlucky-clouds-build.md new file mode 100644 index 0000000000..35aa277653 --- /dev/null +++ b/.changeset/unlucky-clouds-build.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-azure-devops-backend': minor +--- + +**BREAKING** New `fromConfig` static method must be used now when creating an instance of the `AzureDevOpsApi` + +Added support for using the `AzureDevOpsCredentialsProvider` diff --git a/.changeset/violet-zebras-thank.md b/.changeset/violet-zebras-thank.md new file mode 100644 index 0000000000..eda6137dc1 --- /dev/null +++ b/.changeset/violet-zebras-thank.md @@ -0,0 +1,5 @@ +--- +'@backstage/theme': minor +--- + +Added a global `OverrideComponentNameToClassKeys` for other plugins and packages to populate using module augmentation. This will in turn will provide component style override types for `createUnifiedTheme`. diff --git a/.changeset/warm-plums-beg.md b/.changeset/warm-plums-beg.md new file mode 100644 index 0000000000..6d09aabd2d --- /dev/null +++ b/.changeset/warm-plums-beg.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes-common': patch +--- + +Remove unused dependency diff --git a/.changeset/wet-bananas-agree.md b/.changeset/wet-bananas-agree.md new file mode 100644 index 0000000000..4bf47ca664 --- /dev/null +++ b/.changeset/wet-bananas-agree.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +Fixed issue for showing undefined for hidden form items diff --git a/.changeset/wicked-elephants-think.md b/.changeset/wicked-elephants-think.md new file mode 100644 index 0000000000..73fc9621bf --- /dev/null +++ b/.changeset/wicked-elephants-think.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': minor +--- + +The extension `factory` function now longer receives `id` or `source`, but instead now provides the extension's `AppNode` as `node`. The `ExtensionBoundary` component has also been updated to receive a `node` prop rather than `id` and `source`. diff --git a/.changeset/wicked-pants-end.md b/.changeset/wicked-pants-end.md new file mode 100644 index 0000000000..ecb42d0957 --- /dev/null +++ b/.changeset/wicked-pants-end.md @@ -0,0 +1,35 @@ +--- +'@backstage/plugin-catalog-backend-module-scaffolder-entity-model': patch +'@backstage/plugin-search-backend-module-stack-overflow-collator': patch +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +'@backstage/plugin-permission-backend-module-allow-all-policy': patch +'@backstage/plugin-auth-backend-module-oauth2-proxy-provider': patch +'@backstage/plugin-catalog-backend-module-bitbucket-server': patch +'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch +'@backstage/plugin-events-backend-module-bitbucket-cloud': patch +'@backstage/plugin-auth-backend-module-gcp-iap-provider': patch +'@backstage/plugin-auth-backend-module-google-provider': patch +'@backstage/plugin-search-backend-module-elasticsearch': patch +'@backstage/plugin-catalog-backend-module-unprocessed': patch +'@backstage/plugin-catalog-backend-module-github-org': patch +'@backstage/plugin-catalog-backend-module-puppetdb': patch +'@backstage/plugin-search-backend-module-techdocs': 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-search-backend-module-catalog': patch +'@backstage/plugin-search-backend-module-explore': patch +'@backstage/plugin-catalog-backend-module-azure': patch +'@backstage/plugin-events-backend-module-gerrit': patch +'@backstage/plugin-events-backend-module-github': patch +'@backstage/plugin-events-backend-module-gitlab': patch +'@backstage/plugin-events-backend-module-azure': patch +'@backstage/plugin-catalog-backend-module-aws': patch +'@backstage/plugin-catalog-backend-module-gcp': patch +'@backstage/plugin-search-backend-module-pg': patch +'@backstage/backend-test-utils': patch +'@backstage/plugin-events-backend': patch +--- + +Switched module ID to use kebab-case. diff --git a/.changeset/wild-knives-wait.md b/.changeset/wild-knives-wait.md new file mode 100644 index 0000000000..6aafbe7acd --- /dev/null +++ b/.changeset/wild-knives-wait.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-catalog-backend': minor +'@backstage/plugin-catalog-node': minor +--- + +Permission rules can now be added for the Catalog plugin through the `CatalogPermissionExtensionPoint` interface. diff --git a/.changeset/witty-cars-wash.md b/.changeset/witty-cars-wash.md new file mode 100644 index 0000000000..301ed5e35a --- /dev/null +++ b/.changeset/witty-cars-wash.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Deprecated `EntitiesSearchFilter` and `EntityFilter`, which can now be imported from `@backstage/plugin-catalog-node` instead diff --git a/.github/labeler.yml b/.github/labeler.yml index dc048b1744..add66d7b28 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -2,7 +2,7 @@ area:catalog: - plugins/catalog/**/* - plugins/catalog-*/**/* - packages/catalog-*/**/* -scaffolder: +area:scaffolder: - plugins/scaffolder/**/* - plugins/scaffolder-*/**/* search: diff --git a/.github/uffizzi/uffizzi.production.app-config.yaml b/.github/uffizzi/uffizzi.production.app-config.yaml index fb6638295e..53944256e1 100644 --- a/.github/uffizzi/uffizzi.production.app-config.yaml +++ b/.github/uffizzi/uffizzi.production.app-config.yaml @@ -38,6 +38,14 @@ auth: url: https://demo.backstage.io/api/auth catalog: + rules: + - allow: + - Component + - API + - Resource + - System + - Domain + - Location locations: - type: url target: https://github.com/backstage/backstage/blob/${REF_NAME}/packages/catalog-model/examples/all.yaml diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index 73f6d56bb4..d557434d78 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -323,6 +323,7 @@ reusability Reusability roadmaps rollbar +Roboto Rollbar Rollup routable @@ -462,3 +463,4 @@ zod Zolotusky zoomable zsh +scrollable \ No newline at end of file diff --git a/.github/workflows/automate_area-labels.yml b/.github/workflows/automate_area-labels.yml index 1ba3b1d6c3..5d12e4ca89 100644 --- a/.github/workflows/automate_area-labels.yml +++ b/.github/workflows/automate_area-labels.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index 1768cb670e..bf58b4b49d 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/automate_merge_message.yml b/.github/workflows/automate_merge_message.yml index 29b64393ad..71e3450235 100644 --- a/.github/workflows/automate_merge_message.yml +++ b/.github/workflows/automate_merge_message.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit @@ -44,7 +44,7 @@ jobs: node generate.js ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} > message.txt - name: Post Message - uses: actions/github-script@v7.0.0 + uses: actions/github-script@v7.0.1 env: ISSUE_NUMBER: ${{ github.event.pull_request.number }} with: diff --git a/.github/workflows/automate_stale.yml b/.github/workflows/automate_stale.yml index b888471254..6d6fd65c0d 100644 --- a/.github/workflows/automate_stale.yml +++ b/.github/workflows/automate_stale.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/ci-noop.yml b/.github/workflows/ci-noop.yml index 648386873b..6918db4be5 100644 --- a/.github/workflows/ci-noop.yml +++ b/.github/workflows/ci-noop.yml @@ -39,7 +39,7 @@ jobs: name: Test ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b77983db04..33d89b9c96 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,7 +27,7 @@ jobs: name: Install ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit @@ -63,7 +63,7 @@ jobs: name: Verify ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index f1a1dbd0b0..4a9e4522f4 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index 65ded2b19b..9ceed78685 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit @@ -57,11 +57,11 @@ jobs: uses: docker/setup-buildx-action@v3.0.0 - name: Build and push - uses: docker/build-push-action@v5.0.0 + uses: docker/build-push-action@v5.1.0 with: context: './example-app' file: ./example-app/packages/backend/Dockerfile - push: ${{ github.event_name == "repository_dispatch" && github.event.action == "release-published" }} + push: ${{ (github.event_name == "repository_dispatch") && (github.event.action == "release-published") }} platforms: linux/amd64,linux/arm64 tags: | ghcr.io/${{ github.repository_owner }}/backstage:latest diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index c7b621f8fe..21a15ae475 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -24,7 +24,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit @@ -66,7 +66,7 @@ jobs: run: ls microsite/build && ls microsite/build/storybook - name: Deploy both microsite and storybook to gh-pages - uses: JamesIves/github-pages-deploy-action@a1ea191d508feb8485aceba848389d49f80ca2dc # v4.4.3 + uses: JamesIves/github-pages-deploy-action@65b5dfd4f5bcd3a7403bbc2959c144256167464e # v4.5.0 with: branch: gh-pages folder: microsite/build diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml index 39bf38f907..0fe84b4329 100644 --- a/.github/workflows/deploy_nightly.yml +++ b/.github/workflows/deploy_nightly.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index 369eb6d8de..72124aa363 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -138,7 +138,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index 8ef339efc7..c81447e9c0 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -10,7 +10,7 @@ jobs: if: github.repository == 'backstage/backstage' steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/pr-review-comment-trigger.yaml b/.github/workflows/pr-review-comment-trigger.yaml index 60129eee82..bfd1ffef3d 100644 --- a/.github/workflows/pr-review-comment-trigger.yaml +++ b/.github/workflows/pr-review-comment-trigger.yaml @@ -20,7 +20,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml index c121c9aec9..7d9869d378 100644 --- a/.github/workflows/pr-review-comment.yaml +++ b/.github/workflows/pr-review-comment.yaml @@ -17,13 +17,13 @@ jobs: steps: # Inspired by https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit - name: Read PR Number id: pr-number - uses: actions/github-script@v7.0.0 + uses: actions/github-script@v7.0.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index cfa0738332..6c2ffcfe77 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -18,7 +18,7 @@ jobs: if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request ) steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 64b5083bda..72bc1bff68 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -29,7 +29,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit @@ -66,6 +66,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@689fdc5193eeb735ecb2e52e819e3382876f93f4 # v2.22.6 + uses: github/codeql-action/upload-sarif@407ffafae6a767df3e0230c3df91b6443ae8df75 # v2.22.8 with: sarif_file: results.sarif diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index 2421d62211..5296dbc4c3 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/sync_dependabot-changesets.yml b/.github/workflows/sync_dependabot-changesets.yml index 7667dc167b..f61d8709a5 100644 --- a/.github/workflows/sync_dependabot-changesets.yml +++ b/.github/workflows/sync_dependabot-changesets.yml @@ -11,7 +11,7 @@ jobs: if: github.actor == 'dependabot[bot]' && github.repository == 'backstage/backstage' steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit @@ -26,7 +26,7 @@ jobs: git config --global user.email noreply@backstage.io git config --global user.name 'Github changeset workflow' - name: Generate changeset - uses: actions/github-script@v7.0.0 + uses: actions/github-script@v7.0.1 with: script: | const { promises: fs } = require('fs'); diff --git a/.github/workflows/sync_release-manifest.yml b/.github/workflows/sync_release-manifest.yml index e7d5ddc2cd..c6547e0f61 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit @@ -53,7 +53,7 @@ jobs: git push - name: Dispatch update-helper update - uses: actions/github-script@v7.0.0 + uses: actions/github-script@v7.0.1 with: github-token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} # TODO(Rugvip): Remove the create-app dispatch once we've been on the release version for a while diff --git a/.github/workflows/sync_renovate-changesets.yml b/.github/workflows/sync_renovate-changesets.yml index 7533ad9a0a..1e93a12f85 100644 --- a/.github/workflows/sync_renovate-changesets.yml +++ b/.github/workflows/sync_renovate-changesets.yml @@ -11,7 +11,7 @@ jobs: if: github.actor == 'renovate[bot]' && github.repository == 'backstage/backstage' steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit @@ -26,7 +26,7 @@ jobs: git config --global user.email noreply@backstage.io git config --global user.name 'Github changeset workflow' - name: Generate changeset - uses: actions/github-script@v7.0.0 + uses: actions/github-script@v7.0.1 with: script: | const { promises: fs } = require("fs"); diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index c030ad124a..40253188f6 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml index 07388cd47b..7b2717d34e 100644 --- a/.github/workflows/sync_snyk-monitor.yml +++ b/.github/workflows/sync_snyk-monitor.yml @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit @@ -58,6 +58,6 @@ jobs: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} NODE_OPTIONS: --max-old-space-size=7168 - name: Upload Snyk report - uses: github/codeql-action/upload-sarif@v2.22.6 + uses: github/codeql-action/upload-sarif@v2.22.8 with: sarif_file: snyk.sarif diff --git a/.github/workflows/sync_version-packages.yml b/.github/workflows/sync_version-packages.yml index 6529017198..fc1d7a68f1 100644 --- a/.github/workflows/sync_version-packages.yml +++ b/.github/workflows/sync_version-packages.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml index 883f000806..4eaf2c2dc0 100644 --- a/.github/workflows/uffizzi-build.yml +++ b/.github/workflows/uffizzi-build.yml @@ -25,7 +25,7 @@ jobs: tags: ${{ steps.meta.outputs.tags }} steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit @@ -60,13 +60,13 @@ jobs: - name: Docker metadata id: meta - uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0 + uses: docker/metadata-action@e6428a5c4e294a61438ed7f43155db912025b6b3 # v5.2.0 with: images: registry.uffizzi.com/${{ env.UUID_TAG_APP }} tags: type=raw,value=60d - name: Build Image - uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 + uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56 # v5.1.0 with: context: . file: packages/backend/Dockerfile @@ -83,7 +83,7 @@ jobs: - build-backstage steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit @@ -115,7 +115,7 @@ jobs: if: ${{ github.event.action == 'closed' }} steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/uffizzi-preview.yaml b/.github/workflows/uffizzi-preview.yaml index f37d27efd9..a9cce41fce 100644 --- a/.github/workflows/uffizzi-preview.yaml +++ b/.github/workflows/uffizzi-preview.yaml @@ -19,13 +19,13 @@ jobs: action: ${{ env.ACTION }} steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit - name: 'Download artifacts' # Fetch output (zip archive) from the workflow run that triggered this workflow. - uses: actions/github-script@v7.0.0 + uses: actions/github-script@v7.0.1 with: script: | let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ @@ -119,7 +119,7 @@ jobs: # Create/Update comment with action deployment status - name: Create or Update Comment with Deployment Notification id: notification - uses: peter-evans/create-or-update-comment@v2 + uses: peter-evans/create-or-update-comment@v3 with: comment-id: ${{ steps.find-comment.outputs.comment-id }} issue-number: ${{ needs.cache-manifests-file.outputs.pr-number }} @@ -168,7 +168,7 @@ jobs: echo "Access the \`backstage\` endpoint at [\`${BACKSTAGE_HOST}\`](http://${BACKSTAGE_HOST})" >> $GITHUB_STEP_SUMMARY - name: Create or Update Comment with Deployment URL - uses: peter-evans/create-or-update-comment@v2 + uses: peter-evans/create-or-update-comment@v3 with: comment-id: ${{ steps.notification.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} @@ -232,7 +232,7 @@ jobs: direction: last - name: Update Comment with Deletion - uses: peter-evans/create-or-update-comment@v2 + uses: peter-evans/create-or-update-comment@v3 with: comment-id: ${{ steps.find-comment.outputs.comment-id }} issue-number: ${{ needs.cache-manifests-file.outputs.pr-number }} diff --git a/.github/workflows/verify_accessibility-noop.yml b/.github/workflows/verify_accessibility-noop.yml index ab438681bb..79c9962fce 100644 --- a/.github/workflows/verify_accessibility-noop.yml +++ b/.github/workflows/verify_accessibility-noop.yml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/verify_accessibility.yml b/.github/workflows/verify_accessibility.yml index 57aec1298a..3a5582792c 100644 --- a/.github/workflows/verify_accessibility.yml +++ b/.github/workflows/verify_accessibility.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/verify_codeql.yml b/.github/workflows/verify_codeql.yml index b859e90d96..c23e45997c 100644 --- a/.github/workflows/verify_codeql.yml +++ b/.github/workflows/verify_codeql.yml @@ -42,7 +42,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit @@ -55,7 +55,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2.22.6 + uses: github/codeql-action/init@v2.22.8 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -66,7 +66,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2.22.6 + uses: github/codeql-action/autobuild@v2.22.8 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -80,4 +80,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2.22.6 + uses: github/codeql-action/analyze@v2.22.8 diff --git a/.github/workflows/verify_docs-quality.yml b/.github/workflows/verify_docs-quality.yml index 8e11a53fb7..f87c8c2d38 100644 --- a/.github/workflows/verify_docs-quality.yml +++ b/.github/workflows/verify_docs-quality.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/verify_e2e-kubernetes-noop.yml b/.github/workflows/verify_e2e-kubernetes-noop.yml index 72b1c57f19..7606f78f07 100644 --- a/.github/workflows/verify_e2e-kubernetes-noop.yml +++ b/.github/workflows/verify_e2e-kubernetes-noop.yml @@ -23,7 +23,7 @@ jobs: name: Kubernetes ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/verify_e2e-kubernetes.yml b/.github/workflows/verify_e2e-kubernetes.yml index fcc75b6264..7e4862001e 100644 --- a/.github/workflows/verify_e2e-kubernetes.yml +++ b/.github/workflows/verify_e2e-kubernetes.yml @@ -22,7 +22,7 @@ jobs: name: Kubernetes ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/verify_e2e-linux-noop.yml b/.github/workflows/verify_e2e-linux-noop.yml index b451c5d75e..c1ac6ecf89 100644 --- a/.github/workflows/verify_e2e-linux-noop.yml +++ b/.github/workflows/verify_e2e-linux-noop.yml @@ -28,7 +28,7 @@ jobs: name: E2E Linux ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index 925f593ba7..89da89889f 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -40,7 +40,7 @@ jobs: name: E2E Linux ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/verify_e2e-techdocs.yml b/.github/workflows/verify_e2e-techdocs.yml index 3b7b42e905..46070cf248 100644 --- a/.github/workflows/verify_e2e-techdocs.yml +++ b/.github/workflows/verify_e2e-techdocs.yml @@ -30,7 +30,7 @@ jobs: name: Techdocs steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/verify_e2e-windows-noop.yml b/.github/workflows/verify_e2e-windows-noop.yml index d8119f8363..e24f7820fe 100644 --- a/.github/workflows/verify_e2e-windows-noop.yml +++ b/.github/workflows/verify_e2e-windows-noop.yml @@ -25,7 +25,7 @@ jobs: name: E2E Windows ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml index cfb7014224..c0553fce3f 100644 --- a/.github/workflows/verify_e2e-windows.yml +++ b/.github/workflows/verify_e2e-windows.yml @@ -31,7 +31,7 @@ jobs: name: E2E Windows ${{ matrix.node-version }} steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/verify_fossa.yml b/.github/workflows/verify_fossa.yml index 85dbc46afa..e91a04d6ed 100644 --- a/.github/workflows/verify_fossa.yml +++ b/.github/workflows/verify_fossa.yml @@ -14,7 +14,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/verify_microsite-noop.yml b/.github/workflows/verify_microsite-noop.yml index 020ecbcfd5..ac0e397127 100644 --- a/.github/workflows/verify_microsite-noop.yml +++ b/.github/workflows/verify_microsite-noop.yml @@ -5,7 +5,6 @@ name: Microsite Void on: pull_request: paths-ignore: - - '.github/workflows/verify_microsite-next.yml' - '.github/workflows/verify_microsite.yml' - 'microsite/**' - 'mkdocs.yml' @@ -21,7 +20,7 @@ jobs: name: Microsite steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/verify_microsite.yml b/.github/workflows/verify_microsite.yml index a3be6c4c69..aef2bc333a 100644 --- a/.github/workflows/verify_microsite.yml +++ b/.github/workflows/verify_microsite.yml @@ -3,7 +3,6 @@ on: # NOTE: If you change these you must update verify_microsite-noop.yml as well pull_request: paths: - - '.github/workflows/verify_microsite-next.yml' - '.github/workflows/verify_microsite.yml' - 'microsite/**' - 'mkdocs.yml' @@ -24,7 +23,7 @@ jobs: name: Microsite steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/verify_storybook-noop.yml b/.github/workflows/verify_storybook-noop.yml index b60aa18362..3c92f0eaa2 100644 --- a/.github/workflows/verify_storybook-noop.yml +++ b/.github/workflows/verify_storybook-noop.yml @@ -28,7 +28,7 @@ jobs: name: Storybook steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index 5ebce61da2..d6f71d4ef3 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -28,7 +28,7 @@ jobs: name: Storybook steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit @@ -51,7 +51,7 @@ jobs: - run: yarn build-storybook - - uses: chromaui/action@b52e14dd333579901e7099e0094b652e8284dea9 # v1 + - uses: chromaui/action@2f12dc37555ffc9ed980d883e96b6d03724a2d6a # v1 with: token: ${{ secrets.GITHUB_TOKEN }} # projectToken intentionally shared to allow collaborators to run Chromatic on forks diff --git a/.github/workflows/verify_windows.yml b/.github/workflows/verify_windows.yml index 22d4f0af3b..9834435504 100644 --- a/.github/workflows/verify_windows.yml +++ b/.github/workflows/verify_windows.yml @@ -29,7 +29,7 @@ jobs: steps: - name: Harden Runner - uses: step-security/harden-runner@1b05615854632b887b69ae1be8cbefe72d3ae423 # v2.6.0 + uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1 with: egress-policy: audit diff --git a/.prettierignore b/.prettierignore index ad2bd355ed..c54ee5d821 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,7 +5,7 @@ coverage *.hbs templates api-report.md -*-api-report.md +api-report-*.md cli-report.md plugins/scaffolder-backend/sample-templates .vscode diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 7597dd437c..464519e792 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,3 +1,3 @@ # Community Code of Conduct -Backstage follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). +Backstage follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1261e7debc..07c2a3d96f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -113,7 +113,7 @@ If you're contributing to the backend or CLI tooling, be mindful of cross-platfo Also be sure to skim through our [ADRs](docs/architecture-decisions) to see if they cover what you're working on. In particular [ADR006: Avoid React.FC and React.SFC](docs/architecture-decisions/adr006-avoid-react-fc.md) is one to look out for. -If there are any updates in `markdown` file please make sure to run `yarn run lint:docs`. Though it is checked on `lint-staged`. It is required to install [vale](https://docs.errata.ai/vale/install) separately and make sure it is accessed by global command. +If there are any updates in `markdown` file please make sure to run `yarn run lint:docs`. Though it is checked on `lint-staged`. It is required to install [vale](https://vale.sh/docs/vale-cli/installation/) separately and make sure it is accessed by global command. ### Editor diff --git a/README.md b/README.md index 1175b4320c..3f4993658d 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,9 @@ # [Backstage](https://backstage.io) -> 🏖️ From October 30th - November 5th, employees at Spotify will have a week to recharge, which means all core maintainers & some project area maintainers are out of office. Right after that, we will go into the week of BackstageCon + KubeCon in Chicago, hoping to see some of you there! Expect slower responses & reviews during the 2 weeks, but we're on it for urgent issues. We will be up to speed again on November 13th! 🏖️ - [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![CNCF Status](https://img.shields.io/badge/cncf%20status-incubation-blue.svg)](https://www.cncf.io/projects) -[![Discord](https://img.shields.io/discord/687207715902193673)](https://discord.gg/backstage-687207715902193673) +[![Discord](https://img.shields.io/discord/687207715902193673?logo=discord&label=Discord&color=5865F2&logoColor=white)](https://discord.gg/backstage-687207715902193673) ![Code style](https://img.shields.io/badge/code_style-prettier-ff69b4.svg) [![Codecov](https://img.shields.io/codecov/c/github/backstage/backstage)](https://codecov.io/gh/backstage/backstage) [![](https://img.shields.io/github/v/release/backstage/backstage)](https://github.com/backstage/backstage/releases) diff --git a/REVIEWING.md b/REVIEWING.md index 7ed3fcda57..c443c15d77 100644 --- a/REVIEWING.md +++ b/REVIEWING.md @@ -349,3 +349,13 @@ type LabelStyle = 'normal' | 'thin'; // Output, since it's an exported constant const LABEL_SIZE: number; ``` + +## Plugin Directory Submissions + +When reviewing Plugin Directory submissions please consider the following: + +- Check to make sure they have the rights for any icon being used. This is mostly for clearly copyrighted logos, for example the Microsoft Azure DevOps logo +- Make sure the package has been published on the NPM registry. +- Make sure the package on NPM has a link back to the code repo, this helps provide confidence that it's the right package. +- If they use an [NPM scope](https://docs.npmjs.com/about-scopes) make sure it that matches either the Organization name or user name, this provides trust in the plugin +- If the plugin has both a frontend and backend make sure that the documentation notes that. diff --git a/contrib/.devcontainer/Dockerfile b/contrib/.devcontainer/Dockerfile index 35459b8d97..6407aa26dd 100644 --- a/contrib/.devcontainer/Dockerfile +++ b/contrib/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/devcontainers/typescript-node:18 +FROM mcr.microsoft.com/devcontainers/typescript-node:20 RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ && apt-get -y install chromium \ diff --git a/contrib/chart/backstage/Chart.lock b/contrib/chart/backstage/Chart.lock index 6220a481dd..c835a4dcd1 100644 --- a/contrib/chart/backstage/Chart.lock +++ b/contrib/chart/backstage/Chart.lock @@ -1,6 +1,6 @@ dependencies: - name: postgresql repository: https://charts.bitnami.com/bitnami - version: 9.8.12 -digest: sha256:549b9a0cdf7b2e0ad949ebad853a467bf320928970a946fb0ef7e13e9bdb7a10 -generated: "2022-05-20T08:15:48.301491565Z" + version: 13.2.21 +digest: sha256:8f8b0fe6c2e8f640237f61dcfab5821865d67753af06a782db7d61372cbbb9b9 +generated: "2023-11-27T22:30:42.837126565Z" diff --git a/contrib/chart/backstage/Chart.yaml b/contrib/chart/backstage/Chart.yaml index 9770ef665c..efd84f1d38 100644 --- a/contrib/chart/backstage/Chart.yaml +++ b/contrib/chart/backstage/Chart.yaml @@ -18,7 +18,7 @@ sources: dependencies: - name: postgresql condition: postgresql.enabled - version: 9.8.12 + version: 13.2.21 repository: https://charts.bitnami.com/bitnami maintainers: diff --git a/docs/auth/identity-resolver.md b/docs/auth/identity-resolver.md index a65f3d7899..0a626ef175 100644 --- a/docs/auth/identity-resolver.md +++ b/docs/auth/identity-resolver.md @@ -236,6 +236,12 @@ export default async function createPlugin( // an entity you will need to replace this step as well. // // You might also replace it if you for example want to filter out certain groups. + // + // Note that `getDefaultOwnershipEntityRefs` only includes groups to which the + // user has a direct MEMBER_OF relationship. It's perfectly fine to include + // groups that the user is transitively part of in the claims array, but the + // catalog doesn't currently provide a direct way of accessing this list of + // groups. const ownershipRefs = getDefaultOwnershipEntityRefs(entity); // The last step is to issue the token, where we might provide more options in the future. diff --git a/docs/backend-system/architecture/06-modules.md b/docs/backend-system/architecture/06-modules.md index e916e4fdf6..b15c873c39 100644 --- a/docs/backend-system/architecture/06-modules.md +++ b/docs/backend-system/architecture/06-modules.md @@ -25,8 +25,8 @@ import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node' import { MyCustomProcessor } from './MyCustomProcessor'; export const catalogModuleExampleCustomProcessor = createBackendModule({ - moduleId: 'exampleCustomProcessor', pluginId: 'catalog', + moduleId: 'example-custom-processor', register(env) { env.registerInit({ deps: { diff --git a/docs/backend-system/architecture/07-naming-patterns.md b/docs/backend-system/architecture/07-naming-patterns.md index 3e57fa6863..9af1e09a27 100644 --- a/docs/backend-system/architecture/07-naming-patterns.md +++ b/docs/backend-system/architecture/07-naming-patterns.md @@ -10,18 +10,20 @@ description: Naming patterns in the backend system These are the naming patterns to adhere to within the backend system. They help us keep exports consistent across packages and make it easier to understand the usage and intent of exports. +As a rule, all names should be camel case, with the exceptions of plugin and module IDs, which should be kebab case. + ### Plugins -| Description | Pattern | Examples | -| ----------- | ------------ | ----------------------------------- | -| export | `Plugin` | `catalogPlugin`, `scaffolderPlugin` | -| ID | `''` | `'catalog'`, `'scaffolder'` | +| Description | Pattern | Examples | +| ----------- | ----------------- | ------------------------------------- | +| export | `Plugin` | `catalogPlugin`, `userSettingsPlugin` | +| ID | `''` | `'catalog'`, `'user-settings'` | Example: ```ts -export const catalogPlugin = createBackendPlugin({ - pluginId: 'catalog', +export const userSettingsPlugin = createBackendPlugin({ + pluginId: 'user-settings', ... }) ``` @@ -31,14 +33,14 @@ export const catalogPlugin = createBackendPlugin({ | Description | Pattern | Examples | | ----------- | ---------------------------- | ----------------------------------- | | export | `Module` | `catalogModuleGithubEntityProvider` | -| ID | `''` | `'githubEntityProvider'` | +| ID | `''` | `'github-entity-provider'` | Example: ```ts export const catalogModuleGithubEntityProvider = createBackendModule({ pluginId: 'catalog', - moduleId: 'githubEntityProvider', + moduleId: 'github-entity-provider', ... }) ``` diff --git a/docs/backend-system/building-backends/08-migrating.md b/docs/backend-system/building-backends/08-migrating.md index 54b293fae3..4f6575c805 100644 --- a/docs/backend-system/building-backends/08-migrating.md +++ b/docs/backend-system/building-backends/08-migrating.md @@ -547,7 +547,7 @@ import { microsoftGraphOrgEntityProviderTransformExtensionPoint } from '@backsta backend.add( createBackendModule({ pluginId: 'catalog', - moduleId: 'microsoftGraphTransformers', + moduleId: 'microsoft-graph-extensions', register(env) { env.registerInit({ deps: { @@ -580,21 +580,21 @@ depends on the appropriate extension point and interacts with it. ```ts title="packages/backend/src/index.ts" /* highlight-add-start */ -import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node'; +import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { createBackendModule } from '@backstage/backend-plugin-api'; /* highlight-add-end */ /* highlight-add-start */ const catalogModuleCustomExtensions = createBackendModule({ pluginId: 'catalog', // name of the plugin that the module is targeting - moduleId: 'customExtensions', + moduleId: 'custom-extensions', register(env) { env.registerInit({ deps: { catalog: catalogProcessingExtensionPoint, // ... and other dependencies as needed }, - init({ catalog /* ..., other dependencies */ }) { + async init({ catalog /* ..., other dependencies */ }) { // Here you have the opportunity to interact with the extension // point before the plugin itself gets instantiated catalog.addEntityProvider(new MyEntityProvider()); // just an example @@ -649,21 +649,21 @@ depends on the appropriate extension point and interacts with it. ```ts title="packages/backend/src/index.ts" /* highlight-add-start */ -import { eventsExtensionPoint } from '@backstage/plugin-events-node'; +import { eventsExtensionPoint } from '@backstage/plugin-events-node/alpha'; import { createBackendModule } from '@backstage/backend-plugin-api'; /* highlight-add-end */ /* highlight-add-start */ const eventsModuleCustomExtensions = createBackendModule({ pluginId: 'events', // name of the plugin that the module is targeting - moduleId: 'customExtensions', + moduleId: 'custom-extensions', register(env) { env.registerInit({ deps: { events: eventsExtensionPoint, // ... and other dependencies as needed }, - init({ events /* ..., other dependencies */ }) { + async init({ events /* ..., other dependencies */ }) { // Here you have the opportunity to interact with the extension // point before the plugin itself gets instantiated events.addSubscribers(new MySubscriber()); // just an example @@ -714,21 +714,21 @@ depends on the appropriate extension point and interacts with it. ```ts title="packages/backend/src/index.ts" /* highlight-add-start */ -import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node'; +import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha'; import { createBackendModule } from '@backstage/backend-plugin-api'; /* highlight-add-end */ /* highlight-add-start */ const scaffolderModuleCustomExtensions = createBackendModule({ pluginId: 'scaffolder', // name of the plugin that the module is targeting - moduleId: 'customExtensions', + moduleId: 'custom-extensions', register(env) { env.registerInit({ deps: { scaffolder: scaffolderActionsExtensionPoint, // ... and other dependencies as needed }, - init({ scaffolder /* ..., other dependencies */ }) { + async init({ scaffolder /* ..., other dependencies */ }) { // Here you have the opportunity to interact with the extension // point before the plugin itself gets instantiated scaffolder.addActions(new MyAction()); // just an example diff --git a/docs/backend-system/building-plugins-and-modules/01-index.md b/docs/backend-system/building-plugins-and-modules/01-index.md index 7d97694aec..0f12e81a8c 100644 --- a/docs/backend-system/building-plugins-and-modules/01-index.md +++ b/docs/backend-system/building-plugins-and-modules/01-index.md @@ -104,8 +104,8 @@ import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node' import { MyCustomProcessor } from './MyCustomProcessor'; export const catalogModuleExampleCustomProcessor = createBackendModule({ - moduleId: 'exampleCustomProcessor', pluginId: 'catalog', + moduleId: 'example-custom-processor', register(env) { env.registerInit({ deps: { diff --git a/docs/backend-system/building-plugins-and-modules/08-migrating.md b/docs/backend-system/building-plugins-and-modules/08-migrating.md index 067ab02b4d..cc920c576e 100644 --- a/docs/backend-system/building-plugins-and-modules/08-migrating.md +++ b/docs/backend-system/building-plugins-and-modules/08-migrating.md @@ -73,30 +73,99 @@ export const kubernetesPlugin = createBackendPlugin({ }); ``` -Done! Users of this plugin are now able to import the `kubernetesPlugin` and register it in their backend using +Lastly, make sure you re-export the plugin instance as the default export of your package in `src/index.ts`: + +```ts +export { kubernetesPlugin as default } from './plugin.ts'; +``` + +Done! Users of this plugin are now able to import your plugin package and register it in their backend using ```ts // packages/backend/src/index.ts -import { kubernetesPlugin } from '@backstage/plugin-kubernetes-backend'; -backend.add(kubernetesPlugin); +backend.add(import('@backstage/plugin-kubernetes-backend')); ``` There's one thing missing that those sharp eyed readers might have noticed: the `clusterSupplier` option is missing from the original plugin. Let's add it and discuss the alternatives. -One alternative is to pass the `ClusterSupplier` in as options to the plugin, which is quick and easy but not very flexible, and also hard to evolve without introducing breaking changes as it changes the public API for the plugin. Having complex types passed in directly to the plugin also clutters the backend setup code and makes it harder to read. - -Options are primarily used for simple configuration values that are not complex types. In this case we want to allow users to register their own `ClusterSupplier` implementations to the plugin. This is where the new backend system's [extension points](../architecture/05-extension-points.md) come in handy, but let's look at doing this with options first. +One alternative is to make it possible to build the cluster supplier using static configuration. It could for example be that there is a selection of built-in implementations to choose from, or that the logic for how the `ClusterSupplier` is supposed to function is all determined by configuration, or a combination of the two. Using static configuration for customization is always the preferred option whenever it's possible. In this case, we could for example imagine that we would be able to configure our cluster supplier like this: ```ts /* omitted imports but they remain the same as above */ -export interface KubernetesOptions { - clusterSupplier?: KubernetesClustersSupplier; -} - -const kubernetesPlugin = createBackendPlugin((options: KubernetesOptions) => ({ +const kubernetesPlugin = createBackendPlugin({ pluginId: 'kubernetes', register(env) { + env.registerInit({ + deps: { + /* omitted dependencies but they remain the same as above */ + }, + async init({ config, logger, catalogApi, discovery, http }) { + // Note that in a real implementation this would be done by the `KubernetesBuilder` instead, + // but here we've extracted it into a separate call to highlight the example. + const configuredClusterSupplier = readClusterSupplierFromConfig(config); + + const { router } = await KubernetesBuilder.createBuilder({ + config, + logger, + catalogApi, + discovery, + }) + .setClusterSupplier(configuredClusterSupplier) + .build(); + http.use(router); + }, + }); + }, +}); +``` + +There are however many types of customizations that are not possible to do with static configuration. In this case we want integrators to be able to create arbitrary implementations of the `ClusterSupplier` interface, which in the end requires an implementation through code. This is where the new backend system's [extension points](../architecture/05-extension-points.md) come in handy. + +The new [extension points](../architecture/05-extension-points.md) API allows [modules](../architecture/06-modules.md) to add functionality into the backend plugin itself, in this case an additional `ClusterSupplier`. Let's look at how we could add support for installing custom suppliers using an extension point. This will allow integrators to build their own internal module with a custom `ClusterSupplier` implementation. + +First we'll go ahead and create a `@backstage/plugin-kubernetes-node` package where we can define our extension point. A separate package is used to avoid direct dependencies on the plugin package itself. With the new package created, we define the extension point like this: + +```ts +import { createExtensionPoint } from '@backstage/backend-plugin-api'; + +export interface KubernetesClusterSupplierExtensionPoint { + setClusterSupplier(supplier: KubernetesClustersSupplier): void; +} + +/** + * An extension point that allows other plugins to set the cluster supplier. + */ +export const kubernetesClustersSupplierExtensionPoint = + createExtensionPoint({ + id: 'kubernetes.cluster-supplier', + }); +``` + +For more information on how to design extension points, see the [extension points](../architecture/05-extension-points.md#extension-point-design) documentation. + +Next we'll need to add support for this extension point to the Kubernetes backend plugin itself: + +```ts +/* omitted other imports but they remain the same as above */ +import { kubernetesClustersSupplierExtensionPoint } from '@backstage/plugin-kubernetes-node'; + +export const kubernetesPlugin = createBackendPlugin({ + pluginId: 'kubernetes', + register(env) { + let clusterSupplier: KubernetesClustersSupplier | undefined = undefined; + + // We register the extension point with the backend, which allows modules to + // register their own ClusterSupplier. + env.registerExtensionPoint(kubernetesClustersSupplierExtensionPoint, { + setClusterSupplier(supplier) { + if (clusterSupplier) { + throw new Error('ClusterSupplier may only be set once'); + } + clusterSupplier = supplier; + }, + }); + env.registerInit({ deps: { /* omitted dependencies but they remain the same as above */ @@ -108,103 +177,7 @@ const kubernetesPlugin = createBackendPlugin((options: KubernetesOptions) => ({ catalogApi, discovery, }) - .setClusterSupplier(options.clusterSupplier) - .build(); - http.use(router); - }, - }); - }, -})); -``` - -The above would allow users to specify their own `ClusterSupplier` implementation to the plugin like this: - -```ts -backend.add( - kubernetesPlugin({ clusterSupplier: new MyCustomClusterSupplier() }), -); -``` - -Just to echo what was said above, this is not a very flexible solution and will for example be problematic to keep backwards compatible if we start evolving the options to for example accept multiple suppliers or tweak the `ClusterSupplier` interface. - -The new [extension points](../architecture/05-extension-points.md) API allows [modules](../architecture/06-modules.md) to add functionality into the backend plugin itself, in this case an additional `ClusterSupplier`. - -The kubernetes backend plugin only supports one `ClusterSupplier` at this time but let's look at how we could add support for multiple suppliers using extension points. This allows users to install several modules that add their own `ClusterSupplier` implementations to the plugin like this: - -```ts -backend.add(kubernetesPlugin()); -backend.add(kubernetesGoogleContainerEngineClusterSupplier()); -backend.add(kubernetesElasticContainerEngine()); -``` - -Now let's look at how to implement this with extension points. First we need to define the extension point itself. As the extension point will be used by other modules, it's common practice to export these from a shared package so that they can be imported by other modules and plugins. - -We'll go ahead and create a `@backstage/plugin-kubernetes-node` package for this and from there we'll export the extension point. - -```ts -import { createExtensionPoint } from '@backstage/backend-plugin-api'; - -export interface KubernetesClusterSupplierExtensionPoint { - addClusterSupplier(supplier: KubernetesClustersSupplier): void; -} - -/** - * An extension point that allows other plugins to add cluster suppliers. - * @public - */ -export const kubernetesClustersSupplierExtensionPoint = - createExtensionPoint({ - id: 'kubernetes.cluster-supplier', - }); -``` - -Now we can use this extension point in the kubernetes backend plugin to register the extension point for modules to use. - -```ts -import { kubernetesClustersSupplierExtensionPoint, KubernetesClusterSupplierExtensionPoint } from '@backstage/plugin-kubernetes-node'; - -// Our internal implementation of the extension point, should not be exported. -class ClusterSupplier implements KubernetesClusterSupplierExtensionPoint { - private clusterSuppliers: KubernetesClustersSupplier | undefined; - - // This method is private and only used internally to retrieve the registered supplier. - getClusterSupplier() { - return this.clusterSuppliers; - } - - addClusterSupplier(supplier: KubernetesClustersSupplier) { - // We can remove this check once the plugin support multiple suppliers. - if(this.clusterSuppliers) { - throw new Error('Multiple Kubernetes cluster suppliers is not supported at this time'); - } - this.clusterSuppliers = supplier; - } -} - -export const kubernetesPlugin = createBackendPlugin({ - pluginId: 'kubernetes', - register(env) { - const extensionPoint = new ClusterSupplier(); - // We register the extension point with the backend, which allows modules to - // register their own ClusterSupplier. - env.registerExtensionPoint( - kubernetesClustersSupplierExtensionPoint, - extensionPoint, - ); - - env.registerInit({ - deps: { - ... omitted ... - }, - async init({ config, logger, catalogApi, discovery, http }) { - const { router } = await KubernetesBuilder.createBuilder({ - config, - logger, - catalogApi, - discovery, - }) - // We pass in the registered supplier from the extension point. - .setClusterSupplier(extensionPoint.getClusterSupplier()) + .setClusterSupplier(clusterSupplier) .build(); http.use(router); }, @@ -213,24 +186,33 @@ export const kubernetesPlugin = createBackendPlugin({ }); ``` -And that's it! Modules can now be built that add clusters into to the kubernetes backend plugin, here's an example of a module that adds a `GoogleContainerEngineSupplier` to the kubernetes backend. +And that's it! Modules can now be built that add clusters into to the kubernetes backend plugin, here's an example of a module that adds a `GoogleContainerEngineSupplier` to the kubernetes backend: ```ts import { kubernetesClustersSupplierExtensionPoint } from '@backstage/plugin-kubernetes-node'; -export const kubernetesGoogleContainerEngineClusterSupplier = - createBackendModule({ - pluginId: 'kubernetes', - moduleId: 'gke.supplier', - register(env) { - env.registerInit({ - deps: { - supplier: kubernetesClustersSupplierExtensionPoint, - }, - async init({ supplier }) { - supplier.addClusterSupplier(new GoogleContainerEngineSupplier()); - }, - }); - }, - }); +// This is a custom implementation of the ClusterSupplier interface. +import { GoogleContainerEngineSupplier } from './GoogleContainerEngineSupplier'; + +export default createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'gke-supplier', + register(env) { + env.registerInit({ + deps: { + supplier: kubernetesClustersSupplierExtensionPoint, + }, + async init({ supplier }) { + supplier.setClusterSupplier(new GoogleContainerEngineSupplier()); + }, + }); + }, +}); +``` + +The above module can then be installed by the integrator alongside the kubernetes backend plugin: + +```ts +backend.add(import('@backstage/plugin-kubernetes-backend')); +backend.add(import('@internal/gke-cluster-supplier')); ``` diff --git a/docs/features/software-catalog/api.md b/docs/features/software-catalog/api.md index 3ccd89b286..97d43209d6 100644 --- a/docs/features/software-catalog/api.md +++ b/docs/features/software-catalog/api.md @@ -31,8 +31,8 @@ with a `Bearer` token, which should then be the Backstage token returned by the These are the endpoints that deal with reading of entities directly. What it exposes are final entities - i.e. the output of all processing and the stitching -process, not the raw originally ingested entity data. See [The Life of an -Entity](life-of-an-entity.md) for more details about this process and +process, not the raw originally ingested entity data. See +[The Life of an Entity](./life-of-an-entity.md) for more details about this process and distinction. ### `GET /entities` diff --git a/docs/features/software-templates/adding-templates.md b/docs/features/software-templates/adding-templates.md index 7254a56d6c..6396d7530a 100644 --- a/docs/features/software-templates/adding-templates.md +++ b/docs/features/software-templates/adding-templates.md @@ -114,6 +114,6 @@ configured differently should be running on `/catalog-import`. For information about writing your own templates, you can check out the docs [here](./writing-templates.md) -If you are looking for a method to discover templates without the need for manual ingestion, there are several options available. One approach is to utilize Discovery providers, such as [GitHub Discovery](https://backstage.io/docs/integrations/github/discover). +If you are looking for a method to discover templates without the need for manual ingestion, there are several options available. One approach is to utilize Discovery providers, such as [GitHub Discovery](https://backstage.io/docs/integrations/github/discovery). Alternatively, you can choose to set up an external integration. This involves connecting your system to external sources or platforms that may host templates relevant to your needs, as mentioned in [External Integration](https://backstage.io/docs/features/software-catalog/external-integrations/). diff --git a/docs/features/techdocs/cli.md b/docs/features/techdocs/cli.md index 9704b9b21b..c824eb7d7d 100644 --- a/docs/features/techdocs/cli.md +++ b/docs/features/techdocs/cli.md @@ -91,6 +91,9 @@ Options: --docker-option Extra options to pass to the docker run command, e.g. "--add-host=internal.host:192.168.11.12" (can be added multiple times). --no-docker Do not use Docker, use MkDocs executable in current user environment. + --mkdocs-parameter-clean Pass "--clean" parameter to mkdocs server running in containerized environment. + --mkdocs-parameter-dirtyreload Pass "--dirtyreload" parameter to mkdocs server running in containerized environment. + --mkdocs-parameter-strict Pass "--strict" parameter to mkdocs server running in containerized environment. --mkdocs-port Port for MkDocs server to use (default: "8000") --preview-app-bundle-path Preview documentation using a web app other than the included one. --preview-app-port Port where the preview will be served. @@ -147,6 +150,7 @@ Options: Defaults to false, which means that the techdocs-core plugin is always added to the mkdocs file. --legacyCopyReadmeMdToIndexMd Attempt to ensure an index.md exists falling back to using /README.md or README.md in case a default /index.md is not provided. (default: false) + --runAsDefaultUser Bypass setting the container user as the same user and group id as host for Linux and MacOS (default: false) -v --verbose Enable verbose output. (default: false) -h, --help display help for command ``` diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index 29f985904f..afc257f20b 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -504,6 +504,18 @@ folder (/docs) or replace the content in this file. Done! You now have support for TechDocs in your own software template! +### Prevent download of Google fonts + +If your Backstage instance does not have internet access, the generation will fail. TechDocs tries to download the Roboto font from Google. You can disable it by adding the following lines to mkdocs.yaml: + +```yaml +theme: + name: material + font: false +``` + +> Note: The addition `name: material` is necessary. Otherwise it will not work + ## How to enable iframes in TechDocs TechDocs uses the [DOMPurify](https://github.com/cure53/DOMPurify) library to diff --git a/docs/getting-started/app-custom-theme.md b/docs/getting-started/app-custom-theme.md index 3b042d5eb4..d6a13ca6e3 100644 --- a/docs/getting-started/app-custom-theme.md +++ b/docs/getting-started/app-custom-theme.md @@ -484,3 +484,7 @@ You can see more ways to use this in the [Storybook Sidebar examples](https://ba In addition to a custom theme, a custom logo, you can also customize the homepage of your app. Read the full guide on the [next page](homepage.md). + +## Migrating to Material UI v5 + +We now support Material UI v5 in Backstage. Check out our [migration guide](../tutorials/migrate-to-mui5.md) to get started. diff --git a/docs/getting-started/configuration.md b/docs/getting-started/configuration.md index 17f07811c0..b7bf7d448d 100644 --- a/docs/getting-started/configuration.md +++ b/docs/getting-started/configuration.md @@ -290,6 +290,11 @@ otherwise something went terribly wrong. ## Create a new component using a software template +> Note: if you're running Backstage with Node 20 or later, you'll need to pass the flag `--no-node-snapshot` to Node in order to +> use the templates feature. +> One way to do this is to specify the `NODE_OPTIONS` environment variable before starting Backstage: +> `export NODE_OPTIONS=--no-node-snapshot` + - Go to `create` and choose to create a website with the `Example Node.js Template` - Type in a name, let's use `tutorial` and click `Next Step` diff --git a/docs/getting-started/configure-app-with-plugins.md b/docs/getting-started/configure-app-with-plugins.md index b44f7877a7..5611117636 100644 --- a/docs/getting-started/configure-app-with-plugins.md +++ b/docs/getting-started/configure-app-with-plugins.md @@ -15,7 +15,7 @@ The following steps assume that you have to it. We are using the -[CircleCI](https://github.com/backstage/backstage/blob/master/plugins/circleci/README.md) +[CircleCI](https://github.com/CircleCI-Public/backstage-plugin/tree/main/plugins/circleci) plugin in this example, which is designed to show CI/CD pipeline information attached to an entity in the software catalog. @@ -23,7 +23,7 @@ to an entity in the software catalog. ```bash # From your Backstage root directory - yarn add --cwd packages/app @backstage/plugin-circleci + yarn add --cwd packages/app @circleci/backstage-plugin ``` Note the plugin is added to the `app` package, rather than the root @@ -38,7 +38,7 @@ to an entity in the software catalog. import { EntityCircleCIContent, isCircleCIAvailable, - } from '@backstage/plugin-circleci'; + } from '@circleci/backstage-plugin'; /* highlight-add-end */ const cicdContent = ( diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index 7bb4918d47..51c328c871 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -295,7 +295,8 @@ Webpack configuration itself varies very little between the frontend development and production bundling, so we'll dive more into the configuration in the production section below. The main differences are that `process.env.NODE_ENV` is set to `'development'`, minification is disabled, cheap source maps are used, -and [React Hot Loader](https://github.com/gaearon/react-hot-loader) is enabled. +and [React Refresh](https://github.com/pmmmwh/react-refresh-webpack-plugin#readme) +is enabled. If you prefer to run type checking and linting as part of the Webpack process, you can enable usage of the @@ -589,22 +590,25 @@ For your productivity working with unit tests it's quite essential to have your A complete launch configuration for VS Code debugging may look like this: -```json +```jsonc { "type": "node", - "name": "vscode-jest-tests", + "name": "vscode-jest-tests.v2", "request": "launch", + "args": [ + "repo", + "test", + "--runInBand", + "--watchAll=false", + "--testNamePattern", + "${jest.testNamePattern}", + "--runTestsByPath", + "${jest.testFile}" + ], "console": "integratedTerminal", "internalConsoleOptions": "neverOpen", "disableOptimisticBPs": true, - "program": "${workspaceFolder}/node_modules/.bin/jest", - "cwd": "${workspaceFolder}", - "args": [ - "--config", - "node_modules/@backstage/cli/config/jest.js", - "--runInBand", - "--watchAll=false" - ] + "program": "${workspaceFolder}/node_modules/.bin/backstage-cli" } ``` diff --git a/docs/local-dev/debugging.md b/docs/local-dev/debugging.md index d2a4d02db0..17a98b1c1c 100644 --- a/docs/local-dev/debugging.md +++ b/docs/local-dev/debugging.md @@ -47,3 +47,27 @@ The resulting log should now have more information available for debugging: [1] 2023-04-12T00:51:44.118Z search info Collating documents for tools succeeded type=plugin documentType=tools [1] 2023-04-12T00:51:44.119Z backstage debug task: search_index_tools will next occur around 2023-04-11T21:01:44.118-04:00 type=taskManager task=search_index_tools ``` + +## Debugger + +### VSCode + +In your `launch.json`, add a new entry with the following, + +```jsonc +{ + "name": "Start Backend", + "type": "node", + "request": "launch", + "args": [ + "package", + "start" + ], + "cwd": "${workspaceFolder}/packages/backend", + "program": "${workspaceFolder}/node_modules/.bin/backstage-cli", + "skipFiles": [ + "/**" + ], + "console": "integratedTerminal" +}, +``` diff --git a/docs/openapi/generate-client.md b/docs/openapi/generate-client.md new file mode 100644 index 0000000000..10e6ec3b2f --- /dev/null +++ b/docs/openapi/generate-client.md @@ -0,0 +1,25 @@ +## How to generate a client with `repo-tools schema openapi generate-client`? + +### Prerequisites + +1. Add your plugin ID as the last `servers` item, like this, + +```yaml +servers: + # first value, used for OpenAPI router validation. + - url: / + + # final value, pluginId. + - url: catalog +``` + +2. Find or create a new plugin to house your new generated client. Currently, we do not support generating an entirely new plugin and instead just generate client files. + +### Generating your client + +1. Run `yarn backstage-repo-tools schema openapi generate-client --input-spec --output-directory `. This will create a new folder in `/src/generated` to house the generated content. +2. You should use the generated files as follows, + +- `apis/DefaultApi.client.ts` - this is the client that you should use. It has types for all of the various operations on your API. +- `models/*` - These are the types generated from your OpenAPI file, ideally you should not need to use these directly and can instead use the inferred types from `apis/DefaultApi.client.ts`. +- everything else is directory specific and shouldn't be touched. diff --git a/docs/plugins/add-to-directory.md b/docs/plugins/add-to-directory.md index dfa43c2ed7..8be0d764dd 100644 --- a/docs/plugins/add-to-directory.md +++ b/docs/plugins/add-to-directory.md @@ -21,7 +21,18 @@ description: A brief description of the plugin. # Max 170 characters documentation: # A link to your documentation E.g. Your github README iconUrl: # Used as the src attribute for your logo. # You can provide an external url or add your logo under static/img and provide a path -# relative to static/ e.g. img/my-logo.png +# relative to static/ e.g. /img/my-logo.png npmPackageName: # Your npm package name E.g. '@backstage/plugin-' quotes are required addedDate: # The date plugin added to directory E.g. '2022-10-01' quotes are required ``` + +## Submission Tips + +Here are a few tips to help speed up the review process when you submit your plugin: + +- For any icon that you use make sure you have the proper rights to use it. +- Make sure that your package had been published on the NPM registry and that it's public. +- Make sure your package on NPM has a link back to your code repo, this helps provide confidence that it's the right package. +- Where possible, please use an [NPM scope](https://docs.npmjs.com/about-scopes) that matches either your Organization name or user name, this provides trust in the plugin +- If your plugin has both a frontend and backend link the documentation to the frontend package but make sure it mentioned needing to install the backend package. +- Where possible include a screenshot of the features in you plugin documentation, it really does help when deciding to use a plugin. diff --git a/docs/plugins/internationalization.md b/docs/plugins/internationalization.md index 78b7de6342..13bb098262 100644 --- a/docs/plugins/internationalization.md +++ b/docs/plugins/internationalization.md @@ -10,7 +10,7 @@ The Backstage core function provides internationalization for plugins ## For a plugin developer -When you are creating your plugin, you have the possibility to use `createTranslationRef` to define all messages for your plugin. For example +When you are creating your plugin, you have the possibility to use `createTranslationRef` to define all messages for your plugin. For example: ```ts import { createTranslationRef } from '@backstage/core-plugin-api/alpha'; @@ -19,8 +19,13 @@ import { createTranslationRef } from '@backstage/core-plugin-api/alpha'; export const myPluginTranslationRef = createTranslationRef({ id: 'plugin.my-plugin', messages: { - index_page_title: 'All your components', - create_component_button_label: 'Create new component', + indexPage: { + title: 'All your components', + createButtonTitle: 'Create new component', + }, + entityPage: { + notFound: 'Entity not found', + }, }, }); ``` @@ -33,9 +38,9 @@ import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; const { t } = useTranslationRef(myPluginTranslationRef); return ( - + ); @@ -53,7 +58,7 @@ In an app you can both override the default messages, as well as register transl + createTranslationMessages({ + ref: myPluginTranslationRef, + messages: { -+ create_component_button_label: 'Create new entity', ++ 'indexPage.createButtonTitle': 'Create new entity', + }, + }), + createTranslationResource({ diff --git a/docs/plugins/new-backend-system.md b/docs/plugins/new-backend-system.md index be27e9427d..b2c73af33b 100644 --- a/docs/plugins/new-backend-system.md +++ b/docs/plugins/new-backend-system.md @@ -147,8 +147,8 @@ import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node' import { MyCustomProcessor } from './processor'; export const exampleCustomProcessorCatalogModule = createBackendModule({ - moduleId: 'exampleCustomProcessor', pluginId: 'catalog', + moduleId: 'example-custom-processor', register(env) { env.registerInit({ deps: { diff --git a/docs/releases/v1.21.0-next.0-changelog.md b/docs/releases/v1.21.0-next.0-changelog.md new file mode 100644 index 0000000000..a306e4158b --- /dev/null +++ b/docs/releases/v1.21.0-next.0-changelog.md @@ -0,0 +1,3058 @@ +# Release v1.21.0-next.0 + +## @backstage/backend-common@0.20.0-next.0 + +### Minor Changes + +- 870db76a45: Implemented `readTree` for Gitea provider to support TechDocs functionality + +### Patch Changes + +- 7f04128bbc: Allow a default cache TTL to be set through the app config +- 1ad8906a9e: Use `Readable.from` to fix some of the stream issues +- 706fc3a7e1: Updated dependency `@kubernetes/client-node` to `0.20.0`. +- d15d483a49: Add command `--runAsDefaultUser` for `@techdocs/cli generate` to bypass running the docker builds as host user for macOS and Linux. +- d1e00aa17a: Expose an `onAuth` handler for `git` actions to provide custom credentials +- Updated dependencies + - @backstage/integration@1.8.0-next.0 + - @backstage/backend-app-api@0.5.9-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/backend-dev-utils@0.1.2 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + +## @backstage/frontend-test-utils@0.1.0-next.0 + +### Minor Changes + +- 59fabd5106: New testing utility library for `@backstage/frontend-app-api` and `@backstage/frontend-plugin-api`. + +### Patch Changes + +- 59fabd5106: Added `createExtensionTester` for rendering extensions in tests. +- Updated dependencies + - @backstage/frontend-app-api@0.3.1-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/test-utils@1.4.6-next.0 + - @backstage/types@1.1.1 + +## @backstage/integration@1.8.0-next.0 + +### Minor Changes + +- 870db76a45: Implemented `readTree` for Gitea provider to support TechDocs functionality + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + +## @techdocs/cli@1.8.0-next.0 + +### Minor Changes + +- d15d483a49: Add command `--runAsDefaultUser` for `@techdocs/cli generate` to bypass running the docker builds as host user for macOS and Linux. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-techdocs-node@1.11.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + +## @backstage/theme@0.5.0-next.0 + +### Minor Changes + +- 4d9e3b39e4: Added a global `OverrideComponentNameToClassKeys` for other plugins and packages to populate using module augmentation. This will in turn will provide component style override types for `createUnifiedTheme`. + +## @backstage/plugin-auth-backend-module-atlassian-provider@0.1.0-next.0 + +### Minor Changes + +- 2a5891e816: New module for `@backstage/plugin-auth-backend` that adds an atlassian auth provider + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + +## @backstage/plugin-catalog@1.16.0-next.0 + +### Minor Changes + +- b8e1eb2c0f: The `columns` prop can be an array or a function that returns an array in order to override the default columns of the `CatalogIndexPage`. + +### Patch Changes + +- bc7e6d3eb9: Fix copy entity url function in http contexts. + +- cd910c4fa5: - Fixes bug where after unregistering an entity you are redirected to `/`. + + - Adds an optional external route `unregisterRedirect` to override this behaviour to another route. + +- 03d0b6dcdc: The `convertLegacyRouteRef` utility used by the alpha exports is now imported from `@backstage/core-compat-api`. + +- 4d9e3b39e4: Register component overrides in the global `OverrideComponentNameToClassKeys` provided by `@backstage/theme`. This will in turn will provide component style override types for `createUnifiedTheme`. + +- 8587f067d2: Added pagination support to `CatalogIndexPage` + + `CatalogIndexPage` now offers an optional pagination feature, designed to accommodate adopters managing extensive catalogs. This new capability allows for better handling of large amounts of data. + + To activate the pagination mode, simply update your `App.tsx` as follows: + + ```diff + const routes = ( + + ... + - } /> + + } /> + ... + ``` + + In case you have a custom catalog page and you want to enable pagination, you need to pass the `pagination` prop to `EntityListProvider` instead. + +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-scaffolder-common@1.4.3 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-kubernetes-backend@0.14.0-next.0 + +### Minor Changes + +- 52050ada6e: You can now select `single` kubernetes cluster that the entity is part-of from all your defined kubernetes clusters, by passing `backstage.io/kubernetes-cluster` annotation with the defined cluster name. + + If you do not specify the annotation by `default it fetches all` defined kubernetes cluster. + + To apply + + catalog-info.yaml + + ```diff + annotations: + 'backstage.io/kubernetes-id': dice-roller + 'backstage.io/kubernetes-namespace': dice-space + + 'backstage.io/kubernetes-cluster': dice-cluster + 'backstage.io/kubernetes-label-selector': 'app=my-app,component=front-end' + ``` + +### Patch Changes + +- 706fc3a7e1: Updated dependency `@kubernetes/client-node` to `0.20.0`. +- 42c1aee741: Updated dependency `@google-cloud/container` to `^5.0.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-kubernetes-common@0.7.2-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + - @backstage/plugin-kubernetes-node@0.1.2-next.0 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-techdocs-node@1.11.0-next.0 + +### Minor Changes + +- d15d483a49: Add command `--runAsDefaultUser` for `@techdocs/cli generate` to bypass running the docker builds as host user for macOS and Linux. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/app-defaults@1.4.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + +## @backstage/backend-app-api@0.5.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/backend-defaults@0.2.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-app-api@0.5.9-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + +## @backstage/backend-openapi-utils@0.1.1-next.0 + +### Patch Changes + +- aaa6fb3bc9: Minor updates for TypeScript 5.2.2+ compatibility +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/backend-plugin-api@0.6.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/backend-tasks@0.5.13-next.0 + +### Patch Changes + +- d8f488aaa8: Allow tasks to run more often that the default work check interval, which is 5 seconds. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/backend-test-utils@0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-app-api@0.5.9-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/cli@0.24.1-next.0 + +### Patch Changes + +- 8cda3c72f2: Tweaked Node.js version check for when to use the new module register API with the new backend `package start` command. +- 017c425f93: Updated dependency `@typescript-eslint/eslint-plugin` to `6.11.0`. +- Updated dependencies + - @backstage/integration@1.8.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/eslint-plugin@0.1.3 + - @backstage/release-manifests@0.0.11 + - @backstage/types@1.1.1 + +## @backstage/core-app-api@1.11.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/core-components@0.13.9-next.0 + +### Patch Changes + +- 381ed86d5e: Add missing export for IconLinkVertical +- 5c8a3e3960: Minor improvements to `Table` component. +- 4d9e3b39e4: Register component overrides in the global `OverrideComponentNameToClassKeys` provided by `@backstage/theme`. This will in turn will provide component style override types for `createUnifiedTheme`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.7 + +## @backstage/core-plugin-api@1.8.1-next.0 + +### Patch Changes + +- 03d0b6dcdc: Removed the alpha `convertLegacyRouteRef` utility, which as been moved to `@backstage/core-compat-api` +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/create-app@0.5.8-next.0 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.13 + +## @backstage/dev-utils@1.0.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/app-defaults@1.4.6-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/frontend-app-api@0.3.1-next.0 + +### Patch Changes + +- 60d6eb544e: Removed `@backstage/plugin-graphiql` dependency. +- 9ad4039efa: Bringing over apis from core-plugin-api +- b8cb7804c8: Added `createSpecializedApp`, which is a synchronous version of `createApp` where config and features already need to be loaded. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/frontend-plugin-api@0.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/integration-react@1.1.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/config@1.1.1 + +## @backstage/test-utils@1.4.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-adr@0.6.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-adr-common@0.2.18-next.0 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-adr-backend@0.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-adr-common@0.2.18-next.0 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-adr-common@0.2.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-airbrake@0.3.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/dev-utils@1.0.25-next.0 + - @backstage/test-utils@1.4.6-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-airbrake-backend@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + +## @backstage/plugin-allure@0.1.44-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-analytics-module-ga@0.1.36-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/config@1.1.1 + +## @backstage/plugin-analytics-module-ga4@0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/config@1.1.1 + +## @backstage/plugin-analytics-module-newrelic-browser@0.0.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/config@1.1.1 + +## @backstage/plugin-apache-airflow@0.2.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + +## @backstage/plugin-api-docs@0.10.2-next.0 + +### Patch Changes + +- 816d331d16: Add dependency on `graphql-config` to compensate for `graphql-language-service` needing it but not shipping the dep properly +- 615159e536: Updated dependency `graphiql` to `3.0.10`. +- 53e2c06f41: Updated dependency `@asyncapi/react-component` to `1.1.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-catalog@1.16.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-apollo-explorer@0.1.18-next.0 + +### Patch Changes + +- e296b94128: Updated dependency `@apollo/explorer` to `^3.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-app-backend@0.3.56-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/types@1.1.1 + - @backstage/plugin-app-node@0.1.8-next.0 + +## @backstage/plugin-app-node@0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + +## @backstage/plugin-auth-backend@0.20.1-next.0 + +### Patch Changes + +- 2a5891e816: Migrate the atlassian auth provider to be implemented using the new `@backstage/plugin-auth-backend-module-atlassian-provider` module +- e1c189b524: The Okta provider implementation is moved to the new module +- Updated dependencies + - @backstage/plugin-auth-backend-module-atlassian-provider@0.1.0-next.0 + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-backend-module-okta-provider@0.0.1-next.0 + - @backstage/plugin-auth-backend-module-github-provider@0.1.5-next.0 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.5-next.0 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.5-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/plugin-auth-backend-module-google-provider@0.1.5-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.2-next.0 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-auth-backend-module-github-provider@0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + +## @backstage/plugin-auth-backend-module-google-provider@0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + +## @backstage/plugin-auth-backend-module-okta-provider@0.0.1-next.0 + +### Patch Changes + +- e1c189b524: Adds okta-provider backend module for the auth plugin +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + +## @backstage/plugin-auth-node@0.4.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-azure-devops@0.3.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-azure-devops-common@0.3.1 + +## @backstage/plugin-azure-devops-backend@0.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-devops-common@0.3.1 + +## @backstage/plugin-azure-sites@0.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-azure-sites-common@0.1.1 + +## @backstage/plugin-azure-sites-backend@0.1.18-next.0 + +### Patch Changes + +- b7a13edf6d: Updated dependency `@azure/arm-appservice` to `^14.0.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-sites-common@0.1.1 + +## @backstage/plugin-badges@0.2.52-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-badges-backend@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-bazaar@0.2.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-catalog@1.16.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-bazaar-backend@0.3.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-bitbucket-cloud-common@0.2.15-next.0 + +### Patch Changes + +- acf93904e7: Updated dependency `ts-morph` to `^20.0.0`. +- Updated dependencies + - @backstage/integration@1.8.0-next.0 + +## @backstage/plugin-bitrise@0.1.55-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-catalog-backend@1.15.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-openapi-utils@0.1.1-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-events-node@0.2.17-next.0 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-catalog-backend-module-aws@0.3.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-kubernetes-common@0.7.2-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-catalog-backend-module-azure@0.1.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-openapi-utils@0.1.1-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.15-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.15-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-events-node@0.2.17-next.0 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-catalog-backend-module-gcp@0.1.8-next.0 + +### Patch Changes + +- 42c1aee741: Updated dependency `@google-cloud/container` to `^5.0.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-kubernetes-common@0.7.2-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.24-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-catalog-backend-module-github@0.4.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-backend@1.15.1-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-events-node@0.2.17-next.0 + +## @backstage/plugin-catalog-backend-module-github-org@0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-backend-module-github@0.4.6-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.4.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-backend@1.15.1-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-events-node@0.2.17-next.0 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-backend@1.15.1-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-scaffolder-common@1.4.3 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-catalog-graph@0.3.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-import@0.10.4-next.0 + +### Patch Changes + +- 03d0b6dcdc: The `convertLegacyRouteRef` utility used by the alpha exports is now imported from `@backstage/core-compat-api`. +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-catalog-node@1.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-catalog-react@1.9.2-next.0 + +### Patch Changes + +- 8587f067d2: Added pagination support to `EntityListProvider`. +- aaa6fb3bc9: Minor updates for TypeScript 5.2.2+ compatibility +- 4d9e3b39e4: Register component overrides in the global `OverrideComponentNameToClassKeys` provided by `@backstage/theme`. This will in turn will provide component style override types for `createUnifiedTheme`. +- eee0ff2946: Fixed a issue where `CatalogPage` wasn't using the chosen `initiallySelectedFilter` as intended. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-cicd-statistics@0.1.30-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.24-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-cicd-statistics@0.1.30-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-circleci@0.3.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-cloudbuild@0.3.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-code-climate@0.1.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-code-coverage@0.2.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-code-coverage-backend@0.2.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-codescene@0.1.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-config-schema@0.1.48-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-cost-insights@0.12.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-cost-insights-common@0.1.2 + +## @backstage/plugin-devtools@0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.6 + +## @backstage/plugin-devtools-backend@0.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.6 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-dynatrace@8.0.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-entity-feedback@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-feedback-backend@0.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-validation@0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-events-backend@0.2.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.0 + +## @backstage/plugin-events-backend-module-aws-sqs@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.0 + +## @backstage/plugin-events-backend-module-azure@0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/plugin-events-node@0.2.17-next.0 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/plugin-events-node@0.2.17-next.0 + +## @backstage/plugin-events-backend-module-gerrit@0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/plugin-events-node@0.2.17-next.0 + +## @backstage/plugin-events-backend-module-github@0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.0 + +## @backstage/plugin-events-backend-module-gitlab@0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.0 + +## @backstage/plugin-events-backend-test-utils@0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.17-next.0 + +## @backstage/plugin-events-node@0.2.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + +## @backstage/plugin-explore@0.4.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/plugin-explore-react@0.0.34-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-explore-backend@0.0.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-explore-react@0.0.34-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-explore-common@0.0.2 + +## @backstage/plugin-firehydrant@0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-fossa@0.2.60-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-gcalendar@0.3.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/errors@1.2.3 + +## @backstage/plugin-gcp-projects@0.3.44-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-git-release-manager@0.3.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-github-actions@0.6.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-github-deployments@0.1.59-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-github-issues@0.2.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-github-pull-requests-board@0.1.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-gitops-profiles@0.3.43-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/config@1.1.1 + +## @backstage/plugin-gocd@0.1.34-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-graphiql@0.3.1-next.0 + +### Patch Changes + +- 03d0b6dcdc: The `convertLegacyRouteRef` utility used by the alpha exports is now imported from `@backstage/core-compat-api`. +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + +## @backstage/plugin-graphql-voyager@0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-home@0.5.12-next.0 + +### Patch Changes + +- 6cd12f277b: Updated dependency `@rjsf/utils` to `5.14.1`. + Updated dependency `@rjsf/core` to `5.14.1`. + Updated dependency `@rjsf/material-ui` to `5.14.1`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.1`. +- 63c494ef22: Updated dependency `@rjsf/utils` to `5.14.2`. + Updated dependency `@rjsf/core` to `5.14.2`. + Updated dependency `@rjsf/material-ui` to `5.14.2`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.2`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-home-react@0.1.6-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-home-react@0.1.6-next.0 + +### Patch Changes + +- 6cd12f277b: Updated dependency `@rjsf/utils` to `5.14.1`. + Updated dependency `@rjsf/core` to `5.14.1`. + Updated dependency `@rjsf/material-ui` to `5.14.1`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.1`. +- 63c494ef22: Updated dependency `@rjsf/utils` to `5.14.2`. + Updated dependency `@rjsf/core` to `5.14.2`. + Updated dependency `@rjsf/material-ui` to `5.14.2`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.2`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + +## @backstage/plugin-ilert@0.2.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-jenkins@0.9.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-jenkins-common@0.1.21 + +## @backstage/plugin-jenkins-backend@0.3.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-jenkins-common@0.1.21 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-kafka@0.3.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-kafka-backend@0.3.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-kubernetes@0.11.3-next.0 + +### Patch Changes + +- 706fc3a7e1: Updated dependency `@kubernetes/client-node` to `0.20.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-kubernetes-react@0.1.2-next.0 + - @backstage/plugin-kubernetes-common@0.7.2-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-kubernetes-cluster@0.0.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-kubernetes-react@0.1.2-next.0 + - @backstage/plugin-kubernetes-common@0.7.2-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-kubernetes-common@0.7.2-next.0 + +### Patch Changes + +- 706fc3a7e1: Updated dependency `@kubernetes/client-node` to `0.20.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-kubernetes-node@0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.7.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-kubernetes-react@0.1.2-next.0 + +### Patch Changes + +- b5ae2e5a62: Add ID property to the table displaying kubernetes pods to avoid closing the info sidebar when the data reloads and needs to rerender. +- 706fc3a7e1: Updated dependency `@kubernetes/client-node` to `0.20.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-kubernetes-common@0.7.2-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-lighthouse@0.4.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4 + +## @backstage/plugin-lighthouse-backend@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4 + +## @backstage/plugin-linguist@0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-linguist-backend@0.5.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-microsoft-calendar@0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/errors@1.2.3 + +## @backstage/plugin-newrelic@0.3.43-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-newrelic-dashboard@0.3.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-nomad@0.1.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-nomad-backend@0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-octopus-deploy@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-opencost@0.2.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-org@0.6.18-next.0 + +### Patch Changes + +- 3a65d9c4d7: Support member list scrollable when parent has specified height +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-org-react@0.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-pagerduty@0.6.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-home-react@0.1.6-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-periskop@0.1.26-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-periskop-backend@0.2.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + +## @backstage/plugin-permission-backend@0.5.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-permission-node@0.7.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-permission-react@0.4.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-playlist@0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-playlist-common@0.1.12 + +## @backstage/plugin-playlist-backend@0.3.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-playlist-common@0.1.12 + +## @backstage/plugin-proxy-backend@0.4.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + +## @backstage/plugin-puppetdb@0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-rollbar@0.4.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-rollbar-backend@0.1.53-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/config@1.1.1 + +## @backstage/plugin-scaffolder@1.16.2-next.0 + +### Patch Changes + +- 6806d10be3: Added `headerOptions` to `TemplateListPage` to optionally override default values. + Changed `themeId` of TemplateListPage from `website` to `home`. +- aaa6fb3bc9: Minor updates for TypeScript 5.2.2+ compatibility +- 6cd12f277b: Updated dependency `@rjsf/utils` to `5.14.1`. + Updated dependency `@rjsf/core` to `5.14.1`. + Updated dependency `@rjsf/material-ui` to `5.14.1`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.1`. +- 63c494ef22: Updated dependency `@rjsf/utils` to `5.14.2`. + Updated dependency `@rjsf/core` to `5.14.2`. + Updated dependency `@rjsf/material-ui` to `5.14.2`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.2`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-scaffolder-react@1.6.2-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-scaffolder-common@1.4.3 + +## @backstage/plugin-scaffolder-backend@1.19.2-next.0 + +### Patch Changes + +- aff34fcf23: Fix issue with Circular JSON dependencies in templating +- 48667b4d3a: Fix creating env secret in github:environment:create action +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-catalog-backend@1.15.1-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-scaffolder-common@1.4.3 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.32-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.29-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-node@0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.3 + +## @backstage/plugin-scaffolder-react@1.6.2-next.0 + +### Patch Changes + +- e516bf4da8: Step titles in the Stepper are now clickable and redirect the user to the corresponding step, as an alternative to using the back buttons. +- aaa6fb3bc9: Minor updates for TypeScript 5.2.2+ compatibility +- 6cd12f277b: Updated dependency `@rjsf/utils` to `5.14.1`. + Updated dependency `@rjsf/core` to `5.14.1`. + Updated dependency `@rjsf/material-ui` to `5.14.1`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.1`. +- 63c494ef22: Updated dependency `@rjsf/utils` to `5.14.2`. + Updated dependency `@rjsf/core` to `5.14.2`. + Updated dependency `@rjsf/material-ui` to `5.14.2`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.2`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-scaffolder-common@1.4.3 + +## @backstage/plugin-search@1.4.4-next.0 + +### Patch Changes + +- 03d0b6dcdc: The `convertLegacyRouteRef` utility used by the alpha exports is now imported from `@backstage/core-compat-api`. +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend@1.4.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-openapi-utils@0.1.1-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/plugin-search-backend-node@1.2.12-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-catalog@0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/plugin-search-backend-node@1.2.12-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-elasticsearch@1.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-search-backend-node@1.2.12-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.8 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-explore@0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-search-backend-node@1.2.12-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-pg@0.5.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-search-backend-node@1.2.12-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-stack-overflow-collator@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-search-backend-node@1.2.12-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-techdocs@0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-techdocs-node@1.11.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/plugin-search-backend-node@1.2.12-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-node@1.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-react@1.7.4-next.0 + +### Patch Changes + +- 84dabc5363: Removed `@backstage/frontend-app-api` dependency. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-sentry@0.5.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-shortcuts@0.3.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-sonarqube@0.7.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-sonarqube-react@0.1.11-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-sonarqube-backend@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-sonarqube-react@0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-splunk-on-call@0.4.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-stack-overflow@0.1.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/plugin-home-react@0.1.6-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-stack-overflow-backend@0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-search-backend-module-stack-overflow-collator@0.1.1-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-stackstorm@0.1.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/errors@1.2.3 + +## @backstage/plugin-tech-insights@0.3.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-backend@0.5.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-tech-insights-node@0.4.14-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-tech-insights-node@0.4.14-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-node@0.4.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-radar@0.6.11-next.0 + +### Patch Changes + +- 03d0b6dcdc: The `convertLegacyRouteRef` utility used by the alpha exports is now imported from `@backstage/core-compat-api`. +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + +## @backstage/plugin-techdocs@1.9.2-next.0 + +### Patch Changes + +- 03d0b6dcdc: The `convertLegacyRouteRef` utility used by the alpha exports is now imported from `@backstage/core-compat-api`. +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/plugin-techdocs-react@1.1.14-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.25-next.0 + +### Patch Changes + +- 3f354e68f4: Move `@testing-library/react` to be a `peerDependency` +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-catalog@1.16.0-next.0 + - @backstage/plugin-techdocs@1.9.2-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/test-utils@1.4.6-next.0 + - @backstage/plugin-techdocs-react@1.1.14-next.0 + +## @backstage/plugin-techdocs-backend@1.9.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-techdocs-node@1.11.0-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/plugin-techdocs-react@1.1.14-next.0 + +## @backstage/plugin-techdocs-react@1.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/plugin-todo@0.2.32-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-todo-backend@0.3.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-openapi-utils@0.1.1-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-user-settings@0.7.14-next.0 + +### Patch Changes + +- 03d0b6dcdc: The `convertLegacyRouteRef` utility used by the alpha exports is now imported from `@backstage/core-compat-api`. +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-user-settings-backend@0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-vault@0.1.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-vault-backend@0.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-vault-node@0.1.1-next.0 + +## @backstage/plugin-vault-node@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + +## @backstage/plugin-xcmetrics@0.2.46-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/errors@1.2.3 + +## example-app@0.2.90-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/plugin-api-docs@0.10.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-scaffolder@1.16.2-next.0 + - @backstage/plugin-catalog@1.16.0-next.0 + - @backstage/frontend-app-api@0.3.1-next.0 + - @backstage/plugin-org@0.6.18-next.0 + - @backstage/plugin-scaffolder-react@1.6.2-next.0 + - @backstage/plugin-catalog-import@0.10.4-next.0 + - @backstage/plugin-user-settings@0.7.14-next.0 + - @backstage/plugin-tech-radar@0.6.11-next.0 + - @backstage/plugin-graphiql@0.3.1-next.0 + - @backstage/plugin-techdocs@1.9.2-next.0 + - @backstage/plugin-search@1.4.4-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/cli@0.24.1-next.0 + - @backstage/plugin-home@0.5.12-next.0 + - @backstage/plugin-kubernetes@0.11.3-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/app-defaults@1.4.6-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/plugin-adr@0.6.11-next.0 + - @backstage/plugin-airbrake@0.3.28-next.0 + - @backstage/plugin-apache-airflow@0.2.18-next.0 + - @backstage/plugin-azure-devops@0.3.10-next.0 + - @backstage/plugin-azure-sites@0.1.17-next.0 + - @backstage/plugin-badges@0.2.52-next.0 + - @backstage/plugin-catalog-graph@0.3.2-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.0 + - @backstage/plugin-circleci@0.3.28-next.0 + - @backstage/plugin-cloudbuild@0.3.28-next.0 + - @backstage/plugin-code-coverage@0.2.21-next.0 + - @backstage/plugin-cost-insights@0.12.17-next.0 + - @backstage/plugin-devtools@0.1.7-next.0 + - @backstage/plugin-dynatrace@8.0.2-next.0 + - @backstage/plugin-entity-feedback@0.2.11-next.0 + - @backstage/plugin-explore@0.4.14-next.0 + - @backstage/plugin-gcalendar@0.3.21-next.0 + - @backstage/plugin-gcp-projects@0.3.44-next.0 + - @backstage/plugin-github-actions@0.6.9-next.0 + - @backstage/plugin-gocd@0.1.34-next.0 + - @backstage/plugin-jenkins@0.9.3-next.0 + - @backstage/plugin-kafka@0.3.28-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.4-next.0 + - @backstage/plugin-lighthouse@0.4.13-next.0 + - @backstage/plugin-linguist@0.1.13-next.0 + - @backstage/plugin-microsoft-calendar@0.1.10-next.0 + - @backstage/plugin-newrelic@0.3.43-next.0 + - @backstage/plugin-newrelic-dashboard@0.3.3-next.0 + - @backstage/plugin-nomad@0.1.9-next.0 + - @backstage/plugin-octopus-deploy@0.2.10-next.0 + - @backstage/plugin-pagerduty@0.6.9-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + - @backstage/plugin-playlist@0.2.2-next.0 + - @backstage/plugin-puppetdb@0.1.11-next.0 + - @backstage/plugin-rollbar@0.4.28-next.0 + - @backstage/plugin-sentry@0.5.13-next.0 + - @backstage/plugin-shortcuts@0.3.17-next.0 + - @backstage/plugin-stack-overflow@0.1.23-next.0 + - @backstage/plugin-stackstorm@0.1.9-next.0 + - @backstage/plugin-tech-insights@0.3.20-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.0 + - @backstage/plugin-techdocs-react@1.1.14-next.0 + - @backstage/plugin-todo@0.2.32-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.8 + +## example-app-next@0.0.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/plugin-api-docs@0.10.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-scaffolder@1.16.2-next.0 + - @backstage/plugin-catalog@1.16.0-next.0 + - @backstage/frontend-app-api@0.3.1-next.0 + - @backstage/plugin-org@0.6.18-next.0 + - @backstage/plugin-scaffolder-react@1.6.2-next.0 + - @backstage/plugin-catalog-import@0.10.4-next.0 + - @backstage/plugin-user-settings@0.7.14-next.0 + - @backstage/plugin-tech-radar@0.6.11-next.0 + - @backstage/plugin-graphiql@0.3.1-next.0 + - @backstage/plugin-techdocs@1.9.2-next.0 + - @backstage/plugin-search@1.4.4-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/cli@0.24.1-next.0 + - @backstage/plugin-home@0.5.12-next.0 + - @backstage/plugin-kubernetes@0.11.3-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/app-defaults@1.4.6-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/plugin-adr@0.6.11-next.0 + - @backstage/plugin-airbrake@0.3.28-next.0 + - @backstage/plugin-apache-airflow@0.2.18-next.0 + - @backstage/plugin-azure-devops@0.3.10-next.0 + - @backstage/plugin-azure-sites@0.1.17-next.0 + - @backstage/plugin-badges@0.2.52-next.0 + - @backstage/plugin-catalog-graph@0.3.2-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.0 + - @backstage/plugin-circleci@0.3.28-next.0 + - @backstage/plugin-cloudbuild@0.3.28-next.0 + - @backstage/plugin-code-coverage@0.2.21-next.0 + - @backstage/plugin-cost-insights@0.12.17-next.0 + - @backstage/plugin-devtools@0.1.7-next.0 + - @backstage/plugin-dynatrace@8.0.2-next.0 + - @backstage/plugin-entity-feedback@0.2.11-next.0 + - @backstage/plugin-explore@0.4.14-next.0 + - @backstage/plugin-gcalendar@0.3.21-next.0 + - @backstage/plugin-gcp-projects@0.3.44-next.0 + - @backstage/plugin-github-actions@0.6.9-next.0 + - @backstage/plugin-gocd@0.1.34-next.0 + - @backstage/plugin-jenkins@0.9.3-next.0 + - @backstage/plugin-kafka@0.3.28-next.0 + - @backstage/plugin-lighthouse@0.4.13-next.0 + - @backstage/plugin-linguist@0.1.13-next.0 + - @backstage/plugin-microsoft-calendar@0.1.10-next.0 + - @backstage/plugin-newrelic@0.3.43-next.0 + - @backstage/plugin-newrelic-dashboard@0.3.3-next.0 + - @backstage/plugin-octopus-deploy@0.2.10-next.0 + - @backstage/plugin-pagerduty@0.6.9-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + - @backstage/plugin-playlist@0.2.2-next.0 + - @backstage/plugin-puppetdb@0.1.11-next.0 + - @backstage/plugin-rollbar@0.4.28-next.0 + - @backstage/plugin-sentry@0.5.13-next.0 + - @backstage/plugin-shortcuts@0.3.17-next.0 + - @backstage/plugin-stackstorm@0.1.9-next.0 + - @backstage/plugin-tech-insights@0.3.20-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.0 + - @backstage/plugin-techdocs-react@1.1.14-next.0 + - @backstage/plugin-todo@0.2.32-next.0 + - app-next-example-plugin@0.0.4-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.8 + +## app-next-example-plugin@0.0.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + +## example-backend@0.2.90-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-backend@0.20.1-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-scaffolder-backend@1.19.2-next.0 + - @backstage/plugin-kubernetes-backend@0.14.0-next.0 + - @backstage/plugin-azure-sites-backend@0.1.18-next.0 + - @backstage/integration@1.8.0-next.0 + - example-app@0.2.90-next.0 + - @backstage/plugin-adr-backend@0.4.5-next.0 + - @backstage/plugin-app-backend@0.3.56-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-azure-devops-backend@0.4.5-next.0 + - @backstage/plugin-badges-backend@0.3.5-next.0 + - @backstage/plugin-catalog-backend@1.15.1-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/plugin-code-coverage-backend@0.2.22-next.0 + - @backstage/plugin-devtools-backend@0.2.5-next.0 + - @backstage/plugin-entity-feedback-backend@0.2.5-next.0 + - @backstage/plugin-events-backend@0.2.17-next.0 + - @backstage/plugin-explore-backend@0.0.18-next.0 + - @backstage/plugin-jenkins-backend@0.3.2-next.0 + - @backstage/plugin-kafka-backend@0.3.6-next.0 + - @backstage/plugin-lighthouse-backend@0.3.5-next.0 + - @backstage/plugin-linguist-backend@0.5.5-next.0 + - @backstage/plugin-nomad-backend@0.1.10-next.0 + - @backstage/plugin-permission-backend@0.5.31-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/plugin-playlist-backend@0.3.12-next.0 + - @backstage/plugin-proxy-backend@0.4.6-next.0 + - @backstage/plugin-rollbar-backend@0.1.53-next.0 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.9-next.0 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.25-next.0 + - @backstage/plugin-search-backend@1.4.8-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.11-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.0 + - @backstage/plugin-search-backend-module-pg@0.5.17-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.0 + - @backstage/plugin-search-backend-node@1.2.12-next.0 + - @backstage/plugin-tech-insights-backend@0.5.22-next.0 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.40-next.0 + - @backstage/plugin-tech-insights-node@0.4.14-next.0 + - @backstage/plugin-techdocs-backend@1.9.1-next.0 + - @backstage/plugin-todo-backend@0.3.6-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.0 + - @backstage/plugin-events-node@0.2.17-next.0 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-common@1.2.8 + +## example-backend-next@0.0.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-scaffolder-backend@1.19.2-next.0 + - @backstage/plugin-kubernetes-backend@0.14.0-next.0 + - @backstage/backend-defaults@0.2.8-next.0 + - @backstage/plugin-adr-backend@0.4.5-next.0 + - @backstage/plugin-app-backend@0.3.56-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-azure-devops-backend@0.4.5-next.0 + - @backstage/plugin-badges-backend@0.3.5-next.0 + - @backstage/plugin-catalog-backend@1.15.1-next.0 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.1.1-next.0 + - @backstage/plugin-catalog-backend-module-openapi@0.1.25-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.0 + - @backstage/plugin-devtools-backend@0.2.5-next.0 + - @backstage/plugin-entity-feedback-backend@0.2.5-next.0 + - @backstage/plugin-jenkins-backend@0.3.2-next.0 + - @backstage/plugin-lighthouse-backend@0.3.5-next.0 + - @backstage/plugin-linguist-backend@0.5.5-next.0 + - @backstage/plugin-nomad-backend@0.1.10-next.0 + - @backstage/plugin-permission-backend@0.5.31-next.0 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.5-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/plugin-playlist-backend@0.3.12-next.0 + - @backstage/plugin-proxy-backend@0.4.6-next.0 + - @backstage/plugin-search-backend@1.4.8-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.0 + - @backstage/plugin-search-backend-node@1.2.12-next.0 + - @backstage/plugin-sonarqube-backend@0.2.10-next.0 + - @backstage/plugin-techdocs-backend@1.9.1-next.0 + - @backstage/plugin-todo-backend@0.3.6-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.0 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/backend-plugin-manager@0.0.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-catalog-backend@1.15.1-next.0 + - @backstage/plugin-events-backend@0.2.17-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/plugin-search-backend-node@1.2.12-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.0 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/core-compat-api@0.0.2-next.0 + +### Patch Changes + +- 03d0b6dcdc: Added `convertLegacyRouteRef` utility to convert existing route refs to be used with the new experimental packages. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/core-app-api@1.11.2-next.0 + +## e2e-test@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.8-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/errors@1.2.3 + +## techdocs-cli-embedded-app@0.2.89-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-catalog@1.16.0-next.0 + - @backstage/plugin-techdocs@1.9.2-next.0 + - @backstage/cli@0.24.1-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/app-defaults@1.4.6-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/test-utils@1.4.6-next.0 + - @backstage/plugin-techdocs-react@1.1.14-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + +## @internal/plugin-todo-list@1.0.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + +## @internal/plugin-todo-list-backend@1.0.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 diff --git a/docs/releases/v1.21.0-next.1-changelog.md b/docs/releases/v1.21.0-next.1-changelog.md new file mode 100644 index 0000000000..aa5f14b1b4 --- /dev/null +++ b/docs/releases/v1.21.0-next.1-changelog.md @@ -0,0 +1,140 @@ +# Release v1.21.0-next.1 + +## @backstage/core-compat-api@0.0.1-next.0 + +### Patch Changes + +- c219b168aa: Made package public so it can be published + +## @backstage/create-app@0.5.8-next.1 + +### Patch Changes + +- Bumped create-app version. + +## @backstage/plugin-api-docs@0.10.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.16.0-next.1 + +## @backstage/plugin-bazaar@0.2.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.16.0-next.1 + +## @backstage/plugin-catalog@1.16.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + +## @backstage/plugin-catalog-import@0.10.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + +## @backstage/plugin-graphiql@0.3.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + +## @backstage/plugin-search@1.4.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + +## @backstage/plugin-tech-radar@0.6.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + +## @backstage/plugin-techdocs@1.9.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.16.0-next.1 + - @backstage/plugin-techdocs@1.9.2-next.1 + +## @backstage/plugin-user-settings@0.7.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + +## example-app@0.2.90-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.16.0-next.1 + - @backstage/plugin-catalog-import@0.10.4-next.1 + - @backstage/plugin-graphiql@0.3.1-next.1 + - @backstage/plugin-search@1.4.4-next.1 + - @backstage/plugin-tech-radar@0.6.11-next.1 + - @backstage/plugin-techdocs@1.9.2-next.1 + - @backstage/plugin-user-settings@0.7.14-next.1 + - @backstage/plugin-api-docs@0.10.2-next.1 + - @backstage/plugin-catalog-graph@0.3.2-next.0 + - @backstage/plugin-explore@0.4.14-next.0 + - @backstage/plugin-org@0.6.18-next.0 + - @backstage/plugin-scaffolder@1.16.2-next.0 + - @backstage/plugin-scaffolder-react@1.6.2-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.0 + +## example-app-next@0.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + - @backstage/plugin-catalog@1.16.0-next.1 + - @backstage/plugin-catalog-import@0.10.4-next.1 + - @backstage/plugin-graphiql@0.3.1-next.1 + - @backstage/plugin-search@1.4.4-next.1 + - @backstage/plugin-tech-radar@0.6.11-next.1 + - @backstage/plugin-techdocs@1.9.2-next.1 + - @backstage/plugin-user-settings@0.7.14-next.1 + - @backstage/plugin-api-docs@0.10.2-next.1 + - @backstage/plugin-catalog-graph@0.3.2-next.0 + - @backstage/plugin-explore@0.4.14-next.0 + - @backstage/plugin-org@0.6.18-next.0 + - @backstage/plugin-scaffolder@1.16.2-next.0 + - @backstage/plugin-scaffolder-react@1.6.2-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.0 + +## e2e-test@0.2.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.8-next.1 + +## techdocs-cli-embedded-app@0.2.89-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.16.0-next.1 + - @backstage/plugin-techdocs@1.9.2-next.1 diff --git a/docs/releases/v1.21.0-next.2-changelog.md b/docs/releases/v1.21.0-next.2-changelog.md new file mode 100644 index 0000000000..ba5c3c007d --- /dev/null +++ b/docs/releases/v1.21.0-next.2-changelog.md @@ -0,0 +1,3088 @@ +# Release v1.21.0-next.2 + +## @backstage/catalog-client@1.5.0-next.0 + +### Minor Changes + +- 38340678c3: The internals of `CatalogClient` are now auto-generated using the `backstage-repo-tools schema openapi generate-client` command. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/cli@0.25.0-next.1 + +### Minor Changes + +- 38340678c3: Updates the ESLint config to ignore issues created by generated files in `**/src/generated/**`. + +### Patch Changes + +- 0ffee55010: Toned down the warning message when git is not found +- c6f3743172: Added a warning when starting a standalone backend plugin that hasn't been updated to the new backend system. +- 3e358b0dff: Added deprecation warning for React Router v6 beta, please make sure you have migrated your apps to use React Router v6 stable as support for the beta version will be removed. See the [migration tutorial](https://backstage.io/docs/tutorials/react-router-stable-migration) for more information. +- 8056425e09: Updated dependency `@typescript-eslint/eslint-plugin` to `6.12.0`. +- 33e96e59e7: Switched the `@typescript-eslint/eslint-plugin` dependency back to using a `^` version range. +- Updated dependencies + - @backstage/eslint-plugin@0.1.4-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/release-manifests@0.0.11 + - @backstage/types@1.1.1 + +## @backstage/frontend-app-api@0.4.0-next.1 + +### Minor Changes + +- e539735435: Updated core extension structure to make space for the sign-in page by adding `core.router`. + +### Patch Changes + +- 5eb6b8a7bc: Added the nav logo extension for customization of sidebar logo +- 1f12fb762c: Create a core components extension that allows adopters to override core app components such as `Progress`, `BootErrorPage`, `NotFoundErrorPage` and `ErrorBoundaryFallback`. +- 59709286b3: Collect and register feature flags from plugins and extension overrides. +- f27ee7d937: Migrate analytics route tracker component. +- a5a04739e1: Updates to provide `node` to extension factories instead of `id` and `source`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/frontend-plugin-api@0.4.0-next.1 + +### Minor Changes + +- a5a04739e1: The extension `factory` function now longer receives `id` or `source`, but instead now provides the extension's `AppNode` as `node`. The `ExtensionBoundary` component has also been updated to receive a `node` prop rather than `id` and `source`. + +### Patch Changes + +- 5eb6b8a7bc: Added the nav logo extension for customization of sidebar logo +- 1f12fb762c: Create factories for overriding default core components extensions. +- 59709286b3: Add feature flags to plugins and extension overrides. +- e539735435: Added `createSignInPageExtension`. +- f27ee7d937: Migrate analytics api and context files. +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/repo-tools@0.5.0-next.0 + +### Minor Changes + +- aea8f8d329: **BREAKING**: API Reports generated for sub-path exports now place the name as a suffix rather than prefix, for example `api-report-alpha.md` instead of `alpha-api-report.md`. When upgrading to this version you'll need to re-create any such API reports and delete the old ones. +- 38340678c3: Adds a new command `schema openapi generate-client` that creates a Typescript client with Backstage flavor, including the discovery API and fetch API. This command doesn't currently generate a complete client and needs to be wrapped or exported manually by a separate Backstage plugin. See `@backstage/catalog-client/src/generated` for example output. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/errors@1.2.3 + +## @techdocs/cli@1.8.0-next.1 + +### Minor Changes + +- b2dccad7b3: Support passing additional `mkdocs-server` CLI parameters (`--dirtyreload`, `--strict` and `--clean`) when run in containerized mode. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs-node@1.11.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + +## @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.0-next.0 + +### Minor Changes + +- 271aa12c7c: Release of `oauth2-proxy-provider` plugin + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-auth-backend-module-vmware-cloud-provider@0.1.0-next.0 + +### Minor Changes + +- ed02c69a3c: Add VMware Cloud auth backend module provider + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-azure-devops-backend@0.5.0-next.1 + +### Minor Changes + +- 844969cd97: **BREAKING** New `fromConfig` static method must be used now when creating an instance of the `AzureDevOpsApi` + + Added support for using the `AzureDevOpsCredentialsProvider` + +### Patch Changes + +- 043b724c56: Introduced new `AzureDevOpsAnnotatorProcessor` that adds the needed annotations automatically. Also, moved constants to common package so they can be shared more easily +- Updated dependencies + - @backstage/plugin-azure-devops-common@0.3.2-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-catalog@1.16.0-next.2 + +### Minor Changes + +- e223f2264d: Properly support both function- and string-form visibility filter expressions in the new extensions exported via `/alpha`. + +### Patch Changes + +- 53600976bb: Ensure that passed-in icons are taken advantage of in the presentation API +- a5a04739e1: Internal refactor of alpha exports due to a change in how extension factories are defined. +- 78a10bb085: Adding in spec.type chip to search results for clarity +- fb8f3bdbc2: Updated alpha translation message keys to use nested format and camel case. +- 531e1a2a79: Updated alpha plugin to include the `unregisterRedirect` external route. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-scaffolder-common@1.4.3 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-home@0.6.0-next.1 + +### Minor Changes + +- 5a317f59c0: Added view of entities grouped by kind to make it easier to distinguish entities with different kind but same name + +### Patch Changes + +- 2b725913c1: Updated dependency `@rjsf/utils` to `5.14.3`. + Updated dependency `@rjsf/core` to `5.14.3`. + Updated dependency `@rjsf/material-ui` to `5.14.3`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.3`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/plugin-home-react@0.1.6-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-pagerduty@0.7.0-next.1 + +### Minor Changes + +- 5fca16fdf6: This package has been deprecated, consider using [@pagerduty/backstage-plugin](https://github.com/pagerduty/backstage-plugin) instead. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-home-react@0.1.6-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/app-defaults@1.4.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/backend-app-api@0.5.9-next.1 + +### Patch Changes + +- 1da5f434f3: Ensure redaction of secrets that have accidental extra whitespace around them +- 9f8f266ff4: Add redacting for secrets in stack traces of logs +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-permission-node@0.7.19-next.1 + +## @backstage/backend-common@0.20.0-next.1 + +### Patch Changes + +- 2666675457: Updated dependency `@google-cloud/storage` to `^7.0.0`. +- Updated dependencies + - @backstage/backend-app-api@0.5.9-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-dev-utils@0.1.2 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + +## @backstage/backend-defaults@0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.5.9-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + +## @backstage/backend-openapi-utils@0.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/backend-plugin-api@0.6.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/backend-tasks@0.5.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/backend-test-utils@0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.5.9-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/core-app-api@1.11.2-next.1 + +### Patch Changes + +- 3e358b0dff: Added deprecation warning for React Router v6 beta, please make sure you have migrated your apps to use React Router v6 stable as support for the beta version will be removed. See the [migration tutorial](https://backstage.io/docs/tutorials/react-router-stable-migration) for more information. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/core-compat-api@0.0.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/core-app-api@1.11.2-next.1 + +## @backstage/core-components@0.13.9-next.1 + +### Patch Changes + +- e8f2acef80: Added a new `/testUtils` sub-path that initially exports a `mockBreakpoint` helper. +- 07dfdf3702: Updated dependency `linkifyjs` to `4.1.3`. +- a518c5a25b: Updated dependency `@react-hookz/web` to `^23.0.0`. +- f291757e70: Update `linkify-react` to version `4.1.3` +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/version-bridge@1.0.7 + +## @backstage/core-plugin-api@1.8.1-next.1 + +### Patch Changes + +- 0c93dc37b2: The `createTranslationRef` function from the `/alpha` subpath can now also accept a nested object structure of default translation messages, which will be flatted using `.` separators. +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/create-app@0.5.8-next.2 + +### Patch Changes + +- 375b6f7d68: CircelCI plugin moved permanently +- Updated dependencies + - @backstage/cli-common@0.1.13 + +## @backstage/dev-utils@1.0.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/app-defaults@1.4.6-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/eslint-plugin@0.1.4-next.0 + +### Patch Changes + +- 107dc46ab1: The `no-undeclared-imports` rule will now prefer using version queries that already exist en the repo for the same dependency type when installing new packages. + +## @backstage/frontend-test-utils@0.1.0-next.1 + +### Patch Changes + +- e539735435: Updates for `core.router` addition. +- c21c9cf07b: Re-export mock API implementations as well as `TestApiProvider`, `TestApiRegistry`, `withLogCollector`, and `setupRequestMockHandlers` from `@backstage/test-utils`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/frontend-app-api@0.4.0-next.1 + - @backstage/test-utils@1.4.6-next.1 + - @backstage/types@1.1.1 + +## @backstage/integration@1.8.0-next.1 + +### Patch Changes + +- 99fb54183b: Updated dependency `@azure/identity` to `^4.0.0`. +- Updated dependencies + - @backstage/config@1.1.1 + +## @backstage/integration-react@1.1.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/config@1.1.1 + +## @backstage/test-utils@1.4.6-next.1 + +### Patch Changes + +- e8f2acef80: Deprecated `mockBreakpoint`, as it is now available from `@backstage/core-components/testUtils` instead. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-adr@0.6.11-next.1 + +### Patch Changes + +- fb8f3bdbc2: Updated alpha translation message keys to use nested format and camel case. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-adr-common@0.2.18-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-adr-backend@0.4.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-adr-common@0.2.18-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-adr-common@0.2.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-airbrake@0.3.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/test-utils@1.4.6-next.1 + - @backstage/dev-utils@1.0.25-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-airbrake-backend@0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + +## @backstage/plugin-allure@0.1.44-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-analytics-module-ga@0.1.36-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-analytics-module-ga4@0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-analytics-module-newrelic-browser@0.0.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + +## @backstage/plugin-apache-airflow@0.2.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-api-docs@0.10.2-next.2 + +### Patch Changes + +- e16e7ce6a5: Updated dependency `@asyncapi/react-component` to `1.2.2`. +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-catalog@1.16.0-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-apollo-explorer@0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-app-backend@0.3.56-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/types@1.1.1 + - @backstage/plugin-app-node@0.1.8-next.1 + +## @backstage/plugin-app-node@0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + +## @backstage/plugin-auth-backend@0.20.1-next.1 + +### Patch Changes + +- 7ac25759a5: `oauth2-proxy` auth implementation has been moved to `@backstage/plugin-auth-backend-module-oauth2-proxy-provider` +- bcbbf8e042: Updated dependency `@google-cloud/firestore` to `^7.0.0`. +- Updated dependencies + - @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.0-next.0 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/plugin-auth-backend-module-atlassian-provider@0.1.0-next.1 + - @backstage/plugin-auth-backend-module-github-provider@0.1.5-next.1 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.5-next.1 + - @backstage/plugin-auth-backend-module-google-provider@0.1.5-next.1 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.5-next.1 + - @backstage/plugin-auth-backend-module-okta-provider@0.0.1-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.2-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-auth-backend-module-atlassian-provider@0.1.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-auth-backend-module-github-provider@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-auth-backend-module-google-provider@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-auth-backend-module-okta-provider@0.0.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-auth-node@0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-azure-devops@0.3.10-next.1 + +### Patch Changes + +- 043b724c56: Introduced new `AzureDevOpsAnnotatorProcessor` that adds the needed annotations automatically. Also, moved constants to common package so they can be shared more easily +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-azure-devops-common@0.3.2-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-azure-devops-common@0.3.2-next.0 + +### Patch Changes + +- 043b724c56: Introduced new `AzureDevOpsAnnotatorProcessor` that adds the needed annotations automatically. Also, moved constants to common package so they can be shared more easily + +## @backstage/plugin-azure-sites@0.1.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-azure-sites-common@0.1.1 + +## @backstage/plugin-azure-sites-backend@0.1.18-next.1 + +### Patch Changes + +- 99fb54183b: Updated dependency `@azure/identity` to `^4.0.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-sites-common@0.1.1 + +## @backstage/plugin-badges@0.2.52-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-badges-backend@0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-bazaar@0.2.20-next.2 + +### Patch Changes + +- 5d796829bb: Internalize 'AboutField' to break catalog dependency +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-bazaar-backend@0.3.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-bitbucket-cloud-common@0.2.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + +## @backstage/plugin-bitrise@0.1.55-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-catalog-backend@1.15.1-next.1 + +### Patch Changes + +- 38340678c3: Update the OpenAPI spec to support the use of `openapi-generator`. +- 7123c58b3d: Updated dependency `@types/glob` to `^8.0.0`. +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-openapi-utils@0.1.1-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.1 + +## @backstage/plugin-catalog-backend-module-aws@0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-catalog-backend-module-azure@0.1.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.1.1-next.1 + +### Patch Changes + +- eb44e92898: Support authenticated backends +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-openapi-utils@0.1.1-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.15-next.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.15-next.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-catalog-backend-module-gcp@0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-catalog-backend-module-github@0.4.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.15.1-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## @backstage/plugin-catalog-backend-module-github-org@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-backend-module-github@0.4.6-next.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.4.12-next.1 + +### Patch Changes + +- 43b2eb8f70: Ensure that cursors always come back as JSON on sqlite too +- Updated dependencies + - @backstage/plugin-catalog-backend@1.15.1-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.15-next.1 + +### Patch Changes + +- 99fb54183b: Updated dependency `@azure/identity` to `^4.0.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.15.1-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-scaffolder-common@1.4.3 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-catalog-graph@0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-import@0.10.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-catalog-node@1.5.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-catalog-react@1.9.2-next.1 + +### Patch Changes + +- 53600976bb: Ensure that passed-in icons are taken advantage of in the presentation API + +- 08d9e67199: Add default icon for kind resource. + +- a5a04739e1: Internal refactor of alpha exports due to a change in how extension factories are defined. + +- e223f2264d: Breaking alpha-API change to entity visibility filter functions to accept a bare entity as their first argument, instead of an object with an entity property. + + Functions that accept such filters now also support the string expression form of filters. + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-cicd-statistics@0.1.30-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-cicd-statistics@0.1.30-next.1 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-circleci@0.3.28-next.1 + +### Patch Changes + +- 375b6f7d68: CircelCI plugin moved permanently +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-cloudbuild@0.3.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-code-climate@0.1.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-code-coverage@0.2.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-code-coverage-backend@0.2.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-codescene@0.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-config-schema@0.1.48-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-cost-insights@0.12.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-cost-insights-common@0.1.2 + +## @backstage/plugin-devtools@0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.6 + +## @backstage/plugin-devtools-backend@0.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-devtools-common@0.1.6 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + +## @backstage/plugin-dynatrace@8.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-entity-feedback@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-feedback-backend@0.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-validation@0.1.13-next.1 + +### Patch Changes + +- a518c5a25b: Updated dependency `@react-hookz/web` to `^23.0.0`. +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-events-backend@0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## @backstage/plugin-events-backend-module-aws-sqs@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## @backstage/plugin-events-backend-module-azure@0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## @backstage/plugin-events-backend-module-gerrit@0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## @backstage/plugin-events-backend-module-github@0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## @backstage/plugin-events-backend-module-gitlab@0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## @backstage/plugin-events-backend-test-utils@0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.17-next.1 + +## @backstage/plugin-events-node@0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + +## @backstage/plugin-explore@0.4.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/plugin-explore-react@0.0.34-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-explore-backend@0.0.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-explore-react@0.0.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-explore-common@0.0.2 + +## @backstage/plugin-firehydrant@0.2.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-fossa@0.2.60-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-gcalendar@0.3.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-gcp-projects@0.3.44-next.1 + +### Patch Changes + +- a518c5a25b: Updated dependency `@react-hookz/web` to `^23.0.0`. +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-git-release-manager@0.3.40-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-github-actions@0.6.9-next.1 + +### Patch Changes + +- 08d7e4676a: Github Workflow Runs UI is modified to show in optional Card view instead of table, with branch selection option +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-github-deployments@0.1.59-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-github-issues@0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-github-pull-requests-board@0.1.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-gitops-profiles@0.3.43-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-gocd@0.1.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-graphiql@0.3.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-graphql-voyager@0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-home-react@0.1.6-next.1 + +### Patch Changes + +- 2b725913c1: Updated dependency `@rjsf/utils` to `5.14.3`. + Updated dependency `@rjsf/core` to `5.14.3`. + Updated dependency `@rjsf/material-ui` to `5.14.3`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.3`. +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-ilert@0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-jenkins@0.9.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-jenkins-common@0.1.21 + +## @backstage/plugin-jenkins-backend@0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-jenkins-common@0.1.21 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + +## @backstage/plugin-kafka@0.3.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-kafka-backend@0.3.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-kubernetes@0.11.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/plugin-kubernetes-react@0.1.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-kubernetes-backend@0.14.0-next.1 + +### Patch Changes + +- ae94d3ce6f: Updated dependency `@aws-crypto/sha256-js` to `^5.0.0`. +- 99fb54183b: Updated dependency `@azure/identity` to `^4.0.0`. +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-kubernetes-node@0.1.2-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + +## @backstage/plugin-kubernetes-cluster@0.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/plugin-kubernetes-react@0.1.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-kubernetes-common@0.7.2-next.1 + +### Patch Changes + +- 5d796829bb: Remove unused dependency +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-kubernetes-node@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-kubernetes-react@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-lighthouse@0.4.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-lighthouse-common@0.1.4 + +## @backstage/plugin-lighthouse-backend@0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-lighthouse-common@0.1.4 + +## @backstage/plugin-linguist@0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-linguist-backend@0.5.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-microsoft-calendar@0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-newrelic@0.3.43-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-newrelic-dashboard@0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-nomad@0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-nomad-backend@0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-octopus-deploy@0.2.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-opencost@0.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-org@0.6.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-org-react@0.1.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-periskop@0.1.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-periskop-backend@0.2.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + +## @backstage/plugin-permission-backend@0.5.31-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + +## @backstage/plugin-permission-node@0.7.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-permission-react@0.4.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-playlist@0.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-playlist-common@0.1.12 + +## @backstage/plugin-playlist-backend@0.3.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + - @backstage/plugin-playlist-common@0.1.12 + +## @backstage/plugin-proxy-backend@0.4.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + +## @backstage/plugin-puppetdb@0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-rollbar@0.4.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-rollbar-backend@0.1.53-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + +## @backstage/plugin-scaffolder@1.16.2-next.1 + +### Patch Changes + +- 2b725913c1: Updated dependency `@rjsf/utils` to `5.14.3`. + Updated dependency `@rjsf/core` to `5.14.3`. + Updated dependency `@rjsf/material-ui` to `5.14.3`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.3`. +- a518c5a25b: Updated dependency `@react-hookz/web` to `^23.0.0`. +- b5fa6918dc: Fixing `headerOptions` not being passed through the `TemplatePage` component +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/plugin-scaffolder-react@1.6.2-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-scaffolder-common@1.4.3 + +## @backstage/plugin-scaffolder-backend@1.19.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.15.1-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + - @backstage/plugin-scaffolder-common@1.4.3 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.16-next.1 + +### Patch Changes + +- 7f8a801e6d: Added examples for `sentry:project:create` scaffolder action and unit tests. +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + +## @backstage/plugin-scaffolder-node@0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.3 + +## @backstage/plugin-scaffolder-react@1.6.2-next.1 + +### Patch Changes + +- fa66d1b5b3: Fixed bug in `ReviewState` where `enum` value was displayed in step review instead of the corresponding label when using `enumNames` +- 2aee53bbeb: Add horizontal slider if stepper overflows +- 2b725913c1: Updated dependency `@rjsf/utils` to `5.14.3`. + Updated dependency `@rjsf/core` to `5.14.3`. + Updated dependency `@rjsf/material-ui` to `5.14.3`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.3`. +- a518c5a25b: Updated dependency `@react-hookz/web` to `^23.0.0`. +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-scaffolder-common@1.4.3 + +## @backstage/plugin-search@1.4.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend@1.4.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-openapi-utils@0.1.1-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + - @backstage/plugin-search-backend-node@1.2.12-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-catalog@0.1.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-backend-node@1.2.12-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-elasticsearch@1.3.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.8 + - @backstage/plugin-search-backend-node@1.2.12-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-explore@0.1.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-backend-node@1.2.12-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-pg@0.5.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-search-backend-node@1.2.12-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-stack-overflow-collator@0.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-search-backend-node@1.2.12-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-techdocs@0.1.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/plugin-techdocs-node@1.11.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-backend-node@1.2.12-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-node@1.2.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-react@1.7.4-next.1 + +### Patch Changes + +- a5a04739e1: Internal refactor of alpha exports due to a change in how extension factories are defined. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-sentry@0.5.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-shortcuts@0.3.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-sonarqube@0.7.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-sonarqube-react@0.1.11-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-sonarqube-backend@0.2.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-sonarqube-react@0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-splunk-on-call@0.4.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-stack-overflow@0.1.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/plugin-home-react@0.1.6-next.1 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-stack-overflow-backend@0.2.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-search-backend-module-stack-overflow-collator@0.1.1-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-stackstorm@0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-tech-insights@0.3.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-backend@0.5.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + - @backstage/plugin-tech-insights-node@0.4.14-next.1 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.40-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-tech-insights-common@0.2.12 + - @backstage/plugin-tech-insights-node@0.4.14-next.1 + +## @backstage/plugin-tech-insights-node@0.4.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-radar@0.6.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-techdocs@1.9.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-techdocs-react@1.1.14-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.25-next.2 + +### Patch Changes + +- 5d796829bb: Remove unnecessary catalog dependency +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-catalog@1.16.0-next.2 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/test-utils@1.4.6-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/plugin-techdocs@1.9.2-next.2 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-techdocs-react@1.1.14-next.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-techdocs-backend@1.9.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-techdocs-node@1.11.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.1 + +### Patch Changes + +- a518c5a25b: Updated dependency `@react-hookz/web` to `^23.0.0`. +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-techdocs-react@1.1.14-next.1 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-techdocs-node@1.11.0-next.1 + +### Patch Changes + +- 99fb54183b: Updated dependency `@azure/identity` to `^4.0.0`. +- 2666675457: Updated dependency `@google-cloud/storage` to `^7.0.0`. +- 4f773c15f6: Bumped the default TechDocs docker image version to the latest which was released several month ago +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-techdocs-react@1.1.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/plugin-todo@0.2.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-todo-backend@0.3.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-openapi-utils@0.1.1-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## @backstage/plugin-user-settings@0.7.14-next.2 + +### Patch Changes + +- fb8f3bdbc2: Updated alpha translation message keys to use nested format and camel case. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-user-settings-backend@0.2.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## @backstage/plugin-vault@0.1.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## @backstage/plugin-vault-backend@0.4.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-vault-node@0.1.1-next.1 + +## @backstage/plugin-vault-node@0.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + +## @backstage/plugin-xcmetrics@0.2.46-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## example-app@0.2.90-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/cli@0.25.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-catalog@1.16.0-next.2 + - @backstage/plugin-scaffolder-react@1.6.2-next.1 + - @backstage/plugin-home@0.6.0-next.1 + - @backstage/plugin-github-actions@0.6.9-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/plugin-azure-devops@0.3.10-next.1 + - @backstage/plugin-scaffolder@1.16.2-next.1 + - @backstage/plugin-api-docs@0.10.2-next.2 + - @backstage/plugin-gcp-projects@0.3.44-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.1 + - @backstage/plugin-user-settings@0.7.14-next.2 + - @backstage/plugin-adr@0.6.11-next.1 + - @backstage/plugin-pagerduty@0.7.0-next.1 + - @backstage/plugin-catalog-import@0.10.4-next.2 + - @backstage/plugin-explore@0.4.14-next.1 + - @backstage/plugin-graphiql@0.3.1-next.2 + - @backstage/plugin-search@1.4.4-next.2 + - @backstage/plugin-stack-overflow@0.1.23-next.1 + - @backstage/plugin-tech-radar@0.6.11-next.2 + - @backstage/plugin-techdocs@1.9.2-next.2 + - @backstage/app-defaults@1.4.6-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-airbrake@0.3.28-next.1 + - @backstage/plugin-apache-airflow@0.2.18-next.1 + - @backstage/plugin-azure-sites@0.1.17-next.1 + - @backstage/plugin-badges@0.2.52-next.1 + - @backstage/plugin-catalog-graph@0.3.2-next.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.1 + - @backstage/plugin-cloudbuild@0.3.28-next.1 + - @backstage/plugin-code-coverage@0.2.21-next.1 + - @backstage/plugin-cost-insights@0.12.17-next.1 + - @backstage/plugin-devtools@0.1.7-next.1 + - @backstage/plugin-dynatrace@8.0.2-next.1 + - @backstage/plugin-entity-feedback@0.2.11-next.1 + - @backstage/plugin-gcalendar@0.3.21-next.1 + - @backstage/plugin-gocd@0.1.34-next.1 + - @backstage/plugin-jenkins@0.9.3-next.1 + - @backstage/plugin-kafka@0.3.28-next.1 + - @backstage/plugin-kubernetes@0.11.3-next.1 + - @backstage/plugin-kubernetes-cluster@0.0.4-next.1 + - @backstage/plugin-lighthouse@0.4.13-next.1 + - @backstage/plugin-linguist@0.1.13-next.1 + - @backstage/plugin-microsoft-calendar@0.1.10-next.1 + - @backstage/plugin-newrelic@0.3.43-next.1 + - @backstage/plugin-newrelic-dashboard@0.3.3-next.1 + - @backstage/plugin-nomad@0.1.9-next.1 + - @backstage/plugin-octopus-deploy@0.2.10-next.1 + - @backstage/plugin-org@0.6.18-next.1 + - @backstage/plugin-playlist@0.2.2-next.1 + - @backstage/plugin-puppetdb@0.1.11-next.1 + - @backstage/plugin-rollbar@0.4.28-next.1 + - @backstage/plugin-sentry@0.5.13-next.1 + - @backstage/plugin-shortcuts@0.3.17-next.1 + - @backstage/plugin-stackstorm@0.1.9-next.1 + - @backstage/plugin-tech-insights@0.3.20-next.1 + - @backstage/plugin-techdocs-react@1.1.14-next.1 + - @backstage/plugin-todo@0.2.32-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.8 + +## example-app-next@0.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/frontend-app-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/cli@0.25.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-catalog@1.16.0-next.2 + - @backstage/plugin-scaffolder-react@1.6.2-next.1 + - @backstage/plugin-home@0.6.0-next.1 + - @backstage/plugin-github-actions@0.6.9-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/plugin-azure-devops@0.3.10-next.1 + - @backstage/plugin-scaffolder@1.16.2-next.1 + - @backstage/plugin-api-docs@0.10.2-next.2 + - @backstage/plugin-gcp-projects@0.3.44-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.1 + - @backstage/plugin-user-settings@0.7.14-next.2 + - @backstage/plugin-adr@0.6.11-next.1 + - @backstage/plugin-pagerduty@0.7.0-next.1 + - app-next-example-plugin@0.0.4-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/plugin-catalog-import@0.10.4-next.2 + - @backstage/plugin-explore@0.4.14-next.1 + - @backstage/plugin-graphiql@0.3.1-next.2 + - @backstage/plugin-search@1.4.4-next.2 + - @backstage/plugin-tech-radar@0.6.11-next.2 + - @backstage/plugin-techdocs@1.9.2-next.2 + - @backstage/app-defaults@1.4.6-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-airbrake@0.3.28-next.1 + - @backstage/plugin-apache-airflow@0.2.18-next.1 + - @backstage/plugin-azure-sites@0.1.17-next.1 + - @backstage/plugin-badges@0.2.52-next.1 + - @backstage/plugin-catalog-graph@0.3.2-next.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.1 + - @backstage/plugin-cloudbuild@0.3.28-next.1 + - @backstage/plugin-code-coverage@0.2.21-next.1 + - @backstage/plugin-cost-insights@0.12.17-next.1 + - @backstage/plugin-devtools@0.1.7-next.1 + - @backstage/plugin-dynatrace@8.0.2-next.1 + - @backstage/plugin-entity-feedback@0.2.11-next.1 + - @backstage/plugin-gcalendar@0.3.21-next.1 + - @backstage/plugin-gocd@0.1.34-next.1 + - @backstage/plugin-jenkins@0.9.3-next.1 + - @backstage/plugin-kafka@0.3.28-next.1 + - @backstage/plugin-kubernetes@0.11.3-next.1 + - @backstage/plugin-lighthouse@0.4.13-next.1 + - @backstage/plugin-linguist@0.1.13-next.1 + - @backstage/plugin-microsoft-calendar@0.1.10-next.1 + - @backstage/plugin-newrelic@0.3.43-next.1 + - @backstage/plugin-newrelic-dashboard@0.3.3-next.1 + - @backstage/plugin-octopus-deploy@0.2.10-next.1 + - @backstage/plugin-org@0.6.18-next.1 + - @backstage/plugin-playlist@0.2.2-next.1 + - @backstage/plugin-puppetdb@0.1.11-next.1 + - @backstage/plugin-rollbar@0.4.28-next.1 + - @backstage/plugin-sentry@0.5.13-next.1 + - @backstage/plugin-shortcuts@0.3.17-next.1 + - @backstage/plugin-stackstorm@0.1.9-next.1 + - @backstage/plugin-tech-insights@0.3.20-next.1 + - @backstage/plugin-techdocs-react@1.1.14-next.1 + - @backstage/plugin-todo@0.2.32-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.8 + +## app-next-example-plugin@0.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + +## example-backend@0.2.90-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-backend@0.20.1-next.1 + - @backstage/plugin-catalog-backend@1.15.1-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/plugin-azure-devops-backend@0.5.0-next.1 + - @backstage/plugin-kubernetes-backend@0.14.0-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-azure-sites-backend@0.1.18-next.1 + - @backstage/backend-common@0.20.0-next.1 + - example-app@0.2.90-next.2 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-adr-backend@0.4.5-next.1 + - @backstage/plugin-app-backend@0.3.56-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-badges-backend@0.3.5-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-code-coverage-backend@0.2.22-next.1 + - @backstage/plugin-devtools-backend@0.2.5-next.1 + - @backstage/plugin-entity-feedback-backend@0.2.5-next.1 + - @backstage/plugin-events-backend@0.2.17-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + - @backstage/plugin-explore-backend@0.0.18-next.1 + - @backstage/plugin-jenkins-backend@0.3.2-next.1 + - @backstage/plugin-kafka-backend@0.3.6-next.1 + - @backstage/plugin-lighthouse-backend@0.3.5-next.1 + - @backstage/plugin-linguist-backend@0.5.5-next.1 + - @backstage/plugin-nomad-backend@0.1.10-next.1 + - @backstage/plugin-permission-backend@0.5.31-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + - @backstage/plugin-playlist-backend@0.3.12-next.1 + - @backstage/plugin-proxy-backend@0.4.6-next.1 + - @backstage/plugin-rollbar-backend@0.1.53-next.1 + - @backstage/plugin-scaffolder-backend@1.19.2-next.1 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.9-next.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.25-next.1 + - @backstage/plugin-search-backend@1.4.8-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.1 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.11-next.1 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.1 + - @backstage/plugin-search-backend-module-pg@0.5.17-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.1 + - @backstage/plugin-search-backend-node@1.2.12-next.1 + - @backstage/plugin-search-common@1.2.8 + - @backstage/plugin-tech-insights-backend@0.5.22-next.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.40-next.1 + - @backstage/plugin-tech-insights-node@0.4.14-next.1 + - @backstage/plugin-techdocs-backend@1.9.1-next.1 + - @backstage/plugin-todo-backend@0.3.6-next.1 + +## example-backend-next@0.0.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.1.1-next.1 + - @backstage/plugin-catalog-backend@1.15.1-next.1 + - @backstage/plugin-azure-devops-backend@0.5.0-next.1 + - @backstage/plugin-kubernetes-backend@0.14.0-next.1 + - @backstage/backend-defaults@0.2.8-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/plugin-adr-backend@0.4.5-next.1 + - @backstage/plugin-app-backend@0.3.56-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-badges-backend@0.3.5-next.1 + - @backstage/plugin-catalog-backend-module-openapi@0.1.25-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.1 + - @backstage/plugin-devtools-backend@0.2.5-next.1 + - @backstage/plugin-entity-feedback-backend@0.2.5-next.1 + - @backstage/plugin-jenkins-backend@0.3.2-next.1 + - @backstage/plugin-lighthouse-backend@0.3.5-next.1 + - @backstage/plugin-linguist-backend@0.5.5-next.1 + - @backstage/plugin-nomad-backend@0.1.10-next.1 + - @backstage/plugin-permission-backend@0.5.31-next.1 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.5-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + - @backstage/plugin-playlist-backend@0.3.12-next.1 + - @backstage/plugin-proxy-backend@0.4.6-next.1 + - @backstage/plugin-scaffolder-backend@1.19.2-next.1 + - @backstage/plugin-search-backend@1.4.8-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.1 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.1 + - @backstage/plugin-search-backend-node@1.2.12-next.1 + - @backstage/plugin-sonarqube-backend@0.2.10-next.1 + - @backstage/plugin-techdocs-backend@1.9.1-next.1 + - @backstage/plugin-todo-backend@0.3.6-next.1 + +## @backstage/backend-plugin-manager@0.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.15.1-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-events-backend@0.2.17-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + - @backstage/plugin-search-backend-node@1.2.12-next.1 + - @backstage/plugin-search-common@1.2.8 + +## e2e-test@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.8-next.2 + - @backstage/cli-common@0.1.13 + - @backstage/errors@1.2.3 + +## techdocs-cli-embedded-app@0.2.89-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/cli@0.25.0-next.1 + - @backstage/plugin-catalog@1.16.0-next.2 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/test-utils@1.4.6-next.1 + - @backstage/plugin-techdocs@1.9.2-next.2 + - @backstage/app-defaults@1.4.6-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-techdocs-react@1.1.14-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + +## @internal/plugin-todo-list@1.0.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## @internal/plugin-todo-list-backend@1.0.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 diff --git a/docs/releases/v1.21.0-next.3-changelog.md b/docs/releases/v1.21.0-next.3-changelog.md new file mode 100644 index 0000000000..a45c6d6df0 --- /dev/null +++ b/docs/releases/v1.21.0-next.3-changelog.md @@ -0,0 +1,3025 @@ +# Release v1.21.0-next.3 + +## @backstage/config-loader@1.6.0-next.0 + +### Minor Changes + +- 24f5a85: Add "path" to `TransformFunc` context + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/core-compat-api@0.1.0-next.2 + +### Minor Changes + +- cf5cc4c: Discover plugins and routes recursively beneath the root routes in `collectLecacyRoutes` + +### Patch Changes + +- 8226442: Added `compatWrapper`, which can be used to wrap any React element to provide bi-directional interoperability between the `@backstage/core-*-api` and `@backstage/frontend-*-api` APIs. +- 8f5d6c1: Updates to match the new extension input wrapping. +- b7adf24: Delete alpha DI compatibility helper for components, migrating components should be simple without a helper. +- 046e443: Updates for compatibility with the new extension IDs. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/frontend-app-api@0.4.0-next.2 + +### Minor Changes + +- ea06590: The app no longer provides the `AppContext` from `@backstage/core-plugin-api`. Components that require this context to be available should use the `compatWrapper` helper from `@backstage/core-compat-api`. + +### Patch Changes + +- aeb8008: Add support for translation extensions. +- b7adf24: Use the new plugin type for error boundary components. +- 8f5d6c1: Updates to match the new extension input wrapping. +- cb4197a: Forward ` node`` instead of `extensionId\` to resolved extension inputs. +- 8837a96: Updates to match the introduction of `ExtensionDefinition` and new extension ID naming patterns. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/frontend-plugin-api@0.4.0-next.2 + +### Minor Changes + +- 8f5d6c1: Extension inputs are now wrapped into an additional object when passed to the extension factory, with the previous values being available at the `output` property. The `ExtensionInputValues` type has also been replaced by `ResolvedExtensionInputs`. +- 8837a96: **BREAKING**: This version changes how extensions are created and how their IDs are determined. The `createExtension` function now accepts `kind`, `namespace` and `name` instead of `id`. All of the new options are optional, and are used to construct the final extension ID. By convention extension creators should set the `kind` to match their own name, for example `createNavItemExtension` sets the kind `nav-item`. + + The `createExtension` function as well as all extension creators now also return an `ExtensionDefinition` rather than an `Extension`, which in turn needs to be passed to `createPlugin` or `createExtensionOverrides` to be used. + +### Patch Changes + +- b7adf24: Update alpha component ref type to be more specific than any, delete boot page component and use new plugin type for error boundary component extensions. +- 73246ec: Added translation APIs as well as `createTranslationExtension`. +- cb4197a: Forward ` node`` instead of `extensionId\` to resolved extension inputs. +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/plugin-catalog-backend@1.16.0-next.2 + +### Minor Changes + +- 7804597: Permission rules can now be added for the Catalog plugin through the `CatalogPermissionExtensionPoint` interface. + +### Patch Changes + +- 50ee804: Wrap single `pipelineLoop` of TaskPipeline in a span for better traces +- a168507: Deprecated `EntitiesSearchFilter` and `EntityFilter`, which can now be imported from `@backstage/plugin-catalog-node` instead +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.2 + - @backstage/backend-openapi-utils@0.1.1-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-events-node@0.2.17-next.2 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## @backstage/plugin-catalog-node@1.6.0-next.2 + +### Minor Changes + +- a168507: Added `EntitiesSearchFilter` and `EntityFilter` from `@backstage/plugin-catalog-backend`, for reuse +- 7804597: Permission rules can now be added for the Catalog plugin through the `CatalogPermissionExtensionPoint` interface. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## @backstage/plugin-kubernetes-react@0.2.0-next.2 + +### Minor Changes + +- 899d71a: Change `formatClusterLink` to be an API and make it async for further customization possibilities. + + **BREAKING** + If you have a custom k8s page and used `formatClusterLink` directly, you need to migrate to new `kubernetesClusterLinkFormatterApiRef` + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + +## @backstage/plugin-lighthouse-backend@0.4.0-next.2 + +### Minor Changes + +- 7f0dbfd: Fixed crashes faced with custom schedule configuration. The configuration schema has been update to leverage the TaskScheduleDefinition interface. It is highly recommended to move the `lighthouse.shedule` and `lighthouse.timeout` respectively to `lighthouse.schedule.frequency` and `lighthouse.schedule.timeout`. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4 + +## @backstage/app-defaults@1.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + +## @backstage/backend-app-api@0.5.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.6.0-next.0 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## @backstage/backend-common@0.20.0-next.2 + +### Patch Changes + +- bc67498: Updated dependency `archiver` to `^6.0.0`. + Updated dependency `@types/archiver` to `^6.0.0`. +- Updated dependencies + - @backstage/config-loader@1.6.0-next.0 + - @backstage/backend-app-api@0.5.9-next.2 + - @backstage/backend-dev-utils@0.1.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + +## @backstage/backend-defaults@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-app-api@0.5.9-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## @backstage/backend-openapi-utils@0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/backend-plugin-api@0.6.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/backend-tasks@0.5.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/backend-test-utils@0.2.9-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-app-api@0.5.9-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/catalog-client@1.5.0-next.1 + +### Patch Changes + +- 82fa88b: Fixes a bug where some query parameters were double URL encoded. +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/cli@0.25.0-next.2 + +### Patch Changes + +- 32018ff: Enable the `tsx` loader to work on Node 18.19 and up +- a3edc18: Updated dependency `vite-plugin-node-polyfills` to `^0.17.0`. +- 627554e: Updated dependency `@rollup/plugin-node-resolve` to `^15.0.0`. +- c07cee5: Updated dependency `@rollup/plugin-json` to `^6.0.0`. +- 2565cc8: Updated dependency `@rollup/plugin-commonjs` to `^25.0.0`. +- Updated dependencies + - @backstage/config-loader@1.6.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/eslint-plugin@0.1.4-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/release-manifests@0.0.11 + - @backstage/types@1.1.1 + +## @backstage/core-components@0.13.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.7 + +## @backstage/create-app@0.5.8-next.3 + +### Patch Changes + +- a96c2d4: Include the `` for group entities by default +- Updated dependencies + - @backstage/cli-common@0.1.13 + +## @backstage/dev-utils@1.0.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/app-defaults@1.4.6-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + +## @backstage/frontend-test-utils@0.1.0-next.2 + +### Patch Changes + +- 818eea4: Updates for compatibility with the new extension IDs. +- b9aa6e4: Migrate `renderInTestApp` to `@backstage/frontend-test-utils` for testing individual React components in an app. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/frontend-app-api@0.4.0-next.2 + - @backstage/test-utils@1.4.6-next.2 + - @backstage/types@1.1.1 + +## @backstage/repo-tools@0.5.0-next.1 + +### Patch Changes + +- f909e9d: Includes templates in @backstage/repo-tools package and use them in the CLI + +- da3c4db: Updates the `schema openapi generate-client` command to export all generated types from the generated directory. + +- 7959f23: The `api-reports` command now checks for api report files that no longer apply. + If it finds such files, it's treated basically the same as report errors do, and + the check fails. + + For example, if you had an `api-report-alpha.md` but then removed the alpha + export, the reports generator would now report that this file needs to be + deleted. + +- f49e237: Fixed a bug where `schema openapi init` created an invalid test command. + +- f91be2c: Updated dependency `@stoplight/types` to `^14.0.0`. + +- 45bfb20: Execute `openapi-generator-cli` from `@backstage/repo-tools` directory to force it to use our openapitools.json config file. + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/errors@1.2.3 + +## @techdocs/cli@1.8.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/plugin-techdocs-node@1.11.0-next.2 + +## @backstage/test-utils@1.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-react@0.4.18-next.1 + +## @backstage/theme@0.5.0-next.1 + +### Patch Changes + +- cd0dd4c: Align Material UI v5 `Paper` component background color in dark mode to v4. + +## @backstage/plugin-adr@0.6.11-next.2 + +### Patch Changes + +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-adr-common@0.2.18-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-adr-backend@0.4.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-adr-common@0.2.18-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-airbrake@0.3.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/dev-utils@1.0.25-next.2 + - @backstage/test-utils@1.4.6-next.2 + +## @backstage/plugin-airbrake-backend@0.3.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + +## @backstage/plugin-allure@0.1.44-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-analytics-module-ga@0.1.36-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-analytics-module-ga4@0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-analytics-module-newrelic-browser@0.0.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-apache-airflow@0.2.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-api-docs@0.10.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog@1.16.0-next.3 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-apollo-explorer@0.1.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-app-backend@0.3.56-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.6.0-next.0 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-app-node@0.1.8-next.2 + +## @backstage/plugin-app-node@0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + +## @backstage/plugin-auth-backend@0.20.1-next.2 + +### Patch Changes + +- 783797a: fix static token issuer not being able to initialize +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.0-next.1 + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-backend-module-atlassian-provider@0.1.0-next.2 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.5-next.2 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.5-next.2 + - @backstage/plugin-auth-backend-module-okta-provider@0.0.1-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.2-next.2 + - @backstage/plugin-auth-backend-module-google-provider@0.1.5-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-backend-module-github-provider@0.1.5-next.2 + +## @backstage/plugin-auth-backend-module-atlassian-provider@0.1.0-next.2 + +### Patch Changes + +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.2-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-auth-backend-module-github-provider@0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.1.5-next.2 + +### Patch Changes + +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## @backstage/plugin-auth-backend-module-google-provider@0.1.5-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.1.3-next.2 + +### Patch Changes + +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.1.5-next.2 + +### Patch Changes + +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.0-next.1 + +### Patch Changes + +- a6be465: Exported the provider as default so it gets discovered when using `featureDiscoveryServiceFactory()` +- 510dab4: Change provider id from `oauth2ProxyProvider` to `oauth2Proxy` +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/errors@1.2.3 + +## @backstage/plugin-auth-backend-module-okta-provider@0.0.1-next.2 + +### Patch Changes + +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.1.2-next.2 + +### Patch Changes + +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + +## @backstage/plugin-auth-backend-module-vmware-cloud-provider@0.1.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-auth-node@0.4.2-next.2 + +### Patch Changes + +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-azure-devops@0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-azure-devops-common@0.3.2-next.0 + +## @backstage/plugin-azure-devops-backend@0.5.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-azure-devops-common@0.3.2-next.0 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-azure-sites@0.1.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-azure-sites-common@0.1.1 + +## @backstage/plugin-azure-sites-backend@0.1.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-sites-common@0.1.1 + +## @backstage/plugin-badges@0.2.52-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-badges-backend@0.3.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-bazaar@0.2.20-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-bazaar-backend@0.3.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-bitrise@0.1.55-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-catalog@1.16.0-next.3 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 8f5d6c1: Updates to the `/alpha` exports to match the extension input wrapping change. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-scaffolder-common@1.4.3 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-catalog-backend-module-aws@0.3.2-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + +## @backstage/plugin-catalog-backend-module-azure@0.1.27-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-openapi-utils@0.1.1-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.15-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.23-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.15-next.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-events-node@0.2.17-next.2 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.21-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + +## @backstage/plugin-catalog-backend-module-gcp@0.1.8-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.24-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + +## @backstage/plugin-catalog-backend-module-github@0.4.6-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/plugin-catalog-backend@1.16.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-events-node@0.2.17-next.2 + +## @backstage/plugin-catalog-backend-module-github-org@0.1.2-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-catalog-backend-module-github@0.4.6-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/config@1.1.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.3.5-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/integration@1.8.0-next.1 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.4.12-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/plugin-catalog-backend@1.16.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-events-node@0.2.17-next.2 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/plugin-catalog-backend@1.16.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.13-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-scaffolder-common@1.4.3 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-catalog-graph@0.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-import@0.10.4-next.3 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-catalog-react@1.9.2-next.2 + +### Patch Changes + +- 8f5d6c1: Updates to the `/alpha` exports to match the extension input wrapping change. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-react@0.4.18-next.1 + +## @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-cicd-statistics@0.1.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.24-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-cicd-statistics@0.1.30-next.2 + +## @backstage/plugin-circleci@0.3.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-cloudbuild@0.3.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-code-climate@0.1.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-code-coverage@0.2.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-code-coverage-backend@0.2.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + +## @backstage/plugin-codescene@0.1.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-config-schema@0.1.48-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-cost-insights@0.12.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-cost-insights-common@0.1.2 + +## @backstage/plugin-devtools@0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.6 + - @backstage/plugin-permission-react@0.4.18-next.1 + +## @backstage/plugin-devtools-backend@0.2.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.6.0-next.0 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.6 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## @backstage/plugin-dynatrace@8.0.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-entity-feedback@0.2.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-feedback-backend@0.2.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-validation@0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + +## @backstage/plugin-events-backend@0.2.17-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.2 + +## @backstage/plugin-events-backend-module-aws-sqs@0.2.11-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.2 + +## @backstage/plugin-events-backend-module-azure@0.1.18-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/plugin-events-node@0.2.17-next.2 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.18-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/plugin-events-node@0.2.17-next.2 + +## @backstage/plugin-events-backend-module-gerrit@0.1.18-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/plugin-events-node@0.2.17-next.2 + +## @backstage/plugin-events-backend-module-github@0.1.18-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.2 + +## @backstage/plugin-events-backend-module-gitlab@0.1.18-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.2 + +## @backstage/plugin-events-backend-test-utils@0.1.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.17-next.2 + +## @backstage/plugin-events-node@0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + +## @backstage/plugin-explore@0.4.14-next.2 + +### Patch Changes + +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-explore-react@0.0.34-next.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-explore-backend@0.0.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.2 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-firehydrant@0.2.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-fossa@0.2.60-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-gcalendar@0.3.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-gcp-projects@0.3.44-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-git-release-manager@0.3.40-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration@1.8.0-next.1 + +## @backstage/plugin-github-actions@0.6.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + +## @backstage/plugin-github-deployments@0.1.59-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + +## @backstage/plugin-github-issues@0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + +## @backstage/plugin-github-pull-requests-board@0.1.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration@1.8.0-next.1 + +## @backstage/plugin-gitops-profiles@0.3.43-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-gocd@0.1.34-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-graphiql@0.3.1-next.3 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 8f5d6c1: Updates to the `/alpha` exports to match the extension input wrapping change. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-graphql-voyager@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-home@0.6.0-next.2 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 8f5d6c1: Updates to the `/alpha` exports to match the extension input wrapping change. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-home-react@0.1.6-next.2 + +## @backstage/plugin-home-react@0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-ilert@0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-jenkins@0.9.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-jenkins-common@0.1.21 + +## @backstage/plugin-jenkins-backend@0.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-jenkins-common@0.1.21 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## @backstage/plugin-kafka@0.3.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-kafka-backend@0.3.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-kubernetes@0.11.3-next.2 + +### Patch Changes + +- 899d71a: Change `formatClusterLink` to be an API and make it async for further customization possibilities. + + **BREAKING** + If you have a custom k8s page and used `formatClusterLink` directly, you need to migrate to new `kubernetesClusterLinkFormatterApiRef` + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-kubernetes-react@0.2.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + +## @backstage/plugin-kubernetes-backend@0.14.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/plugin-kubernetes-node@0.1.2-next.2 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## @backstage/plugin-kubernetes-cluster@0.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-kubernetes-react@0.2.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + +## @backstage/plugin-kubernetes-node@0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + +## @backstage/plugin-lighthouse@0.4.13-next.2 + +### Patch Changes + +- ffbf656: Updated README +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-lighthouse-common@0.1.4 + +## @backstage/plugin-linguist@0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-linguist-backend@0.5.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-microsoft-calendar@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-newrelic@0.3.43-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-newrelic-dashboard@0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-nomad@0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-nomad-backend@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-octopus-deploy@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-opencost@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-org@0.6.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-org-react@0.1.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-pagerduty@0.7.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-home-react@0.1.6-next.2 + +## @backstage/plugin-periskop@0.1.26-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-periskop-backend@0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + +## @backstage/plugin-permission-backend@0.5.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.1.5-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## @backstage/plugin-permission-node@0.7.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + +## @backstage/plugin-playlist@0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/plugin-playlist-common@0.1.12 + +## @backstage/plugin-playlist-backend@0.3.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + - @backstage/plugin-playlist-common@0.1.12 + +## @backstage/plugin-proxy-backend@0.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + +## @backstage/plugin-puppetdb@0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-rollbar@0.4.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-rollbar-backend@0.1.53-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/config@1.1.1 + +## @backstage/plugin-scaffolder@1.16.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/plugin-scaffolder-react@1.6.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/plugin-scaffolder-common@1.4.3 + +## @backstage/plugin-scaffolder-backend@1.19.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/plugin-catalog-backend@1.16.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + - @backstage/plugin-scaffolder-common@1.4.3 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + +## @backstage/plugin-scaffolder-node@0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.3 + +## @backstage/plugin-scaffolder-react@1.6.2-next.2 + +### Patch Changes + +- 5bb5240: Fixed issue for showing undefined for hidden form items +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-scaffolder-common@1.4.3 + +## @backstage/plugin-search@1.4.4-next.3 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 8f5d6c1: Updates to the `/alpha` exports to match the extension input wrapping change. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend@1.4.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-openapi-utils@0.1.1-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + - @backstage/plugin-search-backend-node@1.2.12-next.2 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-catalog@0.1.12-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-backend-node@1.2.12-next.2 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-elasticsearch@1.3.11-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.8 + - @backstage/plugin-search-backend-node@1.2.12-next.2 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-explore@0.1.12-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/config@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-backend-node@1.2.12-next.2 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-pg@0.5.17-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/plugin-search-backend-node@1.2.12-next.2 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-stack-overflow-collator@0.1.1-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/config@1.1.1 + - @backstage/plugin-search-backend-node@1.2.12-next.2 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-backend-module-techdocs@0.1.12-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-backend-node@1.2.12-next.2 + - @backstage/plugin-search-common@1.2.8 + - @backstage/plugin-techdocs-node@1.11.0-next.2 + +## @backstage/plugin-search-backend-node@1.2.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-search-react@1.7.4-next.2 + +### Patch Changes + +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-sentry@0.5.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-shortcuts@0.3.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-sonarqube@0.7.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-sonarqube-react@0.1.11-next.1 + +## @backstage/plugin-sonarqube-backend@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-splunk-on-call@0.4.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-stack-overflow@0.1.23-next.2 + +### Patch Changes + +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-home-react@0.1.6-next.2 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-stack-overflow-backend@0.2.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-search-backend-module-stack-overflow-collator@0.1.1-next.2 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-stackstorm@0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-tech-insights@0.3.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-backend@0.5.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + - @backstage/plugin-tech-insights-node@0.4.14-next.2 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.40-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-tech-insights-common@0.2.12 + - @backstage/plugin-tech-insights-node@0.4.14-next.2 + +## @backstage/plugin-tech-insights-node@0.4.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-radar@0.6.11-next.3 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @backstage/plugin-techdocs@1.9.2-next.3 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-search-common@1.2.8 + - @backstage/plugin-techdocs-react@1.1.14-next.2 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.25-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-techdocs@1.9.2-next.3 + - @backstage/plugin-catalog@1.16.0-next.3 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/test-utils@1.4.6-next.2 + - @backstage/plugin-techdocs-react@1.1.14-next.2 + +## @backstage/plugin-techdocs-backend@1.9.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-common@1.2.8 + - @backstage/plugin-techdocs-node@1.11.0-next.2 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-techdocs-react@1.1.14-next.2 + +## @backstage/plugin-techdocs-node@1.11.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-aws-node@0.1.8 + - @backstage/plugin-search-common@1.2.8 + +## @backstage/plugin-techdocs-react@1.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/version-bridge@1.0.7 + +## @backstage/plugin-todo@0.2.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-todo-backend@0.3.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-openapi-utils@0.1.1-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + +## @backstage/plugin-user-settings@0.7.14-next.3 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 8f5d6c1: Updates to the `/alpha` exports to match the extension input wrapping change. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-user-settings-backend@0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-vault@0.1.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## @backstage/plugin-vault-backend@0.4.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-vault-node@0.1.1-next.2 + +## @backstage/plugin-vault-node@0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + +## @backstage/plugin-xcmetrics@0.2.46-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## example-app@0.2.90-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.4.0-next.2 + - @backstage/cli@0.25.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-kubernetes@0.11.3-next.2 + - @backstage/plugin-lighthouse@0.4.13-next.2 + - @backstage/plugin-catalog-import@0.10.4-next.3 + - @backstage/plugin-user-settings@0.7.14-next.3 + - @backstage/plugin-tech-radar@0.6.11-next.3 + - @backstage/plugin-graphiql@0.3.1-next.3 + - @backstage/plugin-techdocs@1.9.2-next.3 + - @backstage/plugin-catalog@1.16.0-next.3 + - @backstage/plugin-search@1.4.4-next.3 + - @backstage/plugin-home@0.6.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-stack-overflow@0.1.23-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/plugin-explore@0.4.14-next.2 + - @backstage/plugin-adr@0.6.11-next.2 + - @backstage/plugin-scaffolder-react@1.6.2-next.2 + - @backstage/app-defaults@1.4.6-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-airbrake@0.3.28-next.2 + - @backstage/plugin-apache-airflow@0.2.18-next.2 + - @backstage/plugin-api-docs@0.10.2-next.3 + - @backstage/plugin-azure-devops@0.3.10-next.2 + - @backstage/plugin-azure-sites@0.1.17-next.2 + - @backstage/plugin-badges@0.2.52-next.2 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-graph@0.3.2-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.2 + - @backstage/plugin-cloudbuild@0.3.28-next.2 + - @backstage/plugin-code-coverage@0.2.21-next.2 + - @backstage/plugin-cost-insights@0.12.17-next.2 + - @backstage/plugin-devtools@0.1.7-next.2 + - @backstage/plugin-dynatrace@8.0.2-next.2 + - @backstage/plugin-entity-feedback@0.2.11-next.2 + - @backstage/plugin-gcalendar@0.3.21-next.2 + - @backstage/plugin-gcp-projects@0.3.44-next.2 + - @backstage/plugin-github-actions@0.6.9-next.2 + - @backstage/plugin-gocd@0.1.34-next.2 + - @backstage/plugin-jenkins@0.9.3-next.2 + - @backstage/plugin-kafka@0.3.28-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.4-next.2 + - @backstage/plugin-linguist@0.1.13-next.2 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-microsoft-calendar@0.1.10-next.2 + - @backstage/plugin-newrelic@0.3.43-next.2 + - @backstage/plugin-newrelic-dashboard@0.3.3-next.2 + - @backstage/plugin-nomad@0.1.9-next.2 + - @backstage/plugin-octopus-deploy@0.2.10-next.2 + - @backstage/plugin-org@0.6.18-next.2 + - @backstage/plugin-pagerduty@0.7.0-next.2 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/plugin-playlist@0.2.2-next.2 + - @backstage/plugin-puppetdb@0.1.11-next.2 + - @backstage/plugin-rollbar@0.4.28-next.2 + - @backstage/plugin-scaffolder@1.16.2-next.2 + - @backstage/plugin-search-common@1.2.8 + - @backstage/plugin-sentry@0.5.13-next.2 + - @backstage/plugin-shortcuts@0.3.17-next.2 + - @backstage/plugin-stackstorm@0.1.9-next.2 + - @backstage/plugin-tech-insights@0.3.20-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.2 + - @backstage/plugin-techdocs-react@1.1.14-next.2 + - @backstage/plugin-todo@0.2.32-next.2 + +## example-app-next@0.0.4-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/frontend-app-api@0.4.0-next.2 + - @backstage/cli@0.25.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-kubernetes@0.11.3-next.2 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/plugin-lighthouse@0.4.13-next.2 + - @backstage/plugin-catalog-import@0.10.4-next.3 + - @backstage/plugin-user-settings@0.7.14-next.3 + - @backstage/plugin-tech-radar@0.6.11-next.3 + - @backstage/plugin-graphiql@0.3.1-next.3 + - @backstage/plugin-techdocs@1.9.2-next.3 + - @backstage/plugin-catalog@1.16.0-next.3 + - @backstage/plugin-search@1.4.4-next.3 + - @backstage/plugin-home@0.6.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/plugin-explore@0.4.14-next.2 + - @backstage/plugin-adr@0.6.11-next.2 + - @backstage/plugin-scaffolder-react@1.6.2-next.2 + - app-next-example-plugin@0.0.4-next.2 + - @backstage/app-defaults@1.4.6-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-airbrake@0.3.28-next.2 + - @backstage/plugin-apache-airflow@0.2.18-next.2 + - @backstage/plugin-api-docs@0.10.2-next.3 + - @backstage/plugin-azure-devops@0.3.10-next.2 + - @backstage/plugin-azure-sites@0.1.17-next.2 + - @backstage/plugin-badges@0.2.52-next.2 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-graph@0.3.2-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.2 + - @backstage/plugin-cloudbuild@0.3.28-next.2 + - @backstage/plugin-code-coverage@0.2.21-next.2 + - @backstage/plugin-cost-insights@0.12.17-next.2 + - @backstage/plugin-devtools@0.1.7-next.2 + - @backstage/plugin-dynatrace@8.0.2-next.2 + - @backstage/plugin-entity-feedback@0.2.11-next.2 + - @backstage/plugin-gcalendar@0.3.21-next.2 + - @backstage/plugin-gcp-projects@0.3.44-next.2 + - @backstage/plugin-github-actions@0.6.9-next.2 + - @backstage/plugin-gocd@0.1.34-next.2 + - @backstage/plugin-jenkins@0.9.3-next.2 + - @backstage/plugin-kafka@0.3.28-next.2 + - @backstage/plugin-linguist@0.1.13-next.2 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-microsoft-calendar@0.1.10-next.2 + - @backstage/plugin-newrelic@0.3.43-next.2 + - @backstage/plugin-newrelic-dashboard@0.3.3-next.2 + - @backstage/plugin-octopus-deploy@0.2.10-next.2 + - @backstage/plugin-org@0.6.18-next.2 + - @backstage/plugin-pagerduty@0.7.0-next.2 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/plugin-playlist@0.2.2-next.2 + - @backstage/plugin-puppetdb@0.1.11-next.2 + - @backstage/plugin-rollbar@0.4.28-next.2 + - @backstage/plugin-scaffolder@1.16.2-next.2 + - @backstage/plugin-search-common@1.2.8 + - @backstage/plugin-sentry@0.5.13-next.2 + - @backstage/plugin-shortcuts@0.3.17-next.2 + - @backstage/plugin-stackstorm@0.1.9-next.2 + - @backstage/plugin-tech-insights@0.3.20-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.2 + - @backstage/plugin-techdocs-react@1.1.14-next.2 + - @backstage/plugin-todo@0.2.32-next.2 + +## app-next-example-plugin@0.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/core-components@0.13.9-next.2 + +## example-backend@0.2.90-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/plugin-catalog-backend@1.16.0-next.2 + - @backstage/plugin-auth-backend@0.20.1-next.2 + - @backstage/plugin-lighthouse-backend@0.4.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.11-next.2 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.2 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.2 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.2 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.2 + - @backstage/plugin-search-backend-module-pg@0.5.17-next.2 + - @backstage/plugin-events-backend@0.2.17-next.2 + - example-app@0.2.90-next.3 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-adr-backend@0.4.5-next.2 + - @backstage/plugin-app-backend@0.3.56-next.2 + - @backstage/plugin-azure-devops-backend@0.5.0-next.2 + - @backstage/plugin-azure-sites-backend@0.1.18-next.2 + - @backstage/plugin-badges-backend@0.3.5-next.2 + - @backstage/plugin-code-coverage-backend@0.2.22-next.2 + - @backstage/plugin-devtools-backend@0.2.5-next.2 + - @backstage/plugin-entity-feedback-backend@0.2.5-next.2 + - @backstage/plugin-events-node@0.2.17-next.2 + - @backstage/plugin-explore-backend@0.0.18-next.2 + - @backstage/plugin-jenkins-backend@0.3.2-next.2 + - @backstage/plugin-kafka-backend@0.3.6-next.2 + - @backstage/plugin-kubernetes-backend@0.14.0-next.2 + - @backstage/plugin-linguist-backend@0.5.5-next.2 + - @backstage/plugin-nomad-backend@0.1.10-next.2 + - @backstage/plugin-permission-backend@0.5.31-next.2 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + - @backstage/plugin-playlist-backend@0.3.12-next.2 + - @backstage/plugin-proxy-backend@0.4.6-next.2 + - @backstage/plugin-rollbar-backend@0.1.53-next.2 + - @backstage/plugin-scaffolder-backend@1.19.2-next.2 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.9-next.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.25-next.2 + - @backstage/plugin-search-backend@1.4.8-next.2 + - @backstage/plugin-search-backend-node@1.2.12-next.2 + - @backstage/plugin-search-common@1.2.8 + - @backstage/plugin-tech-insights-backend@0.5.22-next.2 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.40-next.2 + - @backstage/plugin-tech-insights-node@0.4.14-next.2 + - @backstage/plugin-techdocs-backend@1.9.1-next.2 + - @backstage/plugin-todo-backend@0.3.6-next.2 + +## example-backend-next@0.0.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.16.0-next.2 + - @backstage/plugin-lighthouse-backend@0.4.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.2 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.5-next.2 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.2 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.2 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.2 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.2 + - @backstage/backend-defaults@0.2.8-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/plugin-adr-backend@0.4.5-next.2 + - @backstage/plugin-app-backend@0.3.56-next.2 + - @backstage/plugin-azure-devops-backend@0.5.0-next.2 + - @backstage/plugin-badges-backend@0.3.5-next.2 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.1.1-next.2 + - @backstage/plugin-catalog-backend-module-openapi@0.1.25-next.2 + - @backstage/plugin-devtools-backend@0.2.5-next.2 + - @backstage/plugin-entity-feedback-backend@0.2.5-next.2 + - @backstage/plugin-jenkins-backend@0.3.2-next.2 + - @backstage/plugin-kubernetes-backend@0.14.0-next.2 + - @backstage/plugin-linguist-backend@0.5.5-next.2 + - @backstage/plugin-nomad-backend@0.1.10-next.2 + - @backstage/plugin-permission-backend@0.5.31-next.2 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + - @backstage/plugin-playlist-backend@0.3.12-next.2 + - @backstage/plugin-proxy-backend@0.4.6-next.2 + - @backstage/plugin-scaffolder-backend@1.19.2-next.2 + - @backstage/plugin-search-backend@1.4.8-next.2 + - @backstage/plugin-search-backend-node@1.2.12-next.2 + - @backstage/plugin-sonarqube-backend@0.2.10-next.2 + - @backstage/plugin-techdocs-backend@1.9.1-next.2 + - @backstage/plugin-todo-backend@0.3.6-next.2 + +## @backstage/backend-plugin-manager@0.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.16.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/plugin-events-backend@0.2.17-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.2 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + - @backstage/plugin-search-backend-node@1.2.12-next.2 + - @backstage/plugin-search-common@1.2.8 + +## e2e-test@0.2.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.8-next.3 + - @backstage/cli-common@0.1.13 + - @backstage/errors@1.2.3 + +## techdocs-cli-embedded-app@0.2.89-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.25.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-techdocs@1.9.2-next.3 + - @backstage/plugin-catalog@1.16.0-next.3 + - @backstage/app-defaults@1.4.6-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/test-utils@1.4.6-next.2 + - @backstage/plugin-techdocs-react@1.1.14-next.2 + +## @internal/plugin-todo-list@1.0.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## @internal/plugin-todo-list-backend@1.0.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 diff --git a/docs/tutorials/migrate-to-mui5.md b/docs/tutorials/migrate-to-mui5.md new file mode 100644 index 0000000000..96129ceb8a --- /dev/null +++ b/docs/tutorials/migrate-to-mui5.md @@ -0,0 +1,65 @@ +--- +id: migrate-to-mui5 +title: Migrating from Material UI v4 to v5 +description: Additional resources for the Material UI v5 migration guide specifically for Backstage +--- + +Backstage supports developing new plugins or components using Material UI v5. At the same time, large parts of the application as well as existing plugins will still be using Material UI v4. To support Material UI v4 and v5 at the same time, we have introduced a new concept called the `UnifiedTheme`. The goal of the `UnifiedTheme` is to allow gradual migration by running both versions in parallel, applying theme options similarly & supporting potential future versions of Material UI. + +By default, the `UnifiedThemeProvider` is already used. If you add a custom theme in your `createApp` function, you would need to replace the Material UI `ThemeProvider` with the `UnifiedThemeProvider`: + +```diff ts ++ import import { ++ UnifiedThemeProvider, ++ themes as builtinThemes, ++ } from '@backstage/theme'; + + const app = createApp({ + // ... + themes: [ + { + // ... + provider: ({ children }) => ( +- . +- {children}. +- + ), + } + ] + }); +``` + +Before making specific changes to your Backstage instance, it might be helpful to take a look at the [Migration Guide provided by Material UI](https://mui.com/material-ui/migration/migration-v4/) first. It breaks down the differences between v4 and v5, and will make it easier to understand the impact on your Backstage instance & plugins. + +It is worth noting that we are still using `@mui/styles` & `jss`. You may stumble upon documentation for migrating to `emotion` when using `makeStyles` or `withStyles`. It is not necessary to switch to `emotion`. + +Important to keep in mind is that Material UI v5 is meant to be used with React Version 17 or higher. This means if you intend to use the Material UI v5 components in your plugins, you have to enforce React Version to be at least 17 for these plugins: + +```json +... + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0", + "react-router-dom": "6.0.0-beta.0 || ^6.3.0" + }, +... +``` + +To comply with Material UI recommendations, we are enforcing a new linting rule that favors standard imports over named imports and also restricts 3rd-level imports as they are considered private ([Guide: Minimizing Bundle Size](https://mui.com/material-ui/guides/minimizing-bundle-size)). + +There are `core-components` as well as components exported from Backstage `*-react` plugins written in Material UI v4, which expect Material UI components as props. In these cases you will still be forced to use Material UI v4. + +For current known issues with the Material UI v5 migration, follow our [Milestone on GitHub](https://github.com/backstage/backstage/milestone/40). Please open a new issue if you run into different problems. + +### Plugins + +To migrate your plugin to Material UI v5, you can build on the resources available. + +1. Manually fix the imports from named to default imports to match the new [linting rules for minimizing bundle size](https://mui.com/material-ui/guides/minimizing-bundle-size). +2. Run the migration `codemod` for the path of the specific plugin: `npx @mui/codemod v5.0.0/preset-safe plugins/`. +3. Take a look at possible `TODO:` items the `codemod` could not fix. +4. Remove types & methods from `@backstage/theme` which are marked as `@deprecated`. +5. Ensure you are using `"react": "^17.0.0"` (or newer) as a peer dependency + +You can follow the [migration of the GraphiQL plugin](https://github.com/backstage/backstage/pull/17696) as an example of a plugin migration. diff --git a/microsite/blog/2023-11-15-backstagecon-kubecon-23.mdx b/microsite/blog/2023-11-15-backstagecon-kubecon-23.mdx new file mode 100644 index 0000000000..7b7f7c0f0b --- /dev/null +++ b/microsite/blog/2023-11-15-backstagecon-kubecon-23.mdx @@ -0,0 +1,72 @@ +--- +# prettier-ignore +title: "Wrap up: BackstageCon ‘23, KubeCon + Cloud Native NA" +author: Jorge Lainfiesta, Spotify +authorURL: https://www.linkedin.com/in/jrlainfiesta/ +authorImageURL: https://avatars.githubusercontent.com/u/4451393?v=4 +--- + +![BackstageCon ‘23, KubeCon + Cloud Native NA](assets/23-11-15/00-cover.png) + +tl;dr BackstageCon North America is officially in the books! We had a blast in Chicago talking about Backstage non-stop throughout the week at both BackstageCon and KubeCon. If you weren't able to join us, the [BackstageCon talks are available](https://www.youtube.com/playlist?list=PLj6h78yzYM2PxiInfZi2OKu1KluNfbLtc) for replay on the CNCF YouTube channel. +{/* truncate */} + +Obviously we're biased, but Backstage was definitely one of the big topics at [KubeCon + CloudNativeCon North America](https://events.linuxfoundation.org/kubecon-cloudnativecon-north-america/) this year. Recently, the CNCF announced that Backstage was the [third fastest-growing project](https://www.cncf.io/blog/2023/10/27/october-2023-where-we-are-with-velocity-of-cncf-lf-and-top-30-open-source-projects/) of the year (up from the fifth last year). And you could confirm it with your own eyes during BackstageCon and KubeCon: hundreds of people flocked through the event, talks, and the project booth sharing their enthusiasm and asking more questions about the project. + +### BackstageCon: A growing community  + +With a whopping peak attendance of 400+ people, the crowd nearly doubled from last year,[ taking the center stage of the conference](https://www.forbes.com/sites/janakirammsv/2023/11/14/backstage-project-takes-center-stage-at-kubecon-north-america-2023/?sh=1972303a6539), as reported by Forbes. For some, BackstageCon was their first entry point into the community, but the event also boasted lots of  familiar faces, mostly from some of the most mature adopters such as Dynatrace, Lunar, and US Bank. We also got to hear from new voices in the community like Comcast and Grafana Labs. + +We hear a lot of great questions such as: + +- How do I make more developers use my developer portal? + +- Will generative AI take my Backstage instance to the next level? + +- What's all the fuss around the upcoming Declarative Integration in Backstage? + +The community got together to discuss these and more questions with exciting talks and debates. The talks were all recorded and are [up on YouTube](https://www.youtube.com/playlist?list=PLj6h78yzYM2PxiInfZi2OKu1KluNfbLtc), so make sure to check them out. + +**Driving Backstage adoption** + +Growing adoption was top of mind during BackstageCon. David Tuite, CEO of Roadie, shared the lessons learned from interviewing 20 adopters, which revealed that the Scaffolder was a prime place to get started when adopting Backstage, as it lets stakeholders get an easily measurable ROI. + +![Panel of Backstage adopters](assets/23-11-15/10-panel.jpg) + +Helen Greul, Head of Engineering for Backstage at Spotify, hosted [a panel discussion](https://www.youtube.com/watch?v=Iti5glzYOG8&list=PLj6h78yzYM2PxiInfZi2OKu1KluNfbLtc&index=10) with four adopters that are using Backstage at scale: Twilio, Lunar Bank, US Bank, and Expedia. The crucial role of Backstage in fostering inner sourcing and simplifying new hires onboarding were a few of the subjects covered in the panel. + +How adopters are using Backstage was also a highlight of the day. B3, Brazil's Stock Exchange, shared [how they're building their developer portal](https://www.youtube.com/watch?v=FyWCKIVYO7g&list=PLj6h78yzYM2PxiInfZi2OKu1KluNfbLtc&index=14). And from Grafana Labs, we heard how they're using [Backstage along Crossplane to drive GitOps](https://www.youtube.com/watch?v=q-JUWob69Hw&list=PLj6h78yzYM2PxiInfZi2OKu1KluNfbLtc&index=10). + +**What's next with Backstage?** + +The discussion on how Backstage is evolving was featured in a few talks, through live demos that — remarkably — did not go wrong even once! Ben ([benjdlambert](https://github.com/benjdlambert)) and Patrik ([Rugvip](https://github.com/Rugvip)), core maintainers, presented an introduction to the plans around [Declarative Integration](https://www.youtube.com/watch?v=8hVMNMXXN44&list=PLj6h78yzYM2PxiInfZi2OKu1KluNfbLtc&index=8), which will allow people to install plugins without dealing with TypeScript or React. On the other hand, Djamaile and Mitch, from Spotify, [introduced the upcoming Quickstart](https://www.youtube.com/watch?v=bUdaO9NKXJY&list=PLj6h78yzYM2PxiInfZi2OKu1KluNfbLtc&index=12), a tool from Spotify in private-beta that will allow anyone to get started with Backstage through a GUI in a few steps. + +**A thriving community** + +People gathered outside the conference room where BackstageCon was happening to catch up with each other and learn from the event sponsors. It was great to connect with everyone and talk about how everyone is using Backstage. + +![KubeCon Attendees](assets/23-11-15/20-booth.jpg) + +![Spotify at BackstageCon](assets/23-11-15/30-spotify-kubecon.jpg) + +### Mom, Backstage is not a phase + +The interest from the cloud-native community in Backstage did not waver this year. Instead, the Backstage booth in the KubeCon Project Pavillion saw a nonstop flux of visitors asking more about the project. There were three talks featuring Backstage during KubeCon. + +**Backstage talks during KubeCon NA '23** + +The first talk touching on Backstage of the schedule was Tim Hansen's ([timbonicus](https://github.com/timbonicus)) "Everything Is Code: Embracing GitOps at Spotify," who achieved rockstar status thanks to his phenomenal insights. The queue to ask questions after the talk's questions was surreal! + +![KubeCon Attendees](assets/23-11-15/40-tim-talk.jpg) + +Backstage maintainers Ben and Patrik addressed a full-room during their talk “Simplifying Backstage - Breaking the Code Barrier” in which they explained Declarative Integration, how it works and the expected migration path. Declarative Integration will enable adopters to install the plugins they use—and even customize them—without dealing with TypeScript or React. + +![KubeCon Attendees](assets/23-11-15/50-patrik-ben-full.jpg) + +And to close the event, Ritesh Patel, Nirmata and David Murphy, Upbound, introduced the BACK Stack, which stands for Backstage, Argo, Crossplane, and Kyverno. These four tools make up a powerful combo that can enable self-service workflows secure and scalable. After a great demo, the speakers presented a reference architecture that can help guide an approach to using Backstage to build your platform. + +![KubeCon Attendees](assets/23-11-15/60-back-stack.jpg) + +### See you next year! + +The next KubeCon Europe is scheduled for March 18-22 in Paris. We're looking forward to meeting you all there! [KubeCon EU](https://events.linuxfoundation.org/kubecon-cloudnativecon-europe/program/cfp/) and[ BackstageCon EU](https://events.linuxfoundation.org/kubecon-cloudnativecon-europe/co-located-events/backstagecon/) are accepting CFPs, submit your proposal now! diff --git a/microsite/blog/assets/23-11-15/00-cover.png b/microsite/blog/assets/23-11-15/00-cover.png new file mode 100644 index 0000000000..18da63a930 Binary files /dev/null and b/microsite/blog/assets/23-11-15/00-cover.png differ diff --git a/microsite/blog/assets/23-11-15/10-panel.jpg b/microsite/blog/assets/23-11-15/10-panel.jpg new file mode 100644 index 0000000000..a6ebf8dcae Binary files /dev/null and b/microsite/blog/assets/23-11-15/10-panel.jpg differ diff --git a/microsite/blog/assets/23-11-15/20-booth.jpg b/microsite/blog/assets/23-11-15/20-booth.jpg new file mode 100644 index 0000000000..4faa5a5f1f Binary files /dev/null and b/microsite/blog/assets/23-11-15/20-booth.jpg differ diff --git a/microsite/blog/assets/23-11-15/30-spotify-kubecon.jpg b/microsite/blog/assets/23-11-15/30-spotify-kubecon.jpg new file mode 100644 index 0000000000..fa64ec451f Binary files /dev/null and b/microsite/blog/assets/23-11-15/30-spotify-kubecon.jpg differ diff --git a/microsite/blog/assets/23-11-15/40-tim-talk.jpg b/microsite/blog/assets/23-11-15/40-tim-talk.jpg new file mode 100644 index 0000000000..73873bcb4c Binary files /dev/null and b/microsite/blog/assets/23-11-15/40-tim-talk.jpg differ diff --git a/microsite/blog/assets/23-11-15/50-patrik-ben-full.jpg b/microsite/blog/assets/23-11-15/50-patrik-ben-full.jpg new file mode 100644 index 0000000000..2048dd2f5a Binary files /dev/null and b/microsite/blog/assets/23-11-15/50-patrik-ben-full.jpg differ diff --git a/microsite/blog/assets/23-11-15/60-back-stack.jpg b/microsite/blog/assets/23-11-15/60-back-stack.jpg new file mode 100644 index 0000000000..668fc407da Binary files /dev/null and b/microsite/blog/assets/23-11-15/60-back-stack.jpg differ diff --git a/microsite/data/plugins/circleci.yaml b/microsite/data/plugins/circleci.yaml index 5d7978624b..5980f8cf45 100644 --- a/microsite/data/plugins/circleci.yaml +++ b/microsite/data/plugins/circleci.yaml @@ -1,12 +1,12 @@ --- title: CircleCI -author: Spotify -authorUrl: https://github.com/spotify +author: CircleCI +authorUrl: https://circleci.com/ category: CI/CD description: Automate your development process with CI hosted in the cloud or on a private server. -documentation: https://github.com/backstage/backstage/tree/master/plugins/circleci +documentation: https://github.com/CircleCI-Public/backstage-plugin/tree/main/plugins/circleci iconUrl: /img/circleci.png -npmPackageName: '@backstage/plugin-circleci' +npmPackageName: '@circleci/backstage-plugin' tags: - ci - cd diff --git a/microsite/data/plugins/festive-fun.yaml b/microsite/data/plugins/festive-fun.yaml new file mode 100644 index 0000000000..33995eca27 --- /dev/null +++ b/microsite/data/plugins/festive-fun.yaml @@ -0,0 +1,10 @@ +--- +title: Festive Fun +author: benjmac +authorUrl: https://github.com/benjmac +category: Humor +description: Festive, seasonal, animations to spice up your instance of Backstage! +documentation: https://github.com/benjmac/backstage-plugin-festive-fun/ +iconUrl: https://raw.githubusercontent.com/benjmac/backstage-plugin-festive-fun/main/docs/festive-fun-logo.png +npmPackageName: 'backstage-plugin-festive-fun' +addedDate: '2023-11-20' diff --git a/microsite/data/plugins/harness-srm.yaml b/microsite/data/plugins/harness-srm.yaml new file mode 100644 index 0000000000..d55c60ea04 --- /dev/null +++ b/microsite/data/plugins/harness-srm.yaml @@ -0,0 +1,14 @@ +--- +title: Harness Service Reliability Management +author: harness.io +authorUrl: https://github.com/harness/backstage-plugins +category: Quality +description: This plugin tracks the defined SLOs and Error Budgets for your Monitored services in Harness SRM Module. +documentation: https://github.com/harness/backstage-plugins/tree/main/plugins/harness-srm +iconUrl: https://static.harness.io/ng-static/images/favicon.png +npmPackageName: '@harnessio/backstage-plugin-harness-srm' +tags: + - service-reliability-management + - slo + - sli +addedDate: '2023-11-17' diff --git a/microsite/data/plugins/hcp-consul.yaml b/microsite/data/plugins/hcp-consul.yaml new file mode 100644 index 0000000000..6dabad582e --- /dev/null +++ b/microsite/data/plugins/hcp-consul.yaml @@ -0,0 +1,10 @@ +--- +title: HCP Consul +author: Hashicorp +authorUrl: https://www.hashicorp.com/ +category: Infrastructure +description: View your HCP Consul clusters, services, instances in Backstage. +documentation: https://github.com/hashicorp-forge/backstage-plugin-hcp-consul/tree/main +iconUrl: /img/hcp-consul.svg +npmPackageName: '@hashicorp/plugin-hcp-consul' +addedDate: '2023-11-24' diff --git a/microsite/data/plugins/highlights.yaml b/microsite/data/plugins/highlights.yaml new file mode 100644 index 0000000000..82d303f4ed --- /dev/null +++ b/microsite/data/plugins/highlights.yaml @@ -0,0 +1,12 @@ +--- +title: Highlights +author: RSC Labs +authorUrl: https://rsoftcon.com/ +category: Discovery +description: Highlight what is important for you and put it on front for the quick view and access. Built-in support of Git information from GitHub and GitLab. +documentation: https://github.com/RSC-Labs/backstage-highlights-plugin/blob/main/README.md +iconUrl: https://raw.githubusercontent.com/RSC-Labs/backstage-highlights-plugin/main/docs/highlighter.png +npmPackageName: '@rsc-labs/backstage-highlights-plugin' +tags: + - highlights +addedDate: '2023-11-20' diff --git a/microsite/data/plugins/jira-dashboard b/microsite/data/plugins/jira-dashboard new file mode 100644 index 0000000000..2e67deb4a9 --- /dev/null +++ b/microsite/data/plugins/jira-dashboard @@ -0,0 +1,10 @@ +--- +title: Jira Dashboard +author: AxisCommunications +authorUrl: https://github.com/AxisCommunications +category: Agile Planning +description: Allows you to fetch and display Jira issues for your entity. You get quickly access to issue summaries to achieve better task visibility and more efficient project management. +documentation: https://github.com/AxisCommunications/backstage-plugins/blob/main/plugins/jira-dashboard/README.md +iconUrl: https://github.com/AxisCommunications/backstage-plugins/blob/main/plugins/jira-dashboard/media/jira-logo.png +npmPackageName: '@axis-backstage/plugin-jira-dashboard' +addedDate: '2023-11-29' diff --git a/microsite/data/plugins/scaffolder-backend-slack.yaml b/microsite/data/plugins/scaffolder-backend-slack.yaml index dce7b60eb7..a726751eaf 100644 --- a/microsite/data/plugins/scaffolder-backend-slack.yaml +++ b/microsite/data/plugins/scaffolder-backend-slack.yaml @@ -5,6 +5,6 @@ authorUrl: https://github.com/arhill05 category: Scaffolder description: Interact with Slack from scaffolder templates documentation: https://github.com/arhill05/backstage-plugin-scaffolder-backend-module-slack#readme -iconUrl: img/Slack-mark-RGB.png +iconUrl: /img/Slack-mark-RGB.png npmPackageName: '@mdude2314/backstage-plugin-scaffolder-backend-module-slack' addedDate: '2023-08-04' diff --git a/microsite/data/plugins/search-backend-module-azure-devops-wiki.yaml b/microsite/data/plugins/search-backend-module-azure-devops-wiki.yaml index 02d4131cce..cc8849ee08 100644 --- a/microsite/data/plugins/search-backend-module-azure-devops-wiki.yaml +++ b/microsite/data/plugins/search-backend-module-azure-devops-wiki.yaml @@ -5,6 +5,6 @@ authorUrl: https://github.com/arhill05 category: Search description: Index wiki articles from an Azure DevOps wiki into Backstage to allow you to search them with the Backstage Search feature. documentation: https://github.com/arhill05/backstage-plugin-search-backend-module-azure-devops-wiki#readme -iconUrl: img/ado-wiki-search-icon.png +iconUrl: /img/ado-wiki-search-icon.png npmPackageName: '@mdude2314/backstage-plugin-search-backend-module-azure-devops-wiki' addedDate: '2023-06-13' diff --git a/microsite/docusaurus.config.js b/microsite/docusaurus.config.js index 7a01498646..99f58d29cb 100644 --- a/microsite/docusaurus.config.js +++ b/microsite/docusaurus.config.js @@ -140,6 +140,10 @@ module.exports = { from: '/docs/getting-started/running-backstage-locally', to: '/docs/getting-started/', }, + { + from: '/docs/features/software-templates/testing-scaffolder-alpha', + to: '/docs/features/software-templates/migrating-to-rjsf-v5', + }, ], }, ], diff --git a/microsite/package.json b/microsite/package.json index 61bfcbd04a..eb4d6bccb2 100644 --- a/microsite/package.json +++ b/microsite/package.json @@ -33,7 +33,7 @@ "@docusaurus/plugin-client-redirects": "0.0.0-5703", "@docusaurus/preset-classic": "0.0.0-5703", "@swc/core": "^1.3.46", - "clsx": "^1.1.1", + "clsx": "^2.0.0", "docusaurus-plugin-sass": "^0.2.3", "luxon": "^3.0.0", "prism-react-renderer": "^1.3.5", diff --git a/microsite/sidebars.json b/microsite/sidebars.json index c9b1c99eba..fb513697cb 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -408,7 +408,8 @@ "tutorials/configuring-plugin-databases", "tutorials/switching-sqlite-postgres", "tutorials/using-backstage-proxy-within-plugin", - "tutorials/yarn-migration" + "tutorials/yarn-migration", + "tutorials/migrate-to-mui5" ], "Architecture Decision Records (ADRs)": [ "architecture-decisions/adrs-overview", diff --git a/microsite/static/img/hcp-consul.svg b/microsite/static/img/hcp-consul.svg new file mode 100644 index 0000000000..d84972585c --- /dev/null +++ b/microsite/static/img/hcp-consul.svg @@ -0,0 +1,17 @@ + +Consul Logo + + + + + + + + + + + + + + + diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 10ad6d0d68..6df5247272 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -2701,90 +2701,82 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-darwin-arm64@npm:1.3.96" +"@swc/core-darwin-arm64@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-darwin-arm64@npm:1.3.100" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-darwin-x64@npm:1.3.96" +"@swc/core-darwin-x64@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-darwin-x64@npm:1.3.100" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.96" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@swc/core-linux-arm64-gnu@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.96" +"@swc/core-linux-arm64-gnu@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.100" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.96" +"@swc/core-linux-arm64-musl@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.100" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.96" +"@swc/core-linux-x64-gnu@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.100" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-x64-musl@npm:1.3.96" +"@swc/core-linux-x64-musl@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-linux-x64-musl@npm:1.3.100" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.96" +"@swc/core-win32-arm64-msvc@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.100" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.96" +"@swc/core-win32-ia32-msvc@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.100" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.96" +"@swc/core-win32-x64-msvc@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.100" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.46": - version: 1.3.96 - resolution: "@swc/core@npm:1.3.96" + version: 1.3.100 + resolution: "@swc/core@npm:1.3.100" dependencies: - "@swc/core-darwin-arm64": 1.3.96 - "@swc/core-darwin-x64": 1.3.96 - "@swc/core-linux-arm-gnueabihf": 1.3.96 - "@swc/core-linux-arm64-gnu": 1.3.96 - "@swc/core-linux-arm64-musl": 1.3.96 - "@swc/core-linux-x64-gnu": 1.3.96 - "@swc/core-linux-x64-musl": 1.3.96 - "@swc/core-win32-arm64-msvc": 1.3.96 - "@swc/core-win32-ia32-msvc": 1.3.96 - "@swc/core-win32-x64-msvc": 1.3.96 + "@swc/core-darwin-arm64": 1.3.100 + "@swc/core-darwin-x64": 1.3.100 + "@swc/core-linux-arm64-gnu": 1.3.100 + "@swc/core-linux-arm64-musl": 1.3.100 + "@swc/core-linux-x64-gnu": 1.3.100 + "@swc/core-linux-x64-musl": 1.3.100 + "@swc/core-win32-arm64-msvc": 1.3.100 + "@swc/core-win32-ia32-msvc": 1.3.100 + "@swc/core-win32-x64-msvc": 1.3.100 "@swc/counter": ^0.1.1 "@swc/types": ^0.1.5 peerDependencies: @@ -2794,8 +2786,6 @@ __metadata: optional: true "@swc/core-darwin-x64": optional: true - "@swc/core-linux-arm-gnueabihf": - optional: true "@swc/core-linux-arm64-gnu": optional: true "@swc/core-linux-arm64-musl": @@ -2813,7 +2803,7 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 41d4a4461b2952aaf8d3be945d373d0f3bd126115ee1aad0f76f2690e2b5635b6ec5bb54a7638deb9afedb1ad6f7d8453468a704e54e5fbb8234dd4a43b80205 + checksum: b68553db388c36b1859f0e8b5231a608277e17ae7fd7a928ea8b448432532176914f84675426d40aa9710617b2e7fb626aaa8358b6b2506b3c43f82db725c41e languageName: node linkType: hard @@ -3055,9 +3045,9 @@ __metadata: linkType: hard "@types/luxon@npm:^3.0.0": - version: 3.3.4 - resolution: "@types/luxon@npm:3.3.4" - checksum: aa4862bd62d748e7966f9a0ec76058e9d74397ee426c7d64f61c677d83de0303c303cc78515001833df3f4ad16c95f572b0e2ffaee6e55bc50b80857e8437f3a + version: 3.3.6 + resolution: "@types/luxon@npm:3.3.6" + checksum: 44fd3e617fb5d9e370a8d5529de3e703b295bfe225936e786e0b5e7fce662ef82012a6ec29cd2763afbd59bf9a9ab43186bad5c51aa552d963cd5e8c8f4e1d4f languageName: node linkType: hard @@ -3897,7 +3887,7 @@ __metadata: "@tsconfig/docusaurus": ^2.0.0 "@types/luxon": ^3.0.0 "@types/webpack-env": ^1.18.0 - clsx: ^1.1.1 + clsx: ^2.0.0 docusaurus-plugin-sass: ^0.2.3 js-yaml: ^4.1.0 luxon: ^3.0.0 @@ -4375,13 +4365,20 @@ __metadata: languageName: node linkType: hard -"clsx@npm:^1.1.1, clsx@npm:^1.2.1": +"clsx@npm:^1.2.1": version: 1.2.1 resolution: "clsx@npm:1.2.1" checksum: 30befca8019b2eb7dbad38cff6266cf543091dae2825c856a62a8ccf2c3ab9c2907c4d12b288b73101196767f66812365400a227581484a05f968b0307cfaf12 languageName: node linkType: hard +"clsx@npm:^2.0.0": + version: 2.0.0 + resolution: "clsx@npm:2.0.0" + checksum: a2cfb2351b254611acf92faa0daf15220f4cd648bdf96ce369d729813b85336993871a4bf6978ddea2b81b5a130478339c20d9d0b5c6fc287e5147f0c059276e + languageName: node + linkType: hard + "color-convert@npm:^1.9.0": version: 1.9.3 resolution: "color-convert@npm:1.9.3" diff --git a/mkdocs.yml b/mkdocs.yml index de66c97884..d4735c63fc 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -193,6 +193,7 @@ nav: - Switching Backstage from SQLite to PostgreSQL: 'tutorials/switching-sqlite-postgres.md' - Using the Backstage Proxy from Within a Plugin: 'tutorials/using-backstage-proxy-within-plugin.md' - Migration to Yarn 3: 'tutorials/yarn-migration.md' + - Migration to Material UI v5: 'tutorials/migrate-to-mui5.md' - Architecture Decision Records (ADRs): - Overview: 'architecture-decisions/index.md' - ADR001 - Architecture Decision Record (ADR) log: 'architecture-decisions/adr001-add-adr-log.md' diff --git a/package.json b/package.json index 0573e7c136..c19dea9d3b 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "@material-ui/pickers@^3.3.10": "patch:@material-ui/pickers@npm%3A3.3.11#./.yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch", "@material-ui/pickers@^3.2.10": "patch:@material-ui/pickers@npm%3A3.3.11#./.yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch" }, - "version": "1.20.0", + "version": "1.21.0-next.3", "dependencies": { "@backstage/errors": "workspace:^", "@manypkg/get-packages": "^1.1.3", @@ -91,7 +91,7 @@ "semver": "^7.5.3", "shx": "^0.3.2", "ts-node": "^10.4.0", - "typescript": "~5.0.0" + "typescript": "~5.2.0" }, "prettier": "@spotify/prettier-config", "lint-staged": { diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index 7bf0fa633a..3db36e9591 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/app-defaults +## 1.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + +## 1.4.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/theme@0.5.0-next.0 + +## 1.4.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + ## 1.4.5 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 37a8dc35b3..a1301a29c5 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/app-defaults", "description": "Provides the default wiring of a Backstage App", - "version": "1.4.5", + "version": "1.4.6-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/app-next-example-plugin/CHANGELOG.md b/packages/app-next-example-plugin/CHANGELOG.md index c3411cd0f4..9467dd00f0 100644 --- a/packages/app-next-example-plugin/CHANGELOG.md +++ b/packages/app-next-example-plugin/CHANGELOG.md @@ -1,5 +1,29 @@ # app-next-example-plugin +## 0.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/core-components@0.13.9-next.2 + +## 0.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + +## 0.0.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + ## 0.0.3 ### Patch Changes diff --git a/packages/app-next-example-plugin/package.json b/packages/app-next-example-plugin/package.json index b72626580e..689d90e264 100644 --- a/packages/app-next-example-plugin/package.json +++ b/packages/app-next-example-plugin/package.json @@ -1,7 +1,7 @@ { "name": "app-next-example-plugin", "description": "Backstage internal example plugin", - "version": "0.0.3", + "version": "0.0.4-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/app-next-example-plugin/src/plugin.tsx b/packages/app-next-example-plugin/src/plugin.tsx index a3c95e900c..99c377b7e5 100644 --- a/packages/app-next-example-plugin/src/plugin.tsx +++ b/packages/app-next-example-plugin/src/plugin.tsx @@ -21,7 +21,6 @@ import { } from '@backstage/frontend-plugin-api'; export const ExamplePage = createPageExtension({ - id: 'example.page', defaultPath: '/example', loader: () => import('./Component').then(m => ), }); diff --git a/packages/app-next/CHANGELOG.md b/packages/app-next/CHANGELOG.md index 07933071c5..bf7b61d510 100644 --- a/packages/app-next/CHANGELOG.md +++ b/packages/app-next/CHANGELOG.md @@ -1,5 +1,255 @@ # example-app-next +## 0.0.4-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/frontend-app-api@0.4.0-next.2 + - @backstage/cli@0.25.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-kubernetes@0.11.3-next.2 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/plugin-lighthouse@0.4.13-next.2 + - @backstage/plugin-catalog-import@0.10.4-next.3 + - @backstage/plugin-user-settings@0.7.14-next.3 + - @backstage/plugin-tech-radar@0.6.11-next.3 + - @backstage/plugin-graphiql@0.3.1-next.3 + - @backstage/plugin-techdocs@1.9.2-next.3 + - @backstage/plugin-catalog@1.16.0-next.3 + - @backstage/plugin-search@1.4.4-next.3 + - @backstage/plugin-home@0.6.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/plugin-explore@0.4.14-next.2 + - @backstage/plugin-adr@0.6.11-next.2 + - @backstage/plugin-scaffolder-react@1.6.2-next.2 + - app-next-example-plugin@0.0.4-next.2 + - @backstage/app-defaults@1.4.6-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-airbrake@0.3.28-next.2 + - @backstage/plugin-apache-airflow@0.2.18-next.2 + - @backstage/plugin-api-docs@0.10.2-next.3 + - @backstage/plugin-azure-devops@0.3.10-next.2 + - @backstage/plugin-azure-sites@0.1.17-next.2 + - @backstage/plugin-badges@0.2.52-next.2 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-graph@0.3.2-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.2 + - @backstage/plugin-cloudbuild@0.3.28-next.2 + - @backstage/plugin-code-coverage@0.2.21-next.2 + - @backstage/plugin-cost-insights@0.12.17-next.2 + - @backstage/plugin-devtools@0.1.7-next.2 + - @backstage/plugin-dynatrace@8.0.2-next.2 + - @backstage/plugin-entity-feedback@0.2.11-next.2 + - @backstage/plugin-gcalendar@0.3.21-next.2 + - @backstage/plugin-gcp-projects@0.3.44-next.2 + - @backstage/plugin-github-actions@0.6.9-next.2 + - @backstage/plugin-gocd@0.1.34-next.2 + - @backstage/plugin-jenkins@0.9.3-next.2 + - @backstage/plugin-kafka@0.3.28-next.2 + - @backstage/plugin-linguist@0.1.13-next.2 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-microsoft-calendar@0.1.10-next.2 + - @backstage/plugin-newrelic@0.3.43-next.2 + - @backstage/plugin-newrelic-dashboard@0.3.3-next.2 + - @backstage/plugin-octopus-deploy@0.2.10-next.2 + - @backstage/plugin-org@0.6.18-next.2 + - @backstage/plugin-pagerduty@0.7.0-next.2 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/plugin-playlist@0.2.2-next.2 + - @backstage/plugin-puppetdb@0.1.11-next.2 + - @backstage/plugin-rollbar@0.4.28-next.2 + - @backstage/plugin-scaffolder@1.16.2-next.2 + - @backstage/plugin-search-common@1.2.8 + - @backstage/plugin-sentry@0.5.13-next.2 + - @backstage/plugin-shortcuts@0.3.17-next.2 + - @backstage/plugin-stackstorm@0.1.9-next.2 + - @backstage/plugin-tech-insights@0.3.20-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.2 + - @backstage/plugin-techdocs-react@1.1.14-next.2 + - @backstage/plugin-todo@0.2.32-next.2 + +## 0.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/frontend-app-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/cli@0.25.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-catalog@1.16.0-next.2 + - @backstage/plugin-scaffolder-react@1.6.2-next.1 + - @backstage/plugin-home@0.6.0-next.1 + - @backstage/plugin-github-actions@0.6.9-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/plugin-azure-devops@0.3.10-next.1 + - @backstage/plugin-scaffolder@1.16.2-next.1 + - @backstage/plugin-api-docs@0.10.2-next.2 + - @backstage/plugin-gcp-projects@0.3.44-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.1 + - @backstage/plugin-user-settings@0.7.14-next.2 + - @backstage/plugin-adr@0.6.11-next.1 + - @backstage/plugin-pagerduty@0.7.0-next.1 + - app-next-example-plugin@0.0.4-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/plugin-catalog-import@0.10.4-next.2 + - @backstage/plugin-explore@0.4.14-next.1 + - @backstage/plugin-graphiql@0.3.1-next.2 + - @backstage/plugin-search@1.4.4-next.2 + - @backstage/plugin-tech-radar@0.6.11-next.2 + - @backstage/plugin-techdocs@1.9.2-next.2 + - @backstage/app-defaults@1.4.6-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-airbrake@0.3.28-next.1 + - @backstage/plugin-apache-airflow@0.2.18-next.1 + - @backstage/plugin-azure-sites@0.1.17-next.1 + - @backstage/plugin-badges@0.2.52-next.1 + - @backstage/plugin-catalog-graph@0.3.2-next.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.1 + - @backstage/plugin-cloudbuild@0.3.28-next.1 + - @backstage/plugin-code-coverage@0.2.21-next.1 + - @backstage/plugin-cost-insights@0.12.17-next.1 + - @backstage/plugin-devtools@0.1.7-next.1 + - @backstage/plugin-dynatrace@8.0.2-next.1 + - @backstage/plugin-entity-feedback@0.2.11-next.1 + - @backstage/plugin-gcalendar@0.3.21-next.1 + - @backstage/plugin-gocd@0.1.34-next.1 + - @backstage/plugin-jenkins@0.9.3-next.1 + - @backstage/plugin-kafka@0.3.28-next.1 + - @backstage/plugin-kubernetes@0.11.3-next.1 + - @backstage/plugin-lighthouse@0.4.13-next.1 + - @backstage/plugin-linguist@0.1.13-next.1 + - @backstage/plugin-microsoft-calendar@0.1.10-next.1 + - @backstage/plugin-newrelic@0.3.43-next.1 + - @backstage/plugin-newrelic-dashboard@0.3.3-next.1 + - @backstage/plugin-octopus-deploy@0.2.10-next.1 + - @backstage/plugin-org@0.6.18-next.1 + - @backstage/plugin-playlist@0.2.2-next.1 + - @backstage/plugin-puppetdb@0.1.11-next.1 + - @backstage/plugin-rollbar@0.4.28-next.1 + - @backstage/plugin-sentry@0.5.13-next.1 + - @backstage/plugin-shortcuts@0.3.17-next.1 + - @backstage/plugin-stackstorm@0.1.9-next.1 + - @backstage/plugin-tech-insights@0.3.20-next.1 + - @backstage/plugin-techdocs-react@1.1.14-next.1 + - @backstage/plugin-todo@0.2.32-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.8 + +## 0.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + - @backstage/plugin-catalog@1.16.0-next.1 + - @backstage/plugin-catalog-import@0.10.4-next.1 + - @backstage/plugin-graphiql@0.3.1-next.1 + - @backstage/plugin-search@1.4.4-next.1 + - @backstage/plugin-tech-radar@0.6.11-next.1 + - @backstage/plugin-techdocs@1.9.2-next.1 + - @backstage/plugin-user-settings@0.7.14-next.1 + - @backstage/plugin-api-docs@0.10.2-next.1 + - @backstage/plugin-catalog-graph@0.3.2-next.0 + - @backstage/plugin-explore@0.4.14-next.0 + - @backstage/plugin-org@0.6.18-next.0 + - @backstage/plugin-scaffolder@1.16.2-next.0 + - @backstage/plugin-scaffolder-react@1.6.2-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.0 + +## 0.0.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/plugin-api-docs@0.10.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-scaffolder@1.16.2-next.0 + - @backstage/plugin-catalog@1.16.0-next.0 + - @backstage/frontend-app-api@0.3.1-next.0 + - @backstage/plugin-org@0.6.18-next.0 + - @backstage/plugin-scaffolder-react@1.6.2-next.0 + - @backstage/plugin-catalog-import@0.10.4-next.0 + - @backstage/plugin-user-settings@0.7.14-next.0 + - @backstage/plugin-tech-radar@0.6.11-next.0 + - @backstage/plugin-graphiql@0.3.1-next.0 + - @backstage/plugin-techdocs@1.9.2-next.0 + - @backstage/plugin-search@1.4.4-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/cli@0.24.1-next.0 + - @backstage/plugin-home@0.5.12-next.0 + - @backstage/plugin-kubernetes@0.11.3-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/app-defaults@1.4.6-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/plugin-adr@0.6.11-next.0 + - @backstage/plugin-airbrake@0.3.28-next.0 + - @backstage/plugin-apache-airflow@0.2.18-next.0 + - @backstage/plugin-azure-devops@0.3.10-next.0 + - @backstage/plugin-azure-sites@0.1.17-next.0 + - @backstage/plugin-badges@0.2.52-next.0 + - @backstage/plugin-catalog-graph@0.3.2-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.0 + - @backstage/plugin-circleci@0.3.28-next.0 + - @backstage/plugin-cloudbuild@0.3.28-next.0 + - @backstage/plugin-code-coverage@0.2.21-next.0 + - @backstage/plugin-cost-insights@0.12.17-next.0 + - @backstage/plugin-devtools@0.1.7-next.0 + - @backstage/plugin-dynatrace@8.0.2-next.0 + - @backstage/plugin-entity-feedback@0.2.11-next.0 + - @backstage/plugin-explore@0.4.14-next.0 + - @backstage/plugin-gcalendar@0.3.21-next.0 + - @backstage/plugin-gcp-projects@0.3.44-next.0 + - @backstage/plugin-github-actions@0.6.9-next.0 + - @backstage/plugin-gocd@0.1.34-next.0 + - @backstage/plugin-jenkins@0.9.3-next.0 + - @backstage/plugin-kafka@0.3.28-next.0 + - @backstage/plugin-lighthouse@0.4.13-next.0 + - @backstage/plugin-linguist@0.1.13-next.0 + - @backstage/plugin-microsoft-calendar@0.1.10-next.0 + - @backstage/plugin-newrelic@0.3.43-next.0 + - @backstage/plugin-newrelic-dashboard@0.3.3-next.0 + - @backstage/plugin-octopus-deploy@0.2.10-next.0 + - @backstage/plugin-pagerduty@0.6.9-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + - @backstage/plugin-playlist@0.2.2-next.0 + - @backstage/plugin-puppetdb@0.1.11-next.0 + - @backstage/plugin-rollbar@0.4.28-next.0 + - @backstage/plugin-sentry@0.5.13-next.0 + - @backstage/plugin-shortcuts@0.3.17-next.0 + - @backstage/plugin-stackstorm@0.1.9-next.0 + - @backstage/plugin-tech-insights@0.3.20-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.0 + - @backstage/plugin-techdocs-react@1.1.14-next.0 + - @backstage/plugin-todo@0.2.32-next.0 + - app-next-example-plugin@0.0.4-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.8 + ## 0.0.3 ### Patch Changes diff --git a/packages/app-next/app-config.yaml b/packages/app-next/app-config.yaml index a46e119ac0..3eaab2fa1a 100644 --- a/packages/app-next/app-config.yaml +++ b/packages/app-next/app-config.yaml @@ -7,18 +7,17 @@ app: plugin.catalog.externalRoutes.viewTechDoc: plugin.techdocs.routes.docRoot extensions: - - apis.plugin.graphiql.browse.gitlab: true + # - apis.plugin.graphiql.browse.gitlab: true + - graphiql-endpoint:graphiql/gitlab: true - # Entity page cards - - entity.cards.about - - entity.cards.labels - - entity.cards.links: + - entity-card:catalog/about + - entity-card:catalog/labels + - entity-card:catalog/links: config: - filter: - - isKind: component + filter: kind:component has:links # Entity page content - - entity.content.techdocs + - entity-content:techdocs # scmAuthExtension: >- # createScmAuthExtension({ diff --git a/packages/app-next/package.json b/packages/app-next/package.json index 6e0581d034..276ae4e527 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -1,6 +1,6 @@ { "name": "example-app-next", - "version": "0.0.3", + "version": "0.0.4-next.3", "private": true, "backstage": { "role": "frontend" @@ -31,7 +31,6 @@ "@backstage/plugin-catalog-import": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@backstage/plugin-catalog-unprocessed-entities": "workspace:^", - "@backstage/plugin-circleci": "workspace:^", "@backstage/plugin-cloudbuild": "workspace:^", "@backstage/plugin-code-coverage": "workspace:^", "@backstage/plugin-cost-insights": "workspace:^", @@ -77,6 +76,7 @@ "@backstage/plugin-todo": "workspace:^", "@backstage/plugin-user-settings": "workspace:^", "@backstage/theme": "workspace:^", + "@circleci/backstage-plugin": "^0.1.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index 978c40ef44..d7ec30bf95 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -17,6 +17,7 @@ import React from 'react'; import { createApp } from '@backstage/frontend-app-api'; import { pagesPlugin } from './examples/pagesPlugin'; +import notFoundErrorPage from './examples/notFoundErrorPageExtension'; import graphiqlPlugin from '@backstage/plugin-graphiql/alpha'; import techRadarPlugin from '@backstage/plugin-tech-radar/alpha'; import userSettingsPlugin from '@backstage/plugin-user-settings/alpha'; @@ -36,12 +37,18 @@ import { collectLegacyRoutes } from '@backstage/core-compat-api'; import { FlatRoutes } from '@backstage/core-app-api'; import { Route } from 'react-router'; import { CatalogImportPage } from '@backstage/plugin-catalog-import'; -import { createApiFactory, configApiRef } from '@backstage/core-plugin-api'; +import { + createApiFactory, + configApiRef, + SignInPageProps, +} from '@backstage/core-plugin-api'; import { ScmAuth, ScmIntegrationsApi, scmIntegrationsApiRef, } from '@backstage/integration-react'; +import { createSignInPageExtension } from '@backstage/frontend-plugin-api'; +import { SignInPage } from '@backstage/core-components'; /* @@ -73,7 +80,7 @@ TODO: /* app.tsx */ const homePageExtension = createExtension({ - id: 'myhomepage', + name: 'myhomepage', attachTo: { id: 'home', input: 'props' }, output: { children: coreExtensionData.reactElement, @@ -84,6 +91,12 @@ const homePageExtension = createExtension({ }, }); +const signInPage = createSignInPageExtension({ + name: 'guest', + loader: async () => (props: SignInPageProps) => + , +}); + const scmAuthExtension = createApiExtension({ factory: ScmAuth.createDefaultApiFactory(), }); @@ -112,7 +125,13 @@ const app = createApp({ homePlugin, ...collectedLegacyPlugins, createExtensionOverrides({ - extensions: [homePageExtension, scmAuthExtension, scmIntegrationApi], + extensions: [ + homePageExtension, + scmAuthExtension, + scmIntegrationApi, + signInPage, + notFoundErrorPage, + ], }), ], /* Handled through config instead */ diff --git a/packages/app-next/src/examples/notFoundErrorPageExtension.tsx b/packages/app-next/src/examples/notFoundErrorPageExtension.tsx new file mode 100644 index 0000000000..06e9b50bb8 --- /dev/null +++ b/packages/app-next/src/examples/notFoundErrorPageExtension.tsx @@ -0,0 +1,56 @@ +/* + * 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. + */ + +import React from 'react'; +import { + createComponentExtension, + coreComponentRefs, +} from '@backstage/frontend-plugin-api'; +import { Box, Typography } from '@material-ui/core'; +import { Button } from '@backstage/core-components'; + +export function CustomNotFoundErrorPage() { + return ( + + 404 + + Unable to locate this page. Please contact your support team if this + page used to exist. + + + + ); +} + +export default createComponentExtension({ + ref: coreComponentRefs.notFoundErrorPage, + component: { sync: () => CustomNotFoundErrorPage }, +}); diff --git a/packages/app-next/src/examples/pagesPlugin.tsx b/packages/app-next/src/examples/pagesPlugin.tsx index 1e9409a5e4..c5069f99c3 100644 --- a/packages/app-next/src/examples/pagesPlugin.tsx +++ b/packages/app-next/src/examples/pagesPlugin.tsx @@ -36,7 +36,7 @@ export const pageXRouteRef = createRouteRef(); // }); const IndexPage = createPageExtension({ - id: 'index', + name: 'index', defaultPath: '/', routeRef: indexRouteRef, loader: async () => { @@ -68,7 +68,7 @@ const IndexPage = createPageExtension({ }); const Page1 = createPageExtension({ - id: 'page1', + name: 'page1', defaultPath: '/page1', routeRef: page1RouteRef, loader: async () => { @@ -102,7 +102,7 @@ const Page1 = createPageExtension({ }); const ExternalPage = createPageExtension({ - id: 'pageX', + name: 'pageX', defaultPath: '/pageX', routeRef: pageXRouteRef, loader: async () => { diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 6288eba0c3..159468d4ef 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,254 @@ # example-app +## 0.2.90-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.4.0-next.2 + - @backstage/cli@0.25.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-kubernetes@0.11.3-next.2 + - @backstage/plugin-lighthouse@0.4.13-next.2 + - @backstage/plugin-catalog-import@0.10.4-next.3 + - @backstage/plugin-user-settings@0.7.14-next.3 + - @backstage/plugin-tech-radar@0.6.11-next.3 + - @backstage/plugin-graphiql@0.3.1-next.3 + - @backstage/plugin-techdocs@1.9.2-next.3 + - @backstage/plugin-catalog@1.16.0-next.3 + - @backstage/plugin-search@1.4.4-next.3 + - @backstage/plugin-home@0.6.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-stack-overflow@0.1.23-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/plugin-explore@0.4.14-next.2 + - @backstage/plugin-adr@0.6.11-next.2 + - @backstage/plugin-scaffolder-react@1.6.2-next.2 + - @backstage/app-defaults@1.4.6-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-airbrake@0.3.28-next.2 + - @backstage/plugin-apache-airflow@0.2.18-next.2 + - @backstage/plugin-api-docs@0.10.2-next.3 + - @backstage/plugin-azure-devops@0.3.10-next.2 + - @backstage/plugin-azure-sites@0.1.17-next.2 + - @backstage/plugin-badges@0.2.52-next.2 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-graph@0.3.2-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.2 + - @backstage/plugin-cloudbuild@0.3.28-next.2 + - @backstage/plugin-code-coverage@0.2.21-next.2 + - @backstage/plugin-cost-insights@0.12.17-next.2 + - @backstage/plugin-devtools@0.1.7-next.2 + - @backstage/plugin-dynatrace@8.0.2-next.2 + - @backstage/plugin-entity-feedback@0.2.11-next.2 + - @backstage/plugin-gcalendar@0.3.21-next.2 + - @backstage/plugin-gcp-projects@0.3.44-next.2 + - @backstage/plugin-github-actions@0.6.9-next.2 + - @backstage/plugin-gocd@0.1.34-next.2 + - @backstage/plugin-jenkins@0.9.3-next.2 + - @backstage/plugin-kafka@0.3.28-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.4-next.2 + - @backstage/plugin-linguist@0.1.13-next.2 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-microsoft-calendar@0.1.10-next.2 + - @backstage/plugin-newrelic@0.3.43-next.2 + - @backstage/plugin-newrelic-dashboard@0.3.3-next.2 + - @backstage/plugin-nomad@0.1.9-next.2 + - @backstage/plugin-octopus-deploy@0.2.10-next.2 + - @backstage/plugin-org@0.6.18-next.2 + - @backstage/plugin-pagerduty@0.7.0-next.2 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/plugin-playlist@0.2.2-next.2 + - @backstage/plugin-puppetdb@0.1.11-next.2 + - @backstage/plugin-rollbar@0.4.28-next.2 + - @backstage/plugin-scaffolder@1.16.2-next.2 + - @backstage/plugin-search-common@1.2.8 + - @backstage/plugin-sentry@0.5.13-next.2 + - @backstage/plugin-shortcuts@0.3.17-next.2 + - @backstage/plugin-stackstorm@0.1.9-next.2 + - @backstage/plugin-tech-insights@0.3.20-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.2 + - @backstage/plugin-techdocs-react@1.1.14-next.2 + - @backstage/plugin-todo@0.2.32-next.2 + +## 0.2.90-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/cli@0.25.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-catalog@1.16.0-next.2 + - @backstage/plugin-scaffolder-react@1.6.2-next.1 + - @backstage/plugin-home@0.6.0-next.1 + - @backstage/plugin-github-actions@0.6.9-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/plugin-azure-devops@0.3.10-next.1 + - @backstage/plugin-scaffolder@1.16.2-next.1 + - @backstage/plugin-api-docs@0.10.2-next.2 + - @backstage/plugin-gcp-projects@0.3.44-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.1 + - @backstage/plugin-user-settings@0.7.14-next.2 + - @backstage/plugin-adr@0.6.11-next.1 + - @backstage/plugin-pagerduty@0.7.0-next.1 + - @backstage/plugin-catalog-import@0.10.4-next.2 + - @backstage/plugin-explore@0.4.14-next.1 + - @backstage/plugin-graphiql@0.3.1-next.2 + - @backstage/plugin-search@1.4.4-next.2 + - @backstage/plugin-stack-overflow@0.1.23-next.1 + - @backstage/plugin-tech-radar@0.6.11-next.2 + - @backstage/plugin-techdocs@1.9.2-next.2 + - @backstage/app-defaults@1.4.6-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-airbrake@0.3.28-next.1 + - @backstage/plugin-apache-airflow@0.2.18-next.1 + - @backstage/plugin-azure-sites@0.1.17-next.1 + - @backstage/plugin-badges@0.2.52-next.1 + - @backstage/plugin-catalog-graph@0.3.2-next.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.1 + - @backstage/plugin-cloudbuild@0.3.28-next.1 + - @backstage/plugin-code-coverage@0.2.21-next.1 + - @backstage/plugin-cost-insights@0.12.17-next.1 + - @backstage/plugin-devtools@0.1.7-next.1 + - @backstage/plugin-dynatrace@8.0.2-next.1 + - @backstage/plugin-entity-feedback@0.2.11-next.1 + - @backstage/plugin-gcalendar@0.3.21-next.1 + - @backstage/plugin-gocd@0.1.34-next.1 + - @backstage/plugin-jenkins@0.9.3-next.1 + - @backstage/plugin-kafka@0.3.28-next.1 + - @backstage/plugin-kubernetes@0.11.3-next.1 + - @backstage/plugin-kubernetes-cluster@0.0.4-next.1 + - @backstage/plugin-lighthouse@0.4.13-next.1 + - @backstage/plugin-linguist@0.1.13-next.1 + - @backstage/plugin-microsoft-calendar@0.1.10-next.1 + - @backstage/plugin-newrelic@0.3.43-next.1 + - @backstage/plugin-newrelic-dashboard@0.3.3-next.1 + - @backstage/plugin-nomad@0.1.9-next.1 + - @backstage/plugin-octopus-deploy@0.2.10-next.1 + - @backstage/plugin-org@0.6.18-next.1 + - @backstage/plugin-playlist@0.2.2-next.1 + - @backstage/plugin-puppetdb@0.1.11-next.1 + - @backstage/plugin-rollbar@0.4.28-next.1 + - @backstage/plugin-sentry@0.5.13-next.1 + - @backstage/plugin-shortcuts@0.3.17-next.1 + - @backstage/plugin-stackstorm@0.1.9-next.1 + - @backstage/plugin-tech-insights@0.3.20-next.1 + - @backstage/plugin-techdocs-react@1.1.14-next.1 + - @backstage/plugin-todo@0.2.32-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.8 + +## 0.2.90-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.16.0-next.1 + - @backstage/plugin-catalog-import@0.10.4-next.1 + - @backstage/plugin-graphiql@0.3.1-next.1 + - @backstage/plugin-search@1.4.4-next.1 + - @backstage/plugin-tech-radar@0.6.11-next.1 + - @backstage/plugin-techdocs@1.9.2-next.1 + - @backstage/plugin-user-settings@0.7.14-next.1 + - @backstage/plugin-api-docs@0.10.2-next.1 + - @backstage/plugin-catalog-graph@0.3.2-next.0 + - @backstage/plugin-explore@0.4.14-next.0 + - @backstage/plugin-org@0.6.18-next.0 + - @backstage/plugin-scaffolder@1.16.2-next.0 + - @backstage/plugin-scaffolder-react@1.6.2-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.0 + +## 0.2.90-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/plugin-api-docs@0.10.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-scaffolder@1.16.2-next.0 + - @backstage/plugin-catalog@1.16.0-next.0 + - @backstage/frontend-app-api@0.3.1-next.0 + - @backstage/plugin-org@0.6.18-next.0 + - @backstage/plugin-scaffolder-react@1.6.2-next.0 + - @backstage/plugin-catalog-import@0.10.4-next.0 + - @backstage/plugin-user-settings@0.7.14-next.0 + - @backstage/plugin-tech-radar@0.6.11-next.0 + - @backstage/plugin-graphiql@0.3.1-next.0 + - @backstage/plugin-techdocs@1.9.2-next.0 + - @backstage/plugin-search@1.4.4-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/cli@0.24.1-next.0 + - @backstage/plugin-home@0.5.12-next.0 + - @backstage/plugin-kubernetes@0.11.3-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/app-defaults@1.4.6-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/plugin-adr@0.6.11-next.0 + - @backstage/plugin-airbrake@0.3.28-next.0 + - @backstage/plugin-apache-airflow@0.2.18-next.0 + - @backstage/plugin-azure-devops@0.3.10-next.0 + - @backstage/plugin-azure-sites@0.1.17-next.0 + - @backstage/plugin-badges@0.2.52-next.0 + - @backstage/plugin-catalog-graph@0.3.2-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.1.6-next.0 + - @backstage/plugin-circleci@0.3.28-next.0 + - @backstage/plugin-cloudbuild@0.3.28-next.0 + - @backstage/plugin-code-coverage@0.2.21-next.0 + - @backstage/plugin-cost-insights@0.12.17-next.0 + - @backstage/plugin-devtools@0.1.7-next.0 + - @backstage/plugin-dynatrace@8.0.2-next.0 + - @backstage/plugin-entity-feedback@0.2.11-next.0 + - @backstage/plugin-explore@0.4.14-next.0 + - @backstage/plugin-gcalendar@0.3.21-next.0 + - @backstage/plugin-gcp-projects@0.3.44-next.0 + - @backstage/plugin-github-actions@0.6.9-next.0 + - @backstage/plugin-gocd@0.1.34-next.0 + - @backstage/plugin-jenkins@0.9.3-next.0 + - @backstage/plugin-kafka@0.3.28-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.4-next.0 + - @backstage/plugin-lighthouse@0.4.13-next.0 + - @backstage/plugin-linguist@0.1.13-next.0 + - @backstage/plugin-microsoft-calendar@0.1.10-next.0 + - @backstage/plugin-newrelic@0.3.43-next.0 + - @backstage/plugin-newrelic-dashboard@0.3.3-next.0 + - @backstage/plugin-nomad@0.1.9-next.0 + - @backstage/plugin-octopus-deploy@0.2.10-next.0 + - @backstage/plugin-pagerduty@0.6.9-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + - @backstage/plugin-playlist@0.2.2-next.0 + - @backstage/plugin-puppetdb@0.1.11-next.0 + - @backstage/plugin-rollbar@0.4.28-next.0 + - @backstage/plugin-sentry@0.5.13-next.0 + - @backstage/plugin-shortcuts@0.3.17-next.0 + - @backstage/plugin-stack-overflow@0.1.23-next.0 + - @backstage/plugin-stackstorm@0.1.9-next.0 + - @backstage/plugin-tech-insights@0.3.20-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.3-next.0 + - @backstage/plugin-techdocs-react@1.1.14-next.0 + - @backstage/plugin-todo@0.2.32-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.8 + ## 0.2.89 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 245b645ddc..7d275ee990 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.89", + "version": "0.2.90-next.3", "private": true, "backstage": { "role": "frontend" @@ -35,7 +35,6 @@ "@backstage/plugin-catalog-import": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@backstage/plugin-catalog-unprocessed-entities": "workspace:^", - "@backstage/plugin-circleci": "workspace:^", "@backstage/plugin-cloudbuild": "workspace:^", "@backstage/plugin-code-coverage": "workspace:^", "@backstage/plugin-cost-insights": "workspace:^", @@ -84,6 +83,7 @@ "@backstage/plugin-todo": "workspace:^", "@backstage/plugin-user-settings": "workspace:^", "@backstage/theme": "workspace:^", + "@circleci/backstage-plugin": "^0.1.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", @@ -102,7 +102,7 @@ "react-use": "^17.2.4", "vite": "^4.4.9", "vite-plugin-html": "^3.2.0", - "vite-plugin-node-polyfills": "^0.16.0", + "vite-plugin-node-polyfills": "^0.17.0", "zen-observable": "^0.10.0" }, "devDependencies": { diff --git a/packages/app/src/components/catalog/EntityPage.test.tsx b/packages/app/src/components/catalog/EntityPage.test.tsx index 68ce5fb497..25181db2c1 100644 --- a/packages/app/src/components/catalog/EntityPage.test.tsx +++ b/packages/app/src/components/catalog/EntityPage.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { EntityLayout } from '@backstage/plugin-catalog'; +import { EntityLayout, catalogPlugin } from '@backstage/plugin-catalog'; import { EntityProvider, starredEntitiesApiRef, @@ -51,6 +51,7 @@ describe('EntityPage Test', () => { listWorkflowRuns: jest.fn().mockResolvedValue([]), }; const mockPermissionApi = new MockPermissionApi(); + const rootRouteRef = catalogPlugin.routes.catalogIndex; describe('cicdContent', () => { it('Should render GitHub Actions View', async () => { @@ -70,6 +71,11 @@ describe('EntityPage Test', () => { , + { + mountedRoutes: { + '/catalog': rootRouteRef, + }, + }, ); expect(rendered.getByText('ExampleComponent')).toBeInTheDocument(); diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index ecc1f008b5..4d5f65cbbe 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -77,7 +77,7 @@ import { import { EntityCircleCIContent, isCircleCIAvailable, -} from '@backstage/plugin-circleci'; +} from '@circleci/backstage-plugin'; import { EntityCloudbuildContent, isCloudbuildAvailable, @@ -798,9 +798,12 @@ const groupPage = ( entityFilterKind={customEntityFilterKind} /> - + + + + diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index 4c94beb674..39110bfa4d 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,58 @@ # @backstage/backend-app-api +## 0.5.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.6.0-next.0 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## 0.5.9-next.1 + +### Patch Changes + +- 1da5f434f3: Ensure redaction of secrets that have accidental extra whitespace around them +- 9f8f266ff4: Add redacting for secrets in stack traces of logs +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-permission-node@0.7.19-next.1 + +## 0.5.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.5.8 ### Patch Changes diff --git a/packages/backend-app-api/alpha-api-report.md b/packages/backend-app-api/api-report-alpha.md similarity index 100% rename from packages/backend-app-api/alpha-api-report.md rename to packages/backend-app-api/api-report-alpha.md diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index 9f75cb81a1..acd97ab544 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-app-api", "description": "Core API used by Backstage backend apps", - "version": "0.5.8", + "version": "0.5.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-app-api/src/logging/WinstonLogger.test.ts b/packages/backend-app-api/src/logging/WinstonLogger.test.ts index 5d8cfc9c90..c7173b1cbe 100644 --- a/packages/backend-app-api/src/logging/WinstonLogger.test.ts +++ b/packages/backend-app-api/src/logging/WinstonLogger.test.ts @@ -14,25 +14,37 @@ * limitations under the License. */ +import { TransformableInfo } from 'logform'; import { WinstonLogger } from './WinstonLogger'; -function msg(message: string) { - return { message, level: 'info' }; +function msg(info: TransformableInfo): TransformableInfo { + return { message: info.message, level: info.level, stack: info.stack }; } describe('WinstonLogger', () => { it('redacter should redact and escape regex', () => { const redacter = WinstonLogger.redacter(); - expect(redacter.format.transform(msg('hello (world)'))).toEqual( - msg('hello (world)'), + const log = { + level: 'error', + message: 'hello (world)', + stack: 'hello (world) from this file', + }; + expect(redacter.format.transform(msg(log))).toEqual(msg(log)); + redacter.add(['hello\n']); + expect(redacter.format.transform(msg(log))).toEqual( + msg({ + ...log, + message: '[REDACTED] (world)', + stack: '[REDACTED] (world) from this file', + }), ); - redacter.add(['hello']); - expect(redacter.format.transform(msg('hello (world)'))).toEqual( - msg('[REDACTED] (world)'), - ); - redacter.add(['(world)']); - expect(redacter.format.transform(msg('hello (world)'))).toEqual( - msg('[REDACTED] [REDACTED]'), + redacter.add(['(world']); + expect(redacter.format.transform(msg(log))).toEqual( + msg({ + ...log, + message: '[REDACTED] [REDACTED])', + stack: '[REDACTED] [REDACTED]) from this file', + }), ); }); }); diff --git a/packages/backend-app-api/src/logging/WinstonLogger.ts b/packages/backend-app-api/src/logging/WinstonLogger.ts index 06a189508b..7dd0ed80b0 100644 --- a/packages/backend-app-api/src/logging/WinstonLogger.ts +++ b/packages/backend-app-api/src/logging/WinstonLogger.ts @@ -82,11 +82,18 @@ export class WinstonLogger implements RootLoggerService { if (redactionPattern && typeof info.message === 'string') { info.message = info.message.replace(redactionPattern, '[REDACTED]'); } + if (redactionPattern && typeof info.stack === 'string') { + info.stack = info.stack.replace(redactionPattern, '[REDACTED]'); + } return info; })(), add(newRedactions) { let added = 0; - for (const redaction of newRedactions) { + for (const redactionToTrim of newRedactions) { + // Trimming the string ensures that we don't accdentally get extra + // newlines or other whitespace interfering with the redaction; this + // can happen for example when using string literals in yaml + const redaction = redactionToTrim.trim(); // Exclude secrets that are empty or just one character in length. These // typically mean that you are running local dev or tests, or using the // --lax flag which sets things to just 'x'. diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.test.ts b/packages/backend-app-api/src/wiring/BackendInitializer.test.ts index 791b9b1c3a..b5b53083a9 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.test.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.test.ts @@ -102,7 +102,7 @@ describe('BackendInitializer', () => { init.add( createBackendModule({ pluginId: 'test', - moduleId: 'modA', + moduleId: 'mod-a', register(reg) { reg.registerInit({ deps: { extension: extensionPoint }, @@ -118,7 +118,7 @@ describe('BackendInitializer', () => { init.add( createBackendModule({ pluginId: 'test', - moduleId: 'modB', + moduleId: 'mod-b', register(reg) { const values = ['b']; reg.registerExtensionPoint(extensionPoint, { values }); @@ -135,7 +135,7 @@ describe('BackendInitializer', () => { init.add( createBackendModule({ pluginId: 'test', - moduleId: 'modC', + moduleId: 'mod-c', register(reg) { reg.registerInit({ deps: { extension: extensionPoint }, @@ -265,7 +265,7 @@ describe('BackendInitializer', () => { init.add( createBackendModule({ pluginId: 'test', - moduleId: 'modA', + moduleId: 'mod-a', register(reg) { reg.registerExtensionPoint(extA, 'a'); reg.registerInit({ @@ -278,7 +278,7 @@ describe('BackendInitializer', () => { init.add( createBackendModule({ pluginId: 'test', - moduleId: 'modB', + moduleId: 'mod-b', register(reg) { reg.registerExtensionPoint(extB, 'b'); reg.registerInit({ @@ -289,7 +289,7 @@ describe('BackendInitializer', () => { })(), ); await expect(init.start()).rejects.toThrow( - "Circular dependency detected for modules of plugin 'test', 'modA' -> 'modB' -> 'modA'", + "Circular dependency detected for modules of plugin 'test', 'mod-a' -> 'mod-b' -> 'mod-a'", ); }); @@ -298,7 +298,7 @@ describe('BackendInitializer', () => { const extA = createExtensionPoint({ id: 'a' }); init.add( createBackendPlugin({ - pluginId: 'testA', + pluginId: 'test-a', register(reg) { reg.registerExtensionPoint(extA, 'a'); reg.registerInit({ @@ -310,7 +310,7 @@ describe('BackendInitializer', () => { ); init.add( createBackendModule({ - pluginId: 'testB', + pluginId: 'test-b', moduleId: 'mod', register(reg) { reg.registerInit({ @@ -321,7 +321,7 @@ describe('BackendInitializer', () => { })(), ); await expect(init.start()).rejects.toThrow( - "Extension point registered for plugin 'testA' may not be used by module for plugin 'testB'", + "Extension point registered for plugin 'test-a' may not be used by module for plugin 'test-b'", ); }); }); diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index a0ee354e30..d4cce4ee08 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,65 @@ # @backstage/backend-common +## 0.20.0-next.2 + +### Patch Changes + +- bc67498: Updated dependency `archiver` to `^6.0.0`. + Updated dependency `@types/archiver` to `^6.0.0`. +- Updated dependencies + - @backstage/config-loader@1.6.0-next.0 + - @backstage/backend-app-api@0.5.9-next.2 + - @backstage/backend-dev-utils@0.1.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + +## 0.20.0-next.1 + +### Patch Changes + +- 2666675457: Updated dependency `@google-cloud/storage` to `^7.0.0`. +- Updated dependencies + - @backstage/backend-app-api@0.5.9-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-dev-utils@0.1.2 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + +## 0.20.0-next.0 + +### Minor Changes + +- 870db76a45: Implemented `readTree` for Gitea provider to support TechDocs functionality + +### Patch Changes + +- 7f04128bbc: Allow a default cache TTL to be set through the app config +- 1ad8906a9e: Use `Readable.from` to fix some of the stream issues +- 706fc3a7e1: Updated dependency `@kubernetes/client-node` to `0.20.0`. +- d15d483a49: Add command `--runAsDefaultUser` for `@techdocs/cli generate` to bypass running the docker builds as host user for macOS and Linux. +- d1e00aa17a: Expose an `onAuth` handler for `git` actions to provide custom credentials +- Updated dependencies + - @backstage/integration@1.8.0-next.0 + - @backstage/backend-app-api@0.5.9-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/backend-dev-utils@0.1.2 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + ## 0.19.9 ### Patch Changes diff --git a/packages/backend-common/alpha-api-report.md b/packages/backend-common/api-report-alpha.md similarity index 100% rename from packages/backend-common/alpha-api-report.md rename to packages/backend-common/api-report-alpha.md diff --git a/packages/backend-common/testUtils-api-report.md b/packages/backend-common/api-report-testUtils.md similarity index 100% rename from packages/backend-common/testUtils-api-report.md rename to packages/backend-common/api-report-testUtils.md diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index dd9ab2bee7..e7d89c2aa5 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -7,6 +7,7 @@ /// import { AppConfig } from '@backstage/config'; +import { AuthCallback } from 'isomorphic-git'; import { AwsCredentialsManager } from '@backstage/integration-aws-node'; import { AwsS3Integration } from '@backstage/integration'; import { AzureDevOpsCredentialsProvider } from '@backstage/integration'; @@ -68,6 +69,12 @@ import { V1PodTemplateSpec } from '@kubernetes/client-node'; import * as winston from 'winston'; import { Writable } from 'stream'; +// @public +export type AuthCallbackOptions = { + onAuth: AuthCallback; + logger?: LoggerService; +}; + // @public export class AwsS3UrlReader implements UrlReader { constructor( @@ -385,12 +392,7 @@ export class Git { tags?: boolean; }): Promise; // (undocumented) - static fromAuth: (options: { - username?: string; - password?: string; - token?: string; - logger?: LoggerService; - }) => Git; + static fromAuth: (options: StaticAuthOptions | AuthCallbackOptions) => Git; // (undocumented) init(options: { dir: string; defaultBranch?: string }): Promise; log(options: { dir: string; ref?: string }): Promise; @@ -689,6 +691,7 @@ export type RunContainerOptions = { workingDir?: string; envVars?: Record; pullImage?: boolean; + defaultUser?: boolean; }; export { SearchOptions }; @@ -750,6 +753,14 @@ export function setRootLogger(newLogger: winston.Logger): void; // @public @deprecated export const SingleHostDiscovery: typeof HostDiscovery_2; +// @public +export type StaticAuthOptions = { + username?: string; + password?: string; + token?: string; + logger?: LoggerService; +}; + // @public export type StatusCheck = () => Promise; diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index a718d7d1b4..1f68db8ba8 100644 --- a/packages/backend-common/package.json +++ b/packages/backend-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-common", "description": "Common functionality library for Backstage backends", - "version": "0.19.9", + "version": "0.20.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -64,10 +64,10 @@ "@backstage/integration": "workspace:^", "@backstage/integration-aws-node": "workspace:^", "@backstage/types": "workspace:^", - "@google-cloud/storage": "^6.0.0", + "@google-cloud/storage": "^7.0.0", "@keyv/memcache": "^1.3.5", "@keyv/redis": "^2.5.3", - "@kubernetes/client-node": "0.19.0", + "@kubernetes/client-node": "0.20.0", "@manypkg/get-packages": "^1.1.3", "@octokit/rest": "^19.0.3", "@types/cors": "^2.8.6", @@ -75,7 +75,7 @@ "@types/express": "^4.17.6", "@types/luxon": "^3.0.0", "@types/webpack-env": "^1.15.2", - "archiver": "^5.0.2", + "archiver": "^6.0.0", "base64-stream": "^1.0.0", "compression": "^1.7.4", "concat-stream": "^2.0.0", @@ -118,7 +118,7 @@ "@aws-sdk/util-stream-node": "^3.350.0", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", - "@types/archiver": "^5.1.0", + "@types/archiver": "^6.0.0", "@types/base64-stream": "^1.0.2", "@types/compression": "^1.7.0", "@types/concat-stream": "^2.0.0", diff --git a/packages/backend-common/src/reading/GerritUrlReader.ts b/packages/backend-common/src/reading/GerritUrlReader.ts index f4a5fdb9f5..665770815f 100644 --- a/packages/backend-common/src/reading/GerritUrlReader.ts +++ b/packages/backend-common/src/reading/GerritUrlReader.ts @@ -139,7 +139,7 @@ export class GerritUrlReader implements UrlReader { return Buffer.from(responseBody, 'base64'); }, stream: () => { - const readable = new Readable().wrap(response.body); + const readable = Readable.from(response.body); return readable.pipe(new Base64Decode()); }, }; diff --git a/packages/backend-common/src/reading/ReadUrlResponseFactory.test.ts b/packages/backend-common/src/reading/ReadUrlResponseFactory.test.ts index 1eb18f5c1d..95d9099662 100644 --- a/packages/backend-common/src/reading/ReadUrlResponseFactory.test.ts +++ b/packages/backend-common/src/reading/ReadUrlResponseFactory.test.ts @@ -16,7 +16,7 @@ import { ConflictError } from '@backstage/errors'; import getRawBody from 'raw-body'; -import { Readable, Stream } from 'stream'; +import { Readable } from 'stream'; import { ReadUrlResponseFactory } from './ReadUrlResponseFactory'; describe('ReadUrlResponseFactory', () => { @@ -74,25 +74,10 @@ describe('ReadUrlResponseFactory', () => { describe("fromNodeJSReadable's", () => { const expectedText = 'expected text'; - const timeouts: NodeJS.Timeout[] = []; let readable: NodeJS.ReadableStream; beforeEach(() => { - readable = new Stream({ - encoding: 'utf-8', - }) as unknown as NodeJS.ReadableStream; - readable.readable = true; - - // Write data asynchronously, as soon as possible. - timeouts[0] = setTimeout(() => { - timeouts[1] = setTimeout(readable.emit.bind(readable, 'end'), 0); - readable.emit('data', expectedText); - }, 0); - }); - - afterEach(() => { - // Clear out timeouts so we don't emit data across tests. - timeouts.forEach(clearTimeout); + readable = Readable.from(Buffer.from(expectedText)); }); it('etag is passed through', async () => { diff --git a/packages/backend-common/src/reading/ReadUrlResponseFactory.ts b/packages/backend-common/src/reading/ReadUrlResponseFactory.ts index 69b9c6c16a..5eb4b2f5bc 100644 --- a/packages/backend-common/src/reading/ReadUrlResponseFactory.ts +++ b/packages/backend-common/src/reading/ReadUrlResponseFactory.ts @@ -72,7 +72,7 @@ export class ReadUrlResponseFactory { oldStyleStream: NodeJS.ReadableStream, options?: ReadUrlResponseFactoryFromStreamOptions, ): Promise { - const readable = new Readable().wrap(oldStyleStream); + const readable = Readable.from(oldStyleStream); return ReadUrlResponseFactory.fromReadable(readable, options); } } diff --git a/packages/backend-common/src/scm/git.test.ts b/packages/backend-common/src/scm/git.test.ts index 5ec960fc53..7533c6e2f3 100644 --- a/packages/backend-common/src/scm/git.test.ts +++ b/packages/backend-common/src/scm/git.test.ts @@ -190,7 +190,7 @@ describe('Git', () => { }); }); - it('should pass a function that returns the authorization as the onAuth handler', async () => { + it('should pass a function that returns the authorization as the onAuth handler when username and password are specified', async () => { const url = 'http://github.com/some/repo'; const dir = '/some/mock/dir'; const auth = { @@ -208,6 +208,25 @@ describe('Git', () => { expect(onAuth()).toEqual(auth); }); + it('should pass the provided callback as the onAuth handler when on auth is specified', async () => { + const url = 'http://github.com/some/repo'; + const dir = '/some/mock/dir'; + const auth = { + username: 'from', + password: 'callback', + }; + + const git = Git.fromAuth({ onAuth: () => auth }); + + await git.clone({ url, dir }); + + const { onAuth } = ( + isomorphic.clone as unknown as jest.Mock<(typeof isomorphic)['clone']> + ).mock.calls[0][0]!; + + expect(onAuth()).toEqual(auth); + }); + it('should propagate the data from the error handler', async () => { const url = 'http://github.com/some/repo'; const dir = '/some/mock/dir'; diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index 8ccdbeafbd..364e1bacd5 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -18,11 +18,40 @@ import git, { ProgressCallback, MergeResult, ReadCommitResult, + AuthCallback, } from 'isomorphic-git'; import http from 'isomorphic-git/http/node'; import fs from 'fs-extra'; import { LoggerService } from '@backstage/backend-plugin-api'; +function isAuthCallbackOptions( + options: StaticAuthOptions | AuthCallbackOptions, +): options is AuthCallbackOptions { + return 'onAuth' in options; +} + +/** + * Configure static credential for authentication + * + * @public + */ +export type StaticAuthOptions = { + username?: string; + password?: string; + token?: string; + logger?: LoggerService; +}; + +/** + * Configure an authentication callback that can provide credentials on demand + * + * @public + */ +export type AuthCallbackOptions = { + onAuth: AuthCallback; + logger?: LoggerService; +}; + /* provider username password Azure 'notempty' token @@ -42,6 +71,7 @@ instead of Basic Auth (e.g., Bitbucket Server). * * @public */ + export class Git { private readonly headers: { [x: string]: string; @@ -49,12 +79,13 @@ export class Git { private constructor( private readonly config: { - username?: string; - password?: string; + onAuth: AuthCallback; token?: string; logger?: LoggerService; }, ) { + this.onAuth = config.onAuth; + this.headers = { 'user-agent': 'git/@isomorphic-git', ...(config.token ? { Authorization: `Bearer ${config.token}` } : {}), @@ -288,10 +319,7 @@ export class Git { }); } - private onAuth = () => ({ - username: this.config.username, - password: this.config.password, - }); + private onAuth: AuthCallback; private onProgressHandler = (): ProgressCallback => { let currentPhase = ''; @@ -308,13 +336,13 @@ export class Git { }; }; - static fromAuth = (options: { - username?: string; - password?: string; - token?: string; - logger?: LoggerService; - }) => { + static fromAuth = (options: StaticAuthOptions | AuthCallbackOptions) => { + if (isAuthCallbackOptions(options)) { + const { onAuth, logger } = options; + return new Git({ onAuth, logger }); + } + const { username, password, token, logger } = options; - return new Git({ username, password, token, logger }); + return new Git({ onAuth: () => ({ username, password }), token, logger }); }; } diff --git a/packages/backend-common/src/scm/index.ts b/packages/backend-common/src/scm/index.ts index ceba752c9e..f9c59e99eb 100644 --- a/packages/backend-common/src/scm/index.ts +++ b/packages/backend-common/src/scm/index.ts @@ -15,3 +15,4 @@ */ export { Git } from './git'; +export type { StaticAuthOptions, AuthCallbackOptions } from './git'; diff --git a/packages/backend-common/src/util/ContainerRunner.ts b/packages/backend-common/src/util/ContainerRunner.ts index 22e40ec455..7dc12919b3 100644 --- a/packages/backend-common/src/util/ContainerRunner.ts +++ b/packages/backend-common/src/util/ContainerRunner.ts @@ -30,6 +30,7 @@ export type RunContainerOptions = { workingDir?: string; envVars?: Record; pullImage?: boolean; + defaultUser?: boolean; }; /** diff --git a/packages/backend-common/src/util/DockerContainerRunner.ts b/packages/backend-common/src/util/DockerContainerRunner.ts index 4d4684c814..986470eb98 100644 --- a/packages/backend-common/src/util/DockerContainerRunner.ts +++ b/packages/backend-common/src/util/DockerContainerRunner.ts @@ -46,6 +46,7 @@ export class DockerContainerRunner implements ContainerRunner { workingDir, envVars = {}, pullImage = true, + defaultUser = false, } = options; // Show a better error message when Docker is unavailable. @@ -71,7 +72,7 @@ export class DockerContainerRunner implements ContainerRunner { } const userOptions: UserOptions = {}; - if (process.getuid && process.getgid) { + if (!defaultUser && process.getuid && process.getgid) { // Files that are created inside the Docker container will be owned by // root on the host system on non Mac systems, because of reasons. Mainly the fact that // volume sharing is done using NFS on Mac and actual mounts in Linux world. diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index 9c901e9cf9..7a1604939c 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/backend-defaults +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-app-api@0.5.9-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## 0.2.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.5.9-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + +## 0.2.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-app-api@0.5.9-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + ## 0.2.7 ### Patch Changes diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 4ae1c8fadc..d7d8d59cb8 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-defaults", "description": "Backend defaults used by Backstage backend apps", - "version": "0.2.7", + "version": "0.2.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-next/CHANGELOG.md b/packages/backend-next/CHANGELOG.md index 0970dd2c1f..e8af725114 100644 --- a/packages/backend-next/CHANGELOG.md +++ b/packages/backend-next/CHANGELOG.md @@ -1,5 +1,128 @@ # example-backend-next +## 0.0.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.16.0-next.2 + - @backstage/plugin-lighthouse-backend@0.4.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.2 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.5-next.2 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.2 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.2 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.2 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.2 + - @backstage/backend-defaults@0.2.8-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/plugin-adr-backend@0.4.5-next.2 + - @backstage/plugin-app-backend@0.3.56-next.2 + - @backstage/plugin-azure-devops-backend@0.5.0-next.2 + - @backstage/plugin-badges-backend@0.3.5-next.2 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.1.1-next.2 + - @backstage/plugin-catalog-backend-module-openapi@0.1.25-next.2 + - @backstage/plugin-devtools-backend@0.2.5-next.2 + - @backstage/plugin-entity-feedback-backend@0.2.5-next.2 + - @backstage/plugin-jenkins-backend@0.3.2-next.2 + - @backstage/plugin-kubernetes-backend@0.14.0-next.2 + - @backstage/plugin-linguist-backend@0.5.5-next.2 + - @backstage/plugin-nomad-backend@0.1.10-next.2 + - @backstage/plugin-permission-backend@0.5.31-next.2 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + - @backstage/plugin-playlist-backend@0.3.12-next.2 + - @backstage/plugin-proxy-backend@0.4.6-next.2 + - @backstage/plugin-scaffolder-backend@1.19.2-next.2 + - @backstage/plugin-search-backend@1.4.8-next.2 + - @backstage/plugin-search-backend-node@1.2.12-next.2 + - @backstage/plugin-sonarqube-backend@0.2.10-next.2 + - @backstage/plugin-techdocs-backend@1.9.1-next.2 + - @backstage/plugin-todo-backend@0.3.6-next.2 + +## 0.0.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.1.1-next.1 + - @backstage/plugin-catalog-backend@1.15.1-next.1 + - @backstage/plugin-azure-devops-backend@0.5.0-next.1 + - @backstage/plugin-kubernetes-backend@0.14.0-next.1 + - @backstage/backend-defaults@0.2.8-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/plugin-adr-backend@0.4.5-next.1 + - @backstage/plugin-app-backend@0.3.56-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-badges-backend@0.3.5-next.1 + - @backstage/plugin-catalog-backend-module-openapi@0.1.25-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.1 + - @backstage/plugin-devtools-backend@0.2.5-next.1 + - @backstage/plugin-entity-feedback-backend@0.2.5-next.1 + - @backstage/plugin-jenkins-backend@0.3.2-next.1 + - @backstage/plugin-lighthouse-backend@0.3.5-next.1 + - @backstage/plugin-linguist-backend@0.5.5-next.1 + - @backstage/plugin-nomad-backend@0.1.10-next.1 + - @backstage/plugin-permission-backend@0.5.31-next.1 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.5-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + - @backstage/plugin-playlist-backend@0.3.12-next.1 + - @backstage/plugin-proxy-backend@0.4.6-next.1 + - @backstage/plugin-scaffolder-backend@1.19.2-next.1 + - @backstage/plugin-search-backend@1.4.8-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.1 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.1 + - @backstage/plugin-search-backend-node@1.2.12-next.1 + - @backstage/plugin-sonarqube-backend@0.2.10-next.1 + - @backstage/plugin-techdocs-backend@1.9.1-next.1 + - @backstage/plugin-todo-backend@0.3.6-next.1 + +## 0.0.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-scaffolder-backend@1.19.2-next.0 + - @backstage/plugin-kubernetes-backend@0.14.0-next.0 + - @backstage/backend-defaults@0.2.8-next.0 + - @backstage/plugin-adr-backend@0.4.5-next.0 + - @backstage/plugin-app-backend@0.3.56-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-azure-devops-backend@0.4.5-next.0 + - @backstage/plugin-badges-backend@0.3.5-next.0 + - @backstage/plugin-catalog-backend@1.15.1-next.0 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.1.1-next.0 + - @backstage/plugin-catalog-backend-module-openapi@0.1.25-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.0 + - @backstage/plugin-devtools-backend@0.2.5-next.0 + - @backstage/plugin-entity-feedback-backend@0.2.5-next.0 + - @backstage/plugin-jenkins-backend@0.3.2-next.0 + - @backstage/plugin-lighthouse-backend@0.3.5-next.0 + - @backstage/plugin-linguist-backend@0.5.5-next.0 + - @backstage/plugin-nomad-backend@0.1.10-next.0 + - @backstage/plugin-permission-backend@0.5.31-next.0 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.5-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/plugin-playlist-backend@0.3.12-next.0 + - @backstage/plugin-proxy-backend@0.4.6-next.0 + - @backstage/plugin-search-backend@1.4.8-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.0 + - @backstage/plugin-search-backend-node@1.2.12-next.0 + - @backstage/plugin-sonarqube-backend@0.2.10-next.0 + - @backstage/plugin-techdocs-backend@1.9.1-next.0 + - @backstage/plugin-todo-backend@0.3.6-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.0 + - @backstage/plugin-permission-common@0.7.10 + ## 0.0.17 ### Patch Changes diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index 5c52d5b79b..a52cd949e0 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-next", - "version": "0.0.17", + "version": "0.0.18-next.2", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-openapi-utils/CHANGELOG.md b/packages/backend-openapi-utils/CHANGELOG.md index 04b4a8d0ba..00fe5bfa8f 100644 --- a/packages/backend-openapi-utils/CHANGELOG.md +++ b/packages/backend-openapi-utils/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/backend-openapi-utils +## 0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## 0.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## 0.1.1-next.0 + +### Patch Changes + +- aaa6fb3bc9: Minor updates for TypeScript 5.2.2+ compatibility +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.1.0 ### Minor Changes diff --git a/packages/backend-openapi-utils/api-report.md b/packages/backend-openapi-utils/api-report.md index 67132ca74b..0d78ec9671 100644 --- a/packages/backend-openapi-utils/api-report.md +++ b/packages/backend-openapi-utils/api-report.md @@ -61,12 +61,13 @@ type ComponentTypes = Extract< >; // @public (undocumented) -type ConvertAll = []> = T extends [ - infer First extends JSONSchema7, - ...infer Rest, -] - ? ConvertAll]> - : R; +type ConvertAll> = { + [Index in keyof T]: T[Index] extends JSONSchema7 + ? FromSchema + : T[Index]; +} & { + length: T['length']; +}; // @public (undocumented) interface CookieObject extends ParameterObject { diff --git a/packages/backend-openapi-utils/package.json b/packages/backend-openapi-utils/package.json index f1f5bf8675..05fcf3e6d6 100644 --- a/packages/backend-openapi-utils/package.json +++ b/packages/backend-openapi-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-openapi-utils", "description": "OpenAPI typescript support.", - "version": "0.1.0", + "version": "0.1.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-openapi-utils/src/types/common.ts b/packages/backend-openapi-utils/src/types/common.ts index c3c7284369..f9dedf2f84 100644 --- a/packages/backend-openapi-utils/src/types/common.ts +++ b/packages/backend-openapi-utils/src/types/common.ts @@ -220,12 +220,11 @@ export type TuplifyUnion< /** * @public */ -export type ConvertAll = []> = T extends [ - infer First extends JSONSchema7, - ...infer Rest, -] - ? ConvertAll]> - : R; +export type ConvertAll> = { + [Index in keyof T]: T[Index] extends JSONSchema7 + ? FromSchema + : T[Index]; +} & { length: T['length'] }; /** * @public diff --git a/packages/backend-plugin-api/CHANGELOG.md b/packages/backend-plugin-api/CHANGELOG.md index 0a1fd56bcb..487799c4dc 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/backend-plugin-api +## 0.6.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + +## 0.6.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-permission-common@0.7.10 + +## 0.6.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + ## 0.6.7 ### Patch Changes diff --git a/packages/backend-plugin-api/alpha-api-report.md b/packages/backend-plugin-api/api-report-alpha.md similarity index 100% rename from packages/backend-plugin-api/alpha-api-report.md rename to packages/backend-plugin-api/api-report-alpha.md diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index c930ef5d15..c335d1f0a2 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-plugin-api", "description": "Core API used by Backstage backend plugins", - "version": "0.6.7", + "version": "0.6.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-plugin-manager/CHANGELOG.md b/packages/backend-plugin-manager/CHANGELOG.md index dc07175fd3..2f846adeaa 100644 --- a/packages/backend-plugin-manager/CHANGELOG.md +++ b/packages/backend-plugin-manager/CHANGELOG.md @@ -1,5 +1,74 @@ # @backstage/backend-plugin-manager +## 0.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.16.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/plugin-events-backend@0.2.17-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.2 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + - @backstage/plugin-search-backend-node@1.2.12-next.2 + - @backstage/plugin-search-common@1.2.8 + +## 0.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.15.1-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-events-backend@0.2.17-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + - @backstage/plugin-search-backend-node@1.2.12-next.1 + - @backstage/plugin-search-common@1.2.8 + +## 0.0.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-catalog-backend@1.15.1-next.0 + - @backstage/plugin-events-backend@0.2.17-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/plugin-search-backend-node@1.2.12-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.0 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-common@1.2.8 + ## 0.0.3 ### Patch Changes diff --git a/packages/backend-plugin-manager/package.json b/packages/backend-plugin-manager/package.json index 2afa6c0ed5..3e91feb9ba 100644 --- a/packages/backend-plugin-manager/package.json +++ b/packages/backend-plugin-manager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-plugin-manager", "description": "Backstage plugin management backend", - "version": "0.0.3", + "version": "0.0.4-next.2", "private": true, "main": "src/index.ts", "types": "src/index.ts", diff --git a/packages/backend-plugin-manager/src/loader/CommonJSModuleLoader.ts b/packages/backend-plugin-manager/src/loader/CommonJSModuleLoader.ts index 06a08117cd..66af367cea 100644 --- a/packages/backend-plugin-manager/src/loader/CommonJSModuleLoader.ts +++ b/packages/backend-plugin-manager/src/loader/CommonJSModuleLoader.ts @@ -49,6 +49,6 @@ export class CommonJSModuleLoader implements ModuleLoader { } async load(packagePath: string): Promise { - return await import(/* webpackIgnore: true */ packagePath); + return await require(/* webpackIgnore: true */ packagePath); } } diff --git a/packages/backend-plugin-manager/src/manager/plugin-manager.test.ts b/packages/backend-plugin-manager/src/manager/plugin-manager.test.ts index 4aabd2c072..5b1e1caf4d 100644 --- a/packages/backend-plugin-manager/src/manager/plugin-manager.test.ts +++ b/packages/backend-plugin-manager/src/manager/plugin-manager.test.ts @@ -113,6 +113,94 @@ describe('backend-plugin-manager', () => { >([]); }, }, + { + name: 'should successfully load a new backend plugin by the default BackendFeature', + packageManifest: { + name: 'backend-dynamic-plugin-test', + version: '0.0.0', + backstage: { + role: 'backend-plugin', + }, + main: 'dist/index.cjs.js', + }, + indexFile: { + retativePath: ['dist', 'index.cjs.js'], + content: `const alpha = { $$type: '@backstage/BackendFeature' }; exports["default"] = alpha;`, + }, + expectedLogs(location) { + return { + infos: [ + { + message: `loaded dynamic backend plugin 'backend-dynamic-plugin-test' from '${location}'`, + }, + ], + }; + }, + checkLoadedPlugins(plugins) { + expect(plugins).toMatchObject([ + { + name: 'backend-dynamic-plugin-test', + version: '0.0.0', + role: 'backend-plugin', + platform: 'node', + installer: { + kind: 'new', + }, + }, + ]); + const installer: NewBackendPluginInstaller = ( + plugins[0] as BackendDynamicPlugin + ).installer as NewBackendPluginInstaller; + expect(installer.install()).toEqual< + BackendFeature | BackendFeature[] + >({ $$type: '@backstage/BackendFeature' }); + }, + }, + { + name: 'should successfully load a new backend plugin by the default BackendFeatureFactory', + packageManifest: { + name: 'backend-dynamic-plugin-test', + version: '0.0.0', + backstage: { + role: 'backend-plugin', + }, + main: 'dist/index.cjs.js', + }, + indexFile: { + retativePath: ['dist', 'index.cjs.js'], + content: `const alpha = () => { return { $$type: '@backstage/BackendFeature' } }; + alpha.$$type = '@backstage/BackendFeatureFactory'; + exports["default"] = alpha;`, + }, + expectedLogs(location) { + return { + infos: [ + { + message: `loaded dynamic backend plugin 'backend-dynamic-plugin-test' from '${location}'`, + }, + ], + }; + }, + checkLoadedPlugins(plugins) { + expect(plugins).toMatchObject([ + { + name: 'backend-dynamic-plugin-test', + version: '0.0.0', + role: 'backend-plugin', + platform: 'node', + installer: { + kind: 'new', + }, + }, + ]); + const installer: NewBackendPluginInstaller = ( + plugins[0] as BackendDynamicPlugin + ).installer as NewBackendPluginInstaller; + expect(installer.install()).toEqual< + BackendFeature | BackendFeature[] + >({ $$type: '@backstage/BackendFeature' }); + }, + }, { name: 'should successfully load a new backend plugin module', packageManifest: { @@ -221,7 +309,7 @@ describe('backend-plugin-manager', () => { return { errors: [ { - message: `dynamic backend plugin 'backend-dynamic-plugin-test' could not be loaded from '${location}': the module should export a 'const dynamicPluginInstaller: BackendDynamicPluginInstaller' field.`, + message: `dynamic backend plugin 'backend-dynamic-plugin-test' could not be loaded from '${location}': the module should either export a 'BackendFeature' or 'BackendFeatureFactory' as default export, or export a 'const dynamicPluginInstaller: BackendDynamicPluginInstaller' field as dynamic loading entrypoint.`, }, ], }; @@ -249,7 +337,7 @@ describe('backend-plugin-manager', () => { return { errors: [ { - message: `dynamic backend plugin 'backend-dynamic-plugin-test' could not be loaded from '${location}': the module should export a 'const dynamicPluginInstaller: BackendDynamicPluginInstaller' field.`, + message: `dynamic backend plugin 'backend-dynamic-plugin-test' could not be loaded from '${location}': the module should either export a 'BackendFeature' or 'BackendFeatureFactory' as default export, or export a 'const dynamicPluginInstaller: BackendDynamicPluginInstaller' field as dynamic loading entrypoint.`, }, ], }; @@ -378,7 +466,7 @@ describe('backend-plugin-manager', () => { logger, async bootstrap(_: string, __: string[]): Promise {}, load: async (packagePath: string) => - await import(/* webpackIgnore: true */ packagePath), + await require(/* webpackIgnore: true */ packagePath), }); const loadedPlugins: DynamicPlugin[] = await pluginManager.loadPlugins(); diff --git a/packages/backend-plugin-manager/src/manager/plugin-manager.ts b/packages/backend-plugin-manager/src/manager/plugin-manager.ts index ad76c7529e..5a5caa0a89 100644 --- a/packages/backend-plugin-manager/src/manager/plugin-manager.ts +++ b/packages/backend-plugin-manager/src/manager/plugin-manager.ts @@ -140,12 +140,25 @@ export class PluginManager implements BackendPluginProvider { `${plugin.location}/${plugin.manifest.main}`, ); try { - const { dynamicPluginInstaller } = await this.moduleLoader.load( - packagePath, - ); + const pluginModule = await this.moduleLoader.load(packagePath); + + let dynamicPluginInstaller; + if (isBackendFeature(pluginModule.default)) { + dynamicPluginInstaller = { + kind: 'new', + install: () => pluginModule.default, + }; + } else if (isBackendFeatureFactory(pluginModule.default)) { + dynamicPluginInstaller = { + kind: 'new', + install: pluginModule.default, + }; + } else { + dynamicPluginInstaller = pluginModule.dynamicPluginInstaller; + } if (!isBackendDynamicPluginInstaller(dynamicPluginInstaller)) { this.logger.error( - `dynamic backend plugin '${plugin.manifest.name}' could not be loaded from '${plugin.location}': the module should export a 'const dynamicPluginInstaller: BackendDynamicPluginInstaller' field.`, + `dynamic backend plugin '${plugin.manifest.name}' could not be loaded from '${plugin.location}': the module should either export a 'BackendFeature' or 'BackendFeatureFactory' as default export, or export a 'const dynamicPluginInstaller: BackendDynamicPluginInstaller' field as dynamic loading entrypoint.`, ); return undefined; } @@ -263,3 +276,21 @@ export const dynamicPluginsFeatureDiscoveryServiceFactory = return new DynamicPluginsEnabledFeatureDiscoveryService(dynamicPlugins); }, }); + +function isBackendFeature(value: unknown): value is BackendFeature { + return ( + !!value && + typeof value === 'object' && + (value as BackendFeature).$$type === '@backstage/BackendFeature' + ); +} + +function isBackendFeatureFactory( + value: unknown, +): value is () => BackendFeature { + return ( + !!value && + typeof value === 'function' && + (value as any).$$type === '@backstage/BackendFeatureFactory' + ); +} diff --git a/packages/backend-plugin-manager/src/scanner/plugin-scanner-watcher.test.ts b/packages/backend-plugin-manager/src/scanner/plugin-scanner-watcher.test.ts index e346bf749f..7b795aee4f 100644 --- a/packages/backend-plugin-manager/src/scanner/plugin-scanner-watcher.test.ts +++ b/packages/backend-plugin-manager/src/scanner/plugin-scanner-watcher.test.ts @@ -229,6 +229,7 @@ describe('plugin-scanner', () => { logger.logs = {}; const debug = jest.spyOn(logger, 'debug'); + const info = jest.spyOn(logger, 'info'); // Check that not all file changes trigger a new scan of plugins await mkdir( @@ -240,8 +241,11 @@ describe('plugin-scanner', () => { ), ); await waitForExpect(() => { - expect(debug).toHaveBeenCalledTimes(1); + expect(debug).toHaveBeenCalled(); }); + expect(info).toHaveBeenCalledTimes(0); + debug.mockClear(); + await writeFile( join( backstageRootDirectory, @@ -252,8 +256,11 @@ describe('plugin-scanner', () => { 'content', ); await waitForExpect(() => { - expect(debug).toHaveBeenCalledTimes(2); + expect(debug).toHaveBeenCalled(); }); + expect(info).toHaveBeenCalledTimes(0); + debug.mockClear(); + await rm( join( backstageRootDirectory, @@ -263,8 +270,11 @@ describe('plugin-scanner', () => { ), ); await waitForExpect(() => { - expect(debug).toHaveBeenCalledTimes(3); + expect(debug).toHaveBeenCalled(); }); + expect(info).toHaveBeenCalledTimes(0); + debug.mockClear(); + await rm( join( backstageRootDirectory, @@ -275,8 +285,10 @@ describe('plugin-scanner', () => { { recursive: true }, ); await waitForExpect(() => { - expect(debug).toHaveBeenCalledTimes(4); + expect(debug).toHaveBeenCalled(); }); + expect(info).toHaveBeenCalledTimes(0); + debug.mockClear(); const onWindows = path.sep === '\\'; // Order of events is not fixed on Windows. diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index 8269059ce1..8360c78337 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/backend-tasks +## 0.5.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## 0.5.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## 0.5.13-next.0 + +### Patch Changes + +- d8f488aaa8: Allow tasks to run more often that the default work check interval, which is 5 seconds. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.5.12 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 565e6c4b8c..f1ac622864 100644 --- a/packages/backend-tasks/package.json +++ b/packages/backend-tasks/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-tasks", "description": "Common distributed task management library for Backstage backends", - "version": "0.5.12", + "version": "0.5.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index 04eabe2dff..697572d50c 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/backend-test-utils +## 0.2.9-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-app-api@0.5.9-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## 0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@0.5.9-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-app-api@0.5.9-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.2.8 ### Patch Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index d88c21d5db..e1983924ab 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/backend-test-utils", "description": "Test helpers library for Backstage backends", - "version": "0.2.8", + "version": "0.2.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts index b127712927..d71c774dd9 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts @@ -33,8 +33,8 @@ beforeAll(async () => { await startTestBackend({ features: [ createBackendModule({ - moduleId: 'test.module', pluginId: 'test', + moduleId: 'test-module', register(env) { env.registerInit({ deps: { lifecycle: coreServices.lifecycle }, @@ -128,8 +128,8 @@ describe('TestBackend', () => { }); const testModule = createBackendModule({ - moduleId: 'test.module', pluginId: 'test', + moduleId: 'test-module', register(env) { env.registerInit({ deps: { @@ -153,8 +153,8 @@ describe('TestBackend', () => { const shutdownSpy = jest.fn(); const testModule = createBackendModule({ - moduleId: 'test.module', pluginId: 'test', + moduleId: 'test-module', register(env) { env.registerInit({ deps: { diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.ts b/packages/backend-test-utils/src/next/wiring/TestBackend.ts index 21ae6159c9..14e8920390 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.ts +++ b/packages/backend-test-utils/src/next/wiring/TestBackend.ts @@ -156,7 +156,7 @@ function createExtensionPointTestModules( modules.push( createBackendModule({ pluginId, - moduleId: 'testExtensionPointRegistration', + moduleId: 'test-extension-point-registration', register(reg) { for (const id of pluginExtensionPointIds) { const tuple = extensionPointMap.get(id)!; diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 414904652d..272c3f17ee 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,179 @@ # example-backend +## 0.2.90-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/plugin-catalog-backend@1.16.0-next.2 + - @backstage/plugin-auth-backend@0.20.1-next.2 + - @backstage/plugin-lighthouse-backend@0.4.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.11-next.2 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.2 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.2 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.2 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.2 + - @backstage/plugin-search-backend-module-pg@0.5.17-next.2 + - @backstage/plugin-events-backend@0.2.17-next.2 + - example-app@0.2.90-next.3 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-adr-backend@0.4.5-next.2 + - @backstage/plugin-app-backend@0.3.56-next.2 + - @backstage/plugin-azure-devops-backend@0.5.0-next.2 + - @backstage/plugin-azure-sites-backend@0.1.18-next.2 + - @backstage/plugin-badges-backend@0.3.5-next.2 + - @backstage/plugin-code-coverage-backend@0.2.22-next.2 + - @backstage/plugin-devtools-backend@0.2.5-next.2 + - @backstage/plugin-entity-feedback-backend@0.2.5-next.2 + - @backstage/plugin-events-node@0.2.17-next.2 + - @backstage/plugin-explore-backend@0.0.18-next.2 + - @backstage/plugin-jenkins-backend@0.3.2-next.2 + - @backstage/plugin-kafka-backend@0.3.6-next.2 + - @backstage/plugin-kubernetes-backend@0.14.0-next.2 + - @backstage/plugin-linguist-backend@0.5.5-next.2 + - @backstage/plugin-nomad-backend@0.1.10-next.2 + - @backstage/plugin-permission-backend@0.5.31-next.2 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + - @backstage/plugin-playlist-backend@0.3.12-next.2 + - @backstage/plugin-proxy-backend@0.4.6-next.2 + - @backstage/plugin-rollbar-backend@0.1.53-next.2 + - @backstage/plugin-scaffolder-backend@1.19.2-next.2 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.9-next.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.25-next.2 + - @backstage/plugin-search-backend@1.4.8-next.2 + - @backstage/plugin-search-backend-node@1.2.12-next.2 + - @backstage/plugin-search-common@1.2.8 + - @backstage/plugin-tech-insights-backend@0.5.22-next.2 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.40-next.2 + - @backstage/plugin-tech-insights-node@0.4.14-next.2 + - @backstage/plugin-techdocs-backend@1.9.1-next.2 + - @backstage/plugin-todo-backend@0.3.6-next.2 + +## 0.2.90-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-backend@0.20.1-next.1 + - @backstage/plugin-catalog-backend@1.15.1-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/plugin-azure-devops-backend@0.5.0-next.1 + - @backstage/plugin-kubernetes-backend@0.14.0-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-azure-sites-backend@0.1.18-next.1 + - @backstage/backend-common@0.20.0-next.1 + - example-app@0.2.90-next.2 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-adr-backend@0.4.5-next.1 + - @backstage/plugin-app-backend@0.3.56-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-badges-backend@0.3.5-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-code-coverage-backend@0.2.22-next.1 + - @backstage/plugin-devtools-backend@0.2.5-next.1 + - @backstage/plugin-entity-feedback-backend@0.2.5-next.1 + - @backstage/plugin-events-backend@0.2.17-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + - @backstage/plugin-explore-backend@0.0.18-next.1 + - @backstage/plugin-jenkins-backend@0.3.2-next.1 + - @backstage/plugin-kafka-backend@0.3.6-next.1 + - @backstage/plugin-lighthouse-backend@0.3.5-next.1 + - @backstage/plugin-linguist-backend@0.5.5-next.1 + - @backstage/plugin-nomad-backend@0.1.10-next.1 + - @backstage/plugin-permission-backend@0.5.31-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + - @backstage/plugin-playlist-backend@0.3.12-next.1 + - @backstage/plugin-proxy-backend@0.4.6-next.1 + - @backstage/plugin-rollbar-backend@0.1.53-next.1 + - @backstage/plugin-scaffolder-backend@1.19.2-next.1 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.9-next.1 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.25-next.1 + - @backstage/plugin-search-backend@1.4.8-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.1 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.11-next.1 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.1 + - @backstage/plugin-search-backend-module-pg@0.5.17-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.1 + - @backstage/plugin-search-backend-node@1.2.12-next.1 + - @backstage/plugin-search-common@1.2.8 + - @backstage/plugin-tech-insights-backend@0.5.22-next.1 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.40-next.1 + - @backstage/plugin-tech-insights-node@0.4.14-next.1 + - @backstage/plugin-techdocs-backend@1.9.1-next.1 + - @backstage/plugin-todo-backend@0.3.6-next.1 + +## 0.2.90-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-backend@0.20.1-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-scaffolder-backend@1.19.2-next.0 + - @backstage/plugin-kubernetes-backend@0.14.0-next.0 + - @backstage/plugin-azure-sites-backend@0.1.18-next.0 + - @backstage/integration@1.8.0-next.0 + - example-app@0.2.90-next.0 + - @backstage/plugin-adr-backend@0.4.5-next.0 + - @backstage/plugin-app-backend@0.3.56-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-azure-devops-backend@0.4.5-next.0 + - @backstage/plugin-badges-backend@0.3.5-next.0 + - @backstage/plugin-catalog-backend@1.15.1-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/plugin-code-coverage-backend@0.2.22-next.0 + - @backstage/plugin-devtools-backend@0.2.5-next.0 + - @backstage/plugin-entity-feedback-backend@0.2.5-next.0 + - @backstage/plugin-events-backend@0.2.17-next.0 + - @backstage/plugin-explore-backend@0.0.18-next.0 + - @backstage/plugin-jenkins-backend@0.3.2-next.0 + - @backstage/plugin-kafka-backend@0.3.6-next.0 + - @backstage/plugin-lighthouse-backend@0.3.5-next.0 + - @backstage/plugin-linguist-backend@0.5.5-next.0 + - @backstage/plugin-nomad-backend@0.1.10-next.0 + - @backstage/plugin-permission-backend@0.5.31-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/plugin-playlist-backend@0.3.12-next.0 + - @backstage/plugin-proxy-backend@0.4.6-next.0 + - @backstage/plugin-rollbar-backend@0.1.53-next.0 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.9-next.0 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.25-next.0 + - @backstage/plugin-search-backend@1.4.8-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.11-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.0 + - @backstage/plugin-search-backend-module-pg@0.5.17-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.0 + - @backstage/plugin-search-backend-node@1.2.12-next.0 + - @backstage/plugin-tech-insights-backend@0.5.22-next.0 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.40-next.0 + - @backstage/plugin-tech-insights-node@0.4.14-next.0 + - @backstage/plugin-techdocs-backend@1.9.1-next.0 + - @backstage/plugin-todo-backend@0.3.6-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.5-next.0 + - @backstage/plugin-events-node@0.2.17-next.0 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-common@1.2.8 + ## 0.2.89 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index cfa234a552..fe072cf11a 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.89", + "version": "0.2.90-next.2", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -49,7 +49,6 @@ "@backstage/plugin-events-backend": "workspace:^", "@backstage/plugin-events-node": "workspace:^", "@backstage/plugin-explore-backend": "workspace:^", - "@backstage/plugin-graphql-backend": "workspace:^", "@backstage/plugin-jenkins-backend": "workspace:^", "@backstage/plugin-kafka-backend": "workspace:^", "@backstage/plugin-kubernetes-backend": "workspace:^", diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index 7a2618f0e0..d81062fd03 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/catalog-client +## 1.5.0-next.1 + +### Patch Changes + +- 82fa88b: Fixes a bug where some query parameters were double URL encoded. +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## 1.5.0-next.0 + +### Minor Changes + +- 38340678c3: The internals of `CatalogClient` are now auto-generated using the `backstage-repo-tools schema openapi generate-client` command. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 1.4.6 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index 02c30ee19b..24e4f3f4c7 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-client", "description": "An isomorphic client for the catalog backend", - "version": "1.4.6", + "version": "1.5.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,7 +35,8 @@ "dependencies": { "@backstage/catalog-model": "workspace:^", "@backstage/errors": "workspace:^", - "cross-fetch": "^4.0.0" + "cross-fetch": "^4.0.0", + "uri-template": "^2.0.0" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index f5c221569d..b8212fde96 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -86,9 +86,12 @@ describe('CatalogClient', () => { server.use( rest.get(`${mockBaseUrl}/entities`, (req, res, ctx) => { - expect(req.url.search).toBe( - '?filter=a=1,b=2,b=3,%C3%B6=%3D&filter=a=2&filter=c', - ); + const queryParams = new URLSearchParams(req.url.search); + expect(queryParams.getAll('filter')).toEqual([ + 'a=1,b=2,b=3,ö==', + 'a=2', + 'c', + ]); return res(ctx.json([])); }), ); @@ -120,7 +123,8 @@ describe('CatalogClient', () => { server.use( rest.get(`${mockBaseUrl}/entities`, (req, res, ctx) => { - expect(req.url.search).toBe('?filter=a=1,b=2,b=3,%C3%B6=%3D,c'); + const queryParams = new URLSearchParams(req.url.search); + expect(queryParams.getAll('filter')).toEqual(['a=1,b=2,b=3,ö==,c']); return res(ctx.json([])); }), ); @@ -140,12 +144,45 @@ describe('CatalogClient', () => { expect(response.items).toEqual([]); }); + it('builds search filters property even those with URL unsafe values', async () => { + const mockedEndpoint = jest + .fn() + .mockImplementation((_req, res, ctx) => + res(ctx.json({ items: [], totalItems: 0 })), + ); + + server.use(rest.get(`${mockBaseUrl}/entities/by-query`, mockedEndpoint)); + + const response = await client.queryEntities( + { + filter: [ + { + '!@#$%': 't?i=1&a:2', + '^&*(){}[]': ['t%^url*encoded2', 'url'], + }, + ], + }, + { token }, + ); + + expect(response).toEqual({ items: [], totalItems: 0 }); + expect(mockedEndpoint).toHaveBeenCalledTimes(1); + + const queryParams = new URLSearchParams( + mockedEndpoint.mock.calls[0][0].url.search, + ); + expect(queryParams.getAll('filter')).toEqual([ + '!@#$%=t?i=1&a:2,^&*(){}[]=t%^url*encoded2,^&*(){}[]=url', + ]); + }); + it('builds entity field selectors properly', async () => { expect.assertions(2); server.use( rest.get(`${mockBaseUrl}/entities`, (req, res, ctx) => { - expect(req.url.search).toBe('?fields=a.b,%C3%B6'); + const queryParams = new URLSearchParams(req.url.search); + expect(queryParams.getAll('fields')).toEqual(['a.b,ö']); return res(ctx.json([])); }), ); @@ -185,7 +222,7 @@ describe('CatalogClient', () => { server.use( rest.get(`${mockBaseUrl}/entities`, (req, res, ctx) => { - expect(req.url.search).toBe('?offset=1&limit=2&after=%3D'); + expect(req.url.search).toBe('?limit=2&offset=1&after=%3D'); return res(ctx.json([])); }), ); @@ -203,9 +240,11 @@ describe('CatalogClient', () => { server.use( rest.get(`${mockBaseUrl}/entities`, (req, res, ctx) => { - expect(req.url.search).toBe( - '?order=asc:kind&order=desc:metadata.name', - ); + const queryParams = new URLSearchParams(req.url.search); + expect(queryParams.getAll('order')).toEqual([ + 'asc:kind', + 'desc:metadata.name', + ]); return res(ctx.json([])); }), ); @@ -326,9 +365,46 @@ describe('CatalogClient', () => { expect(response).toEqual({ items: [], totalItems: 0 }); expect(mockedEndpoint).toHaveBeenCalledTimes(1); - expect(mockedEndpoint.mock.calls[0][0].url.search).toBe( - '?filter=a=1,b=2,b=3,%C3%B6=%3D&filter=a=2&filter=c', + + const queryParams = new URLSearchParams( + mockedEndpoint.mock.calls[0][0].url.search, ); + expect(queryParams.getAll('filter')).toEqual([ + 'a=1,b=2,b=3,ö==', + 'a=2', + 'c', + ]); + }); + + it('builds search filters property even those with URL unsafe values', async () => { + const mockedEndpoint = jest + .fn() + .mockImplementation((_req, res, ctx) => + res(ctx.json({ items: [], totalItems: 0 })), + ); + + server.use(rest.get(`${mockBaseUrl}/entities/by-query`, mockedEndpoint)); + + const response = await client.queryEntities( + { + filter: [ + { + '!@#$%': 't?i=1&a:2', + '^&*(){}[]': ['t%^url*encoded2', 'url'], + }, + ], + }, + { token }, + ); + + expect(response).toEqual({ items: [], totalItems: 0 }); + expect(mockedEndpoint).toHaveBeenCalledTimes(1); + const queryParams = new URLSearchParams( + mockedEndpoint.mock.calls[0][0].url.search, + ); + expect(queryParams.getAll('filter')).toEqual([ + '!@#$%=t?i=1&a:2,^&*(){}[]=t%^url*encoded2,^&*(){}[]=url', + ]); }); it('should send query params correctly on initial request', async () => { @@ -351,9 +427,17 @@ describe('CatalogClient', () => { { field: 'metadata.uid', order: 'desc' }, ], }); - expect(mockedEndpoint.mock.calls[0][0].url.search).toBe( - '?limit=100&orderField=metadata.name,asc&orderField=metadata.uid,desc&fields=a,b&fullTextFilterTerm=query', + + const queryParams = new URLSearchParams( + mockedEndpoint.mock.calls[0][0].url.search, ); + expect(queryParams.getAll('fields')).toEqual(['a,b']); + expect(queryParams.getAll('limit')).toEqual(['100']); + expect(queryParams.getAll('fullTextFilterTerm')).toEqual(['query']); + expect(queryParams.getAll('orderField')).toEqual([ + 'metadata.name,asc', + 'metadata.uid,desc', + ]); }); it('should ignore initial query params if cursor is passed', async () => { @@ -375,7 +459,7 @@ describe('CatalogClient', () => { cursor: 'cursor', }); expect(mockedEndpoint.mock.calls[0][0].url.search).toBe( - '?cursor=cursor&limit=100&fields=a,b', + '?fields=a,b&limit=100&cursor=cursor', ); }); diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index c388519e05..f97360d1d7 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -22,7 +22,6 @@ import { stringifyLocationRef, } from '@backstage/catalog-model'; import { ResponseError } from '@backstage/errors'; -import crossFetch from 'cross-fetch'; import { CATALOG_FILTER_EXISTS, AddLocationRequest, @@ -40,12 +39,11 @@ import { GetEntitiesByRefsRequest, GetEntitiesByRefsResponse, QueryEntitiesRequest, - QueryEntitiesResponse, EntityFilterQuery, + QueryEntitiesResponse, } from './types/api'; -import { DiscoveryApi } from './types/discovery'; -import { FetchApi } from './types/fetch'; import { isQueryEntitiesInitialRequest } from './utils'; +import { DefaultApiClient } from './generated'; /** * A frontend and backend compatible client for communicating with the Backstage @@ -54,15 +52,13 @@ import { isQueryEntitiesInitialRequest } from './utils'; * @public */ export class CatalogClient implements CatalogApi { - private readonly discoveryApi: DiscoveryApi; - private readonly fetchApi: FetchApi; + private readonly apiClient: DefaultApiClient; constructor(options: { discoveryApi: { getBaseUrl(pluginId: string): Promise }; fetchApi?: { fetch: typeof fetch }; }) { - this.discoveryApi = options.discoveryApi; - this.fetchApi = options.fetchApi || { fetch: crossFetch }; + this.apiClient = new DefaultApiClient(options); } /** @@ -72,13 +68,11 @@ export class CatalogClient implements CatalogApi { request: GetEntityAncestorsRequest, options?: CatalogRequestOptions, ): Promise { - const { kind, namespace, name } = parseEntityRef(request.entityRef); return await this.requestRequired( - 'GET', - `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent( - namespace, - )}/${encodeURIComponent(name)}/ancestry`, - options, + await this.apiClient.getEntityAncestryByName( + { path: parseEntityRef(request.entityRef) }, + options, + ), ); } @@ -90,9 +84,7 @@ export class CatalogClient implements CatalogApi { options?: CatalogRequestOptions, ): Promise { return await this.requestOptional( - 'GET', - `/locations/${encodeURIComponent(id)}`, - options, + await this.apiClient.getLocation({ path: { id } }, options), ); } @@ -111,39 +103,29 @@ export class CatalogClient implements CatalogApi { limit, after, } = request ?? {}; - const params = this.getParams(filter); - - if (fields.length) { - params.push(`fields=${fields.map(encodeURIComponent).join(',')}`); - } - + const encodedOrder = []; if (order) { for (const directive of [order].flat()) { if (directive) { - params.push( - `order=${encodeURIComponent(directive.order)}:${encodeURIComponent( - directive.field, - )}`, - ); + encodedOrder.push(`${directive.order}:${directive.field}`); } } } - if (offset !== undefined) { - params.push(`offset=${offset}`); - } - if (limit !== undefined) { - params.push(`limit=${limit}`); - } - if (after !== undefined) { - params.push(`after=${encodeURIComponent(after)}`); - } - - const query = params.length ? `?${params.join('&')}` : ''; const entities: Entity[] = await this.requestRequired( - 'GET', - `/entities${query}`, - options, + await this.apiClient.getEntities( + { + query: { + fields, + limit, + filter: this.getFilterValue(filter), + offset, + after, + order: order ? encodedOrder : undefined, + }, + }, + options, + ), ); const refCompare = (a: Entity, b: Entity) => { @@ -178,22 +160,12 @@ export class CatalogClient implements CatalogApi { request: GetEntitiesByRefsRequest, options?: CatalogRequestOptions, ): Promise { - const body: any = { entityRefs: request.entityRefs }; - if (request.fields?.length) { - body.fields = request.fields; - } - - const baseUrl = await this.discoveryApi.getBaseUrl('catalog'); - const url = `${baseUrl}/entities/by-refs`; - - const response = await this.fetchApi.fetch(url, { - headers: { - 'Content-Type': 'application/json', - ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + const response = await this.apiClient.getEntitiesByRefs( + { + body: request, }, - method: 'POST', - body: JSON.stringify(body), - }); + options, + ); if (!response.ok) { throw await ResponseError.fromResponse(response); @@ -212,8 +184,10 @@ export class CatalogClient implements CatalogApi { async queryEntities( request: QueryEntitiesRequest = {}, options?: CatalogRequestOptions, - ) { - const params: string[] = []; + ): Promise { + const params: Partial< + Parameters[0]['query'] + > = {}; if (isQueryEntitiesInitialRequest(request)) { const { @@ -223,45 +197,42 @@ export class CatalogClient implements CatalogApi { orderFields, fullTextFilter, } = request; - params.push(...this.getParams(filter)); + params.filter = this.getFilterValue(filter); if (limit !== undefined) { - params.push(`limit=${limit}`); + params.limit = limit; } if (orderFields !== undefined) { - (Array.isArray(orderFields) ? orderFields : [orderFields]).forEach( - ({ field, order }) => params.push(`orderField=${field},${order}`), - ); + params.orderField = ( + Array.isArray(orderFields) ? orderFields : [orderFields] + ).map(({ field, order }) => `${field},${order}`); } if (fields.length) { - params.push(`fields=${fields.map(encodeURIComponent).join(',')}`); + params.fields = fields; } const normalizedFullTextFilterTerm = fullTextFilter?.term?.trim(); if (normalizedFullTextFilterTerm) { - params.push(`fullTextFilterTerm=${normalizedFullTextFilterTerm}`); + params.fullTextFilterTerm = normalizedFullTextFilterTerm; } if (fullTextFilter?.fields?.length) { - params.push(`fullTextFilterFields=${fullTextFilter.fields.join(',')}`); + params.fullTextFilterFields = fullTextFilter.fields; } } else { const { fields = [], limit, cursor } = request; - params.push(`cursor=${cursor}`); + params.cursor = cursor; if (limit !== undefined) { - params.push(`limit=${limit}`); + params.limit = limit; } if (fields.length) { - params.push(`fields=${fields.map(encodeURIComponent).join(',')}`); + params.fields = fields; } } - const query = params.length ? `?${params.join('&')}` : ''; - return this.requestRequired( - 'GET', - `/entities/by-query${query}`, - options, - ); + return this.apiClient + .getEntitiesByQuery({ query: params }, options) + .then(r => r.json()); } /** @@ -271,13 +242,13 @@ export class CatalogClient implements CatalogApi { entityRef: string | CompoundEntityRef, options?: CatalogRequestOptions, ): Promise { - const { kind, namespace, name } = parseEntityRef(entityRef); return this.requestOptional( - 'GET', - `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent( - namespace, - )}/${encodeURIComponent(name)}`, - options, + await this.apiClient.getEntityByName( + { + path: parseEntityRef(entityRef), + }, + options, + ), ); } @@ -294,11 +265,10 @@ export class CatalogClient implements CatalogApi { ): Promise { const { kind, namespace = 'default', name } = compoundName; return this.requestOptional( - 'GET', - `/entities/by-name/${encodeURIComponent(kind)}/${encodeURIComponent( - namespace, - )}/${encodeURIComponent(name)}`, - options, + await this.apiClient.getEntityByName( + { path: { kind, namespace, name } }, + options, + ), ); } @@ -306,16 +276,9 @@ export class CatalogClient implements CatalogApi { * {@inheritdoc CatalogApi.refreshEntity} */ async refreshEntity(entityRef: string, options?: CatalogRequestOptions) { - const response = await this.fetchApi.fetch( - `${await this.discoveryApi.getBaseUrl('catalog')}/refresh`, - { - headers: { - 'Content-Type': 'application/json', - ...(options?.token && { Authorization: `Bearer ${options?.token}` }), - }, - method: 'POST', - body: JSON.stringify({ entityRef }), - }, + const response = await this.apiClient.refreshEntity( + { body: { entityRef } }, + options, ); if (response.status !== 200) { @@ -331,14 +294,14 @@ export class CatalogClient implements CatalogApi { options?: CatalogRequestOptions, ): Promise { const { filter = [], facets } = request; - const params = this.getParams(filter); - - for (const facet of facets) { - params.push(`facet=${encodeURIComponent(facet)}`); - } - - const query = params.length ? `?${params.join('&')}` : ''; - return await this.requestOptional('GET', `/entity-facets${query}`, options); + return await this.requestOptional( + await this.apiClient.getEntityFacets( + { + query: { facet: facets, filter: this.getFilterValue(filter) }, + }, + options, + ), + ); } /** @@ -350,18 +313,12 @@ export class CatalogClient implements CatalogApi { ): Promise { const { type = 'url', target, dryRun } = request; - const response = await this.fetchApi.fetch( - `${await this.discoveryApi.getBaseUrl('catalog')}/locations${ - dryRun ? '?dryRun=true' : '' - }`, + const response = await this.apiClient.createLocation( { - headers: { - 'Content-Type': 'application/json', - ...(options?.token && { Authorization: `Bearer ${options?.token}` }), - }, - method: 'POST', - body: JSON.stringify({ type, target }), + body: { type, target }, + query: { dryRun: dryRun ? 'true' : undefined }, }, + options, ); if (response.status !== 201) { @@ -389,9 +346,7 @@ export class CatalogClient implements CatalogApi { options?: CatalogRequestOptions, ): Promise { const all: { data: Location }[] = await this.requestRequired( - 'GET', - '/locations', - options, + await this.apiClient.getLocation({ path: { id: locationRef } }, options), ); return all .map(r => r.data) @@ -406,9 +361,7 @@ export class CatalogClient implements CatalogApi { options?: CatalogRequestOptions, ): Promise { await this.requestIgnored( - 'DELETE', - `/locations/${encodeURIComponent(id)}`, - options, + await this.apiClient.deleteLocation({ path: { id } }, options), ); } @@ -420,9 +373,7 @@ export class CatalogClient implements CatalogApi { options?: CatalogRequestOptions, ): Promise { await this.requestIgnored( - 'DELETE', - `/entities/by-uid/${encodeURIComponent(uid)}`, - options, + await this.apiClient.deleteEntityByUid({ path: { uid } }, options), ); } @@ -434,16 +385,9 @@ export class CatalogClient implements CatalogApi { locationRef: string, options?: CatalogRequestOptions, ): Promise { - const response = await this.fetchApi.fetch( - `${await this.discoveryApi.getBaseUrl('catalog')}/validate-entity`, - { - headers: { - 'Content-Type': 'application/json', - ...(options?.token && { Authorization: `Bearer ${options?.token}` }), - }, - method: 'POST', - body: JSON.stringify({ entity, location: locationRef }), - }, + const response = await this.apiClient.validateEntity( + { body: { entity, location: locationRef } }, + options, ); if (response.ok) { @@ -456,7 +400,7 @@ export class CatalogClient implements CatalogApi { throw await ResponseError.fromResponse(response); } - const { errors = [] } = await response.json(); + const { errors = [] } = (await response.json()) as any; return { valid: false, @@ -468,33 +412,13 @@ export class CatalogClient implements CatalogApi { // Private methods // - private async requestIgnored( - method: string, - path: string, - options?: CatalogRequestOptions, - ): Promise { - const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`; - const headers: Record = options?.token - ? { Authorization: `Bearer ${options.token}` } - : {}; - const response = await this.fetchApi.fetch(url, { method, headers }); - + private async requestIgnored(response: Response): Promise { if (!response.ok) { throw await ResponseError.fromResponse(response); } } - private async requestRequired( - method: string, - path: string, - options?: CatalogRequestOptions, - ): Promise { - const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`; - const headers: Record = options?.token - ? { Authorization: `Bearer ${options.token}` } - : {}; - const response = await this.fetchApi.fetch(url, { method, headers }); - + private async requestRequired(response: Response): Promise { if (!response.ok) { throw await ResponseError.fromResponse(response); } @@ -502,17 +426,7 @@ export class CatalogClient implements CatalogApi { return response.json(); } - private async requestOptional( - method: string, - path: string, - options?: CatalogRequestOptions, - ): Promise { - const url = `${await this.discoveryApi.getBaseUrl('catalog')}${path}`; - const headers: Record = options?.token - ? { Authorization: `Bearer ${options.token}` } - : {}; - const response = await this.fetchApi.fetch(url, { method, headers }); - + private async requestOptional(response: Response): Promise { if (!response.ok) { if (response.status === 404) { return undefined; @@ -523,8 +437,8 @@ export class CatalogClient implements CatalogApi { return await response.json(); } - private getParams(filter: EntityFilterQuery = []) { - const params: string[] = []; + private getFilterValue(filter: EntityFilterQuery = []) { + const filters: string[] = []; // filter param can occur multiple times, for example // /api/catalog/entities?filter=metadata.name=wayback-search,kind=component&filter=metadata.name=www-artist,kind=component' // the "outer array" defined by `filter` occurrences corresponds to "anyOf" filters @@ -534,19 +448,17 @@ export class CatalogClient implements CatalogApi { for (const [key, value] of Object.entries(filterItem)) { for (const v of [value].flat()) { if (v === CATALOG_FILTER_EXISTS) { - filterParts.push(encodeURIComponent(key)); + filterParts.push(key); } else if (typeof v === 'string') { - filterParts.push( - `${encodeURIComponent(key)}=${encodeURIComponent(v)}`, - ); + filterParts.push(`${key}=${v}`); } } } if (filterParts.length) { - params.push(`filter=${filterParts.join(',')}`); + filters.push(filterParts.join(',')); } } - return params; + return filters; } } diff --git a/packages/catalog-client/src/generated/apis/DefaultApi.client.ts b/packages/catalog-client/src/generated/apis/DefaultApi.client.ts new file mode 100644 index 0000000000..260f7c9fc8 --- /dev/null +++ b/packages/catalog-client/src/generated/apis/DefaultApi.client.ts @@ -0,0 +1,535 @@ +/* + * 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. + */ + +import { DiscoveryApi } from '../types/discovery'; +import { FetchApi } from '../types/fetch'; +import crossFetch from 'cross-fetch'; +import { pluginId } from '../pluginId'; +import * as parser from 'uri-template'; + +import { AnalyzeLocationRequest } from '../models/AnalyzeLocationRequest.model'; +import { AnalyzeLocationResponse } from '../models/AnalyzeLocationResponse.model'; +import { CreateLocation201Response } from '../models/CreateLocation201Response.model'; +import { CreateLocationRequest } from '../models/CreateLocationRequest.model'; +import { EntitiesBatchResponse } from '../models/EntitiesBatchResponse.model'; +import { EntitiesQueryResponse } from '../models/EntitiesQueryResponse.model'; +import { Entity } from '../models/Entity.model'; +import { EntityAncestryResponse } from '../models/EntityAncestryResponse.model'; +import { EntityFacetsResponse } from '../models/EntityFacetsResponse.model'; +import { GetEntitiesByRefsRequest } from '../models/GetEntitiesByRefsRequest.model'; +import { GetLocations200ResponseInner } from '../models/GetLocations200ResponseInner.model'; +import { Location } from '../models/Location.model'; +import { RefreshEntityRequest } from '../models/RefreshEntityRequest.model'; +import { ValidateEntityRequest } from '../models/ValidateEntityRequest.model'; + +type TypedResponse = Omit & { + json: () => Promise; +}; + +/** + * Options you can pass into a request for additional information. + * + * @public + */ +export interface RequestOptions { + token?: string; +} + +/** + * no description + */ +export class DefaultApiClient { + private readonly discoveryApi: DiscoveryApi; + private readonly fetchApi: FetchApi; + + constructor(options: { + discoveryApi: { getBaseUrl(pluginId: string): Promise }; + fetchApi?: { fetch: typeof fetch }; + }) { + this.discoveryApi = options.discoveryApi; + this.fetchApi = options.fetchApi || { fetch: crossFetch }; + } + + /** + * Validate a given location. + * @param analyzeLocationRequest + */ + public async analyzeLocation( + // @ts-ignore + request: { + body: AnalyzeLocationRequest; + }, + options?: RequestOptions, + ): Promise> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/analyze-location`; + + const uri = parser.parse(uriTemplate).expand({}); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'POST', + body: JSON.stringify(request.body), + }); + } + + /** + * Create a location for a given target. + * @param createLocationRequest + * @param dryRun + */ + public async createLocation( + // @ts-ignore + request: { + body: CreateLocationRequest; + query: { + dryRun?: string; + }; + }, + options?: RequestOptions, + ): Promise> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/locations{?dryRun}`; + + const uri = parser.parse(uriTemplate).expand({ + ...request.query, + }); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'POST', + body: JSON.stringify(request.body), + }); + } + + /** + * Delete a single entity by UID. + * @param uid + */ + public async deleteEntityByUid( + // @ts-ignore + request: { + path: { + uid: string; + }; + }, + options?: RequestOptions, + ): Promise> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/entities/by-uid/{uid}`; + + const uri = parser.parse(uriTemplate).expand({ + uid: request.path.uid, + }); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'DELETE', + }); + } + + /** + * Delete a location by id. + * @param id + */ + public async deleteLocation( + // @ts-ignore + request: { + path: { + id: string; + }; + }, + options?: RequestOptions, + ): Promise> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/locations/{id}`; + + const uri = parser.parse(uriTemplate).expand({ + id: request.path.id, + }); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'DELETE', + }); + } + + /** + * Get all entities matching a given filter. + * @param fields Restrict to just these fields in the response. + * @param limit Number of records to return in the response. + * @param filter Filter for just the entities defined by this filter. + * @param offset Number of records to skip in the query page. + * @param after Pointer to the previous page of results. + * @param order + */ + public async getEntities( + // @ts-ignore + request: { + query: { + fields?: Array; + limit?: number; + filter?: Array; + offset?: number; + after?: string; + order?: Array; + }; + }, + options?: RequestOptions, + ): Promise>> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/entities{?fields,limit,filter*,offset,after,order*}`; + + const uri = parser.parse(uriTemplate).expand({ + ...request.query, + }); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'GET', + }); + } + + /** + * Search for entities by a given query. + * @param fields Restrict to just these fields in the response. + * @param limit Number of records to return in the response. + * @param orderField The fields to sort returned results by. + * @param cursor Cursor to a set page of results. + * @param filter Filter for just the entities defined by this filter. + * @param fullTextFilterTerm Text search term. + * @param fullTextFilterFields A comma separated list of fields to sort returned results by. + */ + public async getEntitiesByQuery( + // @ts-ignore + request: { + query: { + fields?: Array; + limit?: number; + orderField?: Array; + cursor?: string; + filter?: Array; + fullTextFilterTerm?: string; + fullTextFilterFields?: Array; + }; + }, + options?: RequestOptions, + ): Promise> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/entities/by-query{?fields,limit,orderField*,cursor,filter*,fullTextFilterTerm,fullTextFilterFields}`; + + const uri = parser.parse(uriTemplate).expand({ + ...request.query, + }); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'GET', + }); + } + + /** + * Get a batch set of entities given an array of entityRefs. + * @param getEntitiesByRefsRequest + */ + public async getEntitiesByRefs( + // @ts-ignore + request: { + body: GetEntitiesByRefsRequest; + }, + options?: RequestOptions, + ): Promise> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/entities/by-refs`; + + const uri = parser.parse(uriTemplate).expand({}); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'POST', + body: JSON.stringify(request.body), + }); + } + + /** + * Get an entity's ancestry by entity ref. + * @param kind + * @param namespace + * @param name + */ + public async getEntityAncestryByName( + // @ts-ignore + request: { + path: { + kind: string; + namespace: string; + name: string; + }; + }, + options?: RequestOptions, + ): Promise> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/entities/by-name/{kind}/{namespace}/{name}/ancestry`; + + const uri = parser.parse(uriTemplate).expand({ + kind: request.path.kind, + namespace: request.path.namespace, + name: request.path.name, + }); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'GET', + }); + } + + /** + * Get an entity by an entity ref. + * @param kind + * @param namespace + * @param name + */ + public async getEntityByName( + // @ts-ignore + request: { + path: { + kind: string; + namespace: string; + name: string; + }; + }, + options?: RequestOptions, + ): Promise> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/entities/by-name/{kind}/{namespace}/{name}`; + + const uri = parser.parse(uriTemplate).expand({ + kind: request.path.kind, + namespace: request.path.namespace, + name: request.path.name, + }); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'GET', + }); + } + + /** + * Get a single entity by the UID. + * @param uid + */ + public async getEntityByUid( + // @ts-ignore + request: { + path: { + uid: string; + }; + }, + options?: RequestOptions, + ): Promise> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/entities/by-uid/{uid}`; + + const uri = parser.parse(uriTemplate).expand({ + uid: request.path.uid, + }); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'GET', + }); + } + + /** + * Get all entity facets that match the given filters. + * @param facet + * @param filter Filter for just the entities defined by this filter. + */ + public async getEntityFacets( + // @ts-ignore + request: { + query: { + facet: Array; + filter?: Array; + }; + }, + options?: RequestOptions, + ): Promise> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/entity-facets{?facet*,filter*}`; + + const uri = parser.parse(uriTemplate).expand({ + ...request.query, + }); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'GET', + }); + } + + /** + * Get a location by id. + * @param id + */ + public async getLocation( + // @ts-ignore + request: { + path: { + id: string; + }; + }, + options?: RequestOptions, + ): Promise> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/locations/{id}`; + + const uri = parser.parse(uriTemplate).expand({ + id: request.path.id, + }); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'GET', + }); + } + + /** + * Get all locations + */ + public async getLocations( + // @ts-ignore + request: {}, + options?: RequestOptions, + ): Promise>> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/locations`; + + const uri = parser.parse(uriTemplate).expand({}); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'GET', + }); + } + + /** + * Refresh the entity related to entityRef. + * @param refreshEntityRequest + */ + public async refreshEntity( + // @ts-ignore + request: { + body: RefreshEntityRequest; + }, + options?: RequestOptions, + ): Promise> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/refresh`; + + const uri = parser.parse(uriTemplate).expand({}); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'POST', + body: JSON.stringify(request.body), + }); + } + + /** + * Validate that a passed in entity has no errors in schema. + * @param validateEntityRequest + */ + public async validateEntity( + // @ts-ignore + request: { + body: ValidateEntityRequest; + }, + options?: RequestOptions, + ): Promise> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `/validate-entity`; + + const uri = parser.parse(uriTemplate).expand({}); + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: 'POST', + body: JSON.stringify(request.body), + }); + } +} diff --git a/packages/catalog-client/src/generated/apis/index.ts b/packages/catalog-client/src/generated/apis/index.ts new file mode 100644 index 0000000000..ad2f72c5b2 --- /dev/null +++ b/packages/catalog-client/src/generated/apis/index.ts @@ -0,0 +1,17 @@ +/* + * 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 * from './DefaultApi.client'; diff --git a/packages/catalog-client/src/generated/index.ts b/packages/catalog-client/src/generated/index.ts new file mode 100644 index 0000000000..0cf3e9cc49 --- /dev/null +++ b/packages/catalog-client/src/generated/index.ts @@ -0,0 +1,18 @@ +/* + * 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 * from './apis'; +export * from './models'; diff --git a/packages/catalog-client/src/generated/models/AnalyzeLocationEntityField.model.ts b/packages/catalog-client/src/generated/models/AnalyzeLocationEntityField.model.ts new file mode 100644 index 0000000000..a1c1e1f669 --- /dev/null +++ b/packages/catalog-client/src/generated/models/AnalyzeLocationEntityField.model.ts @@ -0,0 +1,36 @@ +/* + * 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 interface AnalyzeLocationEntityField { + /** + * A text to show to the user to inform about the choices made. Like, it could say \"Found a CODEOWNERS file that covers this target, so we suggest leaving this field empty; which would currently make it owned by X\" where X is taken from the codeowners file. + */ + description: string; + value: string | null; + /** + * The outcome of the analysis for this particular field + */ + state: AnalyzeLocationEntityFieldStateEnum; + /** + * e.g. \"spec.owner\"? The frontend needs to know how to \"inject\" the field into the entity again if the user wants to change it + */ + field: string; +} + +export type AnalyzeLocationEntityFieldStateEnum = + | 'analysisSuggestedValue' + | 'analysisSuggestedNoValue' + | 'needsUserInput'; diff --git a/packages/catalog-client/src/generated/models/AnalyzeLocationExistingEntity.model.ts b/packages/catalog-client/src/generated/models/AnalyzeLocationExistingEntity.model.ts new file mode 100644 index 0000000000..5ede0fb60b --- /dev/null +++ b/packages/catalog-client/src/generated/models/AnalyzeLocationExistingEntity.model.ts @@ -0,0 +1,27 @@ +/* + * 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. + */ + +import { Entity } from '../models/Entity.model'; +import { LocationSpec } from '../models/LocationSpec.model'; + +/** + * If the folder pointed to already contained catalog info yaml files, they are read and emitted like this so that the frontend can inform the user that it located them and can make sure to register them as well if they weren't already + */ +export interface AnalyzeLocationExistingEntity { + entity: Entity; + isRegistered: boolean; + location: LocationSpec; +} diff --git a/packages/catalog-client/src/generated/models/AnalyzeLocationGenerateEntity.model.ts b/packages/catalog-client/src/generated/models/AnalyzeLocationGenerateEntity.model.ts new file mode 100644 index 0000000000..886aac05d9 --- /dev/null +++ b/packages/catalog-client/src/generated/models/AnalyzeLocationGenerateEntity.model.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import { AnalyzeLocationEntityField } from '../models/AnalyzeLocationEntityField.model'; +import { RecursivePartialEntity } from '../models/RecursivePartialEntity.model'; + +/** + * This is some form of representation of what the analyzer could deduce. We should probably have a chat about how this can best be conveyed to the frontend. It'll probably contain a (possibly incomplete) entity, plus enough info for the frontend to know what form data to show to the user for overriding/completing the info. + */ +export interface AnalyzeLocationGenerateEntity { + fields: Array; + entity: RecursivePartialEntity; +} diff --git a/packages/catalog-client/src/generated/models/AnalyzeLocationRequest.model.ts b/packages/catalog-client/src/generated/models/AnalyzeLocationRequest.model.ts new file mode 100644 index 0000000000..e8e9542f5a --- /dev/null +++ b/packages/catalog-client/src/generated/models/AnalyzeLocationRequest.model.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import { LocationInput } from '../models/LocationInput.model'; + +export interface AnalyzeLocationRequest { + catalogFileName?: string; + location: LocationInput; +} diff --git a/packages/catalog-client/src/generated/models/AnalyzeLocationResponse.model.ts b/packages/catalog-client/src/generated/models/AnalyzeLocationResponse.model.ts new file mode 100644 index 0000000000..bf60aa8018 --- /dev/null +++ b/packages/catalog-client/src/generated/models/AnalyzeLocationResponse.model.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +import { AnalyzeLocationExistingEntity } from '../models/AnalyzeLocationExistingEntity.model'; +import { AnalyzeLocationGenerateEntity } from '../models/AnalyzeLocationGenerateEntity.model'; + +export interface AnalyzeLocationResponse { + generateEntities: Array; + existingEntityFiles: Array; +} diff --git a/packages/catalog-client/src/generated/models/CreateLocation201Response.model.ts b/packages/catalog-client/src/generated/models/CreateLocation201Response.model.ts new file mode 100644 index 0000000000..d090d80bf2 --- /dev/null +++ b/packages/catalog-client/src/generated/models/CreateLocation201Response.model.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +import { Entity } from '../models/Entity.model'; +import { Location } from '../models/Location.model'; + +export interface CreateLocation201Response { + exists?: boolean; + entities: Array; + location: Location; +} diff --git a/packages/catalog-client/src/generated/models/CreateLocationRequest.model.ts b/packages/catalog-client/src/generated/models/CreateLocationRequest.model.ts new file mode 100644 index 0000000000..6ef950072e --- /dev/null +++ b/packages/catalog-client/src/generated/models/CreateLocationRequest.model.ts @@ -0,0 +1,20 @@ +/* + * 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 interface CreateLocationRequest { + target: string; + type: string; +} diff --git a/packages/catalog-client/src/generated/models/EntitiesBatchResponse.model.ts b/packages/catalog-client/src/generated/models/EntitiesBatchResponse.model.ts new file mode 100644 index 0000000000..d09b2cc086 --- /dev/null +++ b/packages/catalog-client/src/generated/models/EntitiesBatchResponse.model.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +import { NullableEntity } from '../models/NullableEntity.model'; + +export interface EntitiesBatchResponse { + /** + * The list of entities, in the same order as the refs in the request. Entries that are null signify that no entity existed with that ref. + */ + items: Array; +} diff --git a/packages/catalog-client/src/generated/models/EntitiesQueryResponse.model.ts b/packages/catalog-client/src/generated/models/EntitiesQueryResponse.model.ts new file mode 100644 index 0000000000..10d4747caf --- /dev/null +++ b/packages/catalog-client/src/generated/models/EntitiesQueryResponse.model.ts @@ -0,0 +1,27 @@ +/* + * 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. + */ + +import { EntitiesQueryResponsePageInfo } from '../models/EntitiesQueryResponsePageInfo.model'; +import { Entity } from '../models/Entity.model'; + +export interface EntitiesQueryResponse { + /** + * The list of entities paginated by a specific filter. + */ + items: Array; + totalItems: number; + pageInfo: EntitiesQueryResponsePageInfo; +} diff --git a/packages/catalog-client/src/generated/models/EntitiesQueryResponsePageInfo.model.ts b/packages/catalog-client/src/generated/models/EntitiesQueryResponsePageInfo.model.ts new file mode 100644 index 0000000000..8a7d5b39bb --- /dev/null +++ b/packages/catalog-client/src/generated/models/EntitiesQueryResponsePageInfo.model.ts @@ -0,0 +1,26 @@ +/* + * 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 interface EntitiesQueryResponsePageInfo { + /** + * The cursor for the next batch of entities. + */ + nextCursor?: string; + /** + * The cursor for the previous batch of entities. + */ + prevCursor?: string; +} diff --git a/packages/catalog-client/src/generated/models/Entity.model.ts b/packages/catalog-client/src/generated/models/Entity.model.ts new file mode 100644 index 0000000000..59ef9bc741 --- /dev/null +++ b/packages/catalog-client/src/generated/models/Entity.model.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ + +import { EntityMeta } from '../models/EntityMeta.model'; +import { EntityRelation } from '../models/EntityRelation.model'; + +/** + * The parts of the format that's common to all versions/kinds of entity. + */ +export interface Entity { + /** + * The relations that this entity has with other entities. + */ + relations?: Array; + /** + * A type representing all allowed JSON object values. + */ + spec?: { [key: string]: any }; + metadata: EntityMeta; + /** + * The high level entity type being described. + */ + kind: string; + /** + * The version of specification format for this particular entity that this is written against. + */ + apiVersion: string; +} diff --git a/packages/catalog-client/src/generated/models/EntityAncestryResponse.model.ts b/packages/catalog-client/src/generated/models/EntityAncestryResponse.model.ts new file mode 100644 index 0000000000..08076fcf36 --- /dev/null +++ b/packages/catalog-client/src/generated/models/EntityAncestryResponse.model.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import { EntityAncestryResponseItemsInner } from '../models/EntityAncestryResponseItemsInner.model'; + +export interface EntityAncestryResponse { + items: Array; + rootEntityRef: string; +} diff --git a/packages/catalog-client/src/generated/models/EntityAncestryResponseItemsInner.model.ts b/packages/catalog-client/src/generated/models/EntityAncestryResponseItemsInner.model.ts new file mode 100644 index 0000000000..7713c21295 --- /dev/null +++ b/packages/catalog-client/src/generated/models/EntityAncestryResponseItemsInner.model.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +import { Entity } from '../models/Entity.model'; + +export interface EntityAncestryResponseItemsInner { + parentEntityRefs: Array; + entity: Entity; +} diff --git a/packages/catalog-client/src/generated/models/EntityFacet.model.ts b/packages/catalog-client/src/generated/models/EntityFacet.model.ts new file mode 100644 index 0000000000..3872091d77 --- /dev/null +++ b/packages/catalog-client/src/generated/models/EntityFacet.model.ts @@ -0,0 +1,20 @@ +/* + * 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 interface EntityFacet { + value: string; + count: number; +} diff --git a/packages/catalog-client/src/generated/models/EntityFacetsResponse.model.ts b/packages/catalog-client/src/generated/models/EntityFacetsResponse.model.ts new file mode 100644 index 0000000000..0ff37e4f2f --- /dev/null +++ b/packages/catalog-client/src/generated/models/EntityFacetsResponse.model.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import { EntityFacet } from '../models/EntityFacet.model'; + +export interface EntityFacetsResponse { + facets: { [key: string]: Array }; +} diff --git a/packages/catalog-client/src/generated/models/EntityLink.model.ts b/packages/catalog-client/src/generated/models/EntityLink.model.ts new file mode 100644 index 0000000000..f52f9f2df0 --- /dev/null +++ b/packages/catalog-client/src/generated/models/EntityLink.model.ts @@ -0,0 +1,37 @@ +/* + * 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. + */ + +/** + * A link to external information that is related to the entity. + */ +export interface EntityLink { + /** + * An optional value to categorize links into specific groups + */ + type?: string; + /** + * An optional semantic key that represents a visual icon. + */ + icon?: string; + /** + * An optional descriptive title for the link. + */ + title?: string; + /** + * The url to the external site, document, etc. + */ + url: string; +} diff --git a/packages/catalog-client/src/generated/models/EntityMeta.model.ts b/packages/catalog-client/src/generated/models/EntityMeta.model.ts new file mode 100644 index 0000000000..cb0fd28fdc --- /dev/null +++ b/packages/catalog-client/src/generated/models/EntityMeta.model.ts @@ -0,0 +1,64 @@ +/* + * 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. + */ + +import { EntityLink } from '../models/EntityLink.model'; + +/** + * Metadata fields common to all versions/kinds of entity. + */ +export interface EntityMeta { + [key: string]: any; + /** + * A list of external hyperlinks related to the entity. + */ + links?: Array; + /** + * A list of single-valued strings, to for example classify catalog entities in various ways. + */ + tags?: Array; + /** + * Construct a type with a set of properties K of type T + */ + annotations?: { [key: string]: string }; + /** + * Construct a type with a set of properties K of type T + */ + labels?: { [key: string]: string }; + /** + * A short (typically relatively few words, on one line) description of the entity. + */ + description?: string; + /** + * A display name of the entity, to be presented in user interfaces instead of the `name` property above, when available. This field is sometimes useful when the `name` is cumbersome or ends up being perceived as overly technical. The title generally does not have as stringent format requirements on it, so it may contain special characters and be more explanatory. Do keep it very short though, and avoid situations where a title can be confused with the name of another entity, or where two entities share a title. Note that this is only for display purposes, and may be ignored by some parts of the code. Entity references still always make use of the `name` property, not the title. + */ + title?: string; + /** + * The namespace that the entity belongs to. + */ + namespace?: string; + /** + * The name of the entity. Must be unique within the catalog at any given point in time, for any given namespace + kind pair. This value is part of the technical identifier of the entity, and as such it will appear in URLs, database tables, entity references, and similar. It is subject to restrictions regarding what characters are allowed. If you want to use a different, more human readable string with fewer restrictions on it in user interfaces, see the `title` field below. + */ + name: string; + /** + * An opaque string that changes for each update operation to any part of the entity, including metadata. This field can not be set by the user at creation time, and the server will reject an attempt to do so. The field will be populated in read operations. The field can (optionally) be specified when performing update or delete operations, and the server will then reject the operation if it does not match the current stored value. + */ + etag?: string; + /** + * A globally unique ID for the entity. This field can not be set by the user at creation time, and the server will reject an attempt to do so. The field will be populated in read operations. The field can (optionally) be specified when performing update or delete operations, but the server is free to reject requests that do so in such a way that it breaks semantics. + */ + uid?: string; +} diff --git a/packages/catalog-client/src/generated/models/EntityRelation.model.ts b/packages/catalog-client/src/generated/models/EntityRelation.model.ts new file mode 100644 index 0000000000..1107f7563c --- /dev/null +++ b/packages/catalog-client/src/generated/models/EntityRelation.model.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +/** + * A relation of a specific type to another entity in the catalog. + */ +export interface EntityRelation { + /** + * The entity ref of the target of this relation. + */ + targetRef: string; + /** + * The type of the relation. + */ + type: string; +} diff --git a/packages/catalog-client/src/generated/models/ErrorError.model.ts b/packages/catalog-client/src/generated/models/ErrorError.model.ts new file mode 100644 index 0000000000..9dbfa22813 --- /dev/null +++ b/packages/catalog-client/src/generated/models/ErrorError.model.ts @@ -0,0 +1,22 @@ +/* + * 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 interface ErrorError { + name: string; + message: string; + stack?: string; + code?: string; +} diff --git a/packages/catalog-client/src/generated/models/ErrorRequest.model.ts b/packages/catalog-client/src/generated/models/ErrorRequest.model.ts new file mode 100644 index 0000000000..e6306b87f5 --- /dev/null +++ b/packages/catalog-client/src/generated/models/ErrorRequest.model.ts @@ -0,0 +1,20 @@ +/* + * 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 interface ErrorRequest { + method: string; + url: string; +} diff --git a/packages/catalog-client/src/generated/models/ErrorResponse.model.ts b/packages/catalog-client/src/generated/models/ErrorResponse.model.ts new file mode 100644 index 0000000000..1f55c34b4a --- /dev/null +++ b/packages/catalog-client/src/generated/models/ErrorResponse.model.ts @@ -0,0 +1,19 @@ +/* + * 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 interface ErrorResponse { + statusCode: number; +} diff --git a/packages/catalog-client/src/generated/models/GetEntitiesByRefsRequest.model.ts b/packages/catalog-client/src/generated/models/GetEntitiesByRefsRequest.model.ts new file mode 100644 index 0000000000..bdda7c2fa6 --- /dev/null +++ b/packages/catalog-client/src/generated/models/GetEntitiesByRefsRequest.model.ts @@ -0,0 +1,20 @@ +/* + * 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 interface GetEntitiesByRefsRequest { + entityRefs: Array; + fields?: Array; +} diff --git a/packages/catalog-client/src/generated/models/GetLocations200ResponseInner.model.ts b/packages/catalog-client/src/generated/models/GetLocations200ResponseInner.model.ts new file mode 100644 index 0000000000..134306cce7 --- /dev/null +++ b/packages/catalog-client/src/generated/models/GetLocations200ResponseInner.model.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import { Location } from '../models/Location.model'; + +export interface GetLocations200ResponseInner { + data: Location; +} diff --git a/packages/catalog-client/src/generated/models/Location.model.ts b/packages/catalog-client/src/generated/models/Location.model.ts new file mode 100644 index 0000000000..27e47a5a25 --- /dev/null +++ b/packages/catalog-client/src/generated/models/Location.model.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +/** + * Entity location for a specific entity. + */ +export interface Location { + target: string; + type: string; + id: string; +} diff --git a/packages/catalog-client/src/generated/models/LocationInput.model.ts b/packages/catalog-client/src/generated/models/LocationInput.model.ts new file mode 100644 index 0000000000..8de7e3e6c9 --- /dev/null +++ b/packages/catalog-client/src/generated/models/LocationInput.model.ts @@ -0,0 +1,20 @@ +/* + * 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 interface LocationInput { + type: string; + target: string; +} diff --git a/plugins/catalog-graphql/src/index.ts b/packages/catalog-client/src/generated/models/LocationSpec.model.ts similarity index 78% rename from plugins/catalog-graphql/src/index.ts rename to packages/catalog-client/src/generated/models/LocationSpec.model.ts index 51ae12e684..80db2cadf2 100644 --- a/plugins/catalog-graphql/src/index.ts +++ b/packages/catalog-client/src/generated/models/LocationSpec.model.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * 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. @@ -15,9 +15,9 @@ */ /** - * An experimental Backstage catalog GraphQL module - * - * @packageDocumentation + * Holds the entity location information. */ - -export * from './graphql/module'; +export interface LocationSpec { + target: string; + type: string; +} diff --git a/packages/catalog-client/src/generated/models/ModelError.model.ts b/packages/catalog-client/src/generated/models/ModelError.model.ts new file mode 100644 index 0000000000..989e755c9a --- /dev/null +++ b/packages/catalog-client/src/generated/models/ModelError.model.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +import { ErrorError } from '../models/ErrorError.model'; +import { ErrorRequest } from '../models/ErrorRequest.model'; +import { ErrorResponse } from '../models/ErrorResponse.model'; + +export interface ModelError { + [key: string]: any; + error: ErrorError; + request?: ErrorRequest; + response: ErrorResponse; +} diff --git a/packages/catalog-client/src/generated/models/NullableEntity.model.ts b/packages/catalog-client/src/generated/models/NullableEntity.model.ts new file mode 100644 index 0000000000..36aff86ba8 --- /dev/null +++ b/packages/catalog-client/src/generated/models/NullableEntity.model.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ + +import { EntityMeta } from '../models/EntityMeta.model'; +import { EntityRelation } from '../models/EntityRelation.model'; + +/** + * The parts of the format that's common to all versions/kinds of entity. + */ +export interface NullableEntity { + /** + * The relations that this entity has with other entities. + */ + relations?: Array; + /** + * A type representing all allowed JSON object values. + */ + spec?: { [key: string]: any }; + metadata: EntityMeta; + /** + * The high level entity type being described. + */ + kind: string; + /** + * The version of specification format for this particular entity that this is written against. + */ + apiVersion: string; +} diff --git a/packages/catalog-client/src/generated/models/RecursivePartialEntity.model.ts b/packages/catalog-client/src/generated/models/RecursivePartialEntity.model.ts new file mode 100644 index 0000000000..8de7824550 --- /dev/null +++ b/packages/catalog-client/src/generated/models/RecursivePartialEntity.model.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ + +import { RecursivePartialEntityMeta } from '../models/RecursivePartialEntityMeta.model'; +import { RecursivePartialEntityRelation } from '../models/RecursivePartialEntityRelation.model'; + +/** + * Makes all keys of an entire hierarchy optional. + */ +export interface RecursivePartialEntity { + /** + * The version of specification format for this particular entity that this is written against. + */ + apiVersion?: string; + /** + * The high level entity type being described. + */ + kind?: string; + metadata?: RecursivePartialEntityMeta; + /** + * A type representing all allowed JSON object values. + */ + spec?: { [key: string]: any }; + /** + * The relations that this entity has with other entities. + */ + relations?: Array; +} diff --git a/packages/catalog-client/src/generated/models/RecursivePartialEntityMeta.model.ts b/packages/catalog-client/src/generated/models/RecursivePartialEntityMeta.model.ts new file mode 100644 index 0000000000..b21cc1bb21 --- /dev/null +++ b/packages/catalog-client/src/generated/models/RecursivePartialEntityMeta.model.ts @@ -0,0 +1,60 @@ +/* + * 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. + */ + +import { EntityLink } from '../models/EntityLink.model'; + +export interface RecursivePartialEntityMeta { + /** + * A list of external hyperlinks related to the entity. + */ + links?: Array; + /** + * A list of single-valued strings, to for example classify catalog entities in various ways. + */ + tags?: Array; + /** + * Construct a type with a set of properties K of type T + */ + annotations?: { [key: string]: string }; + /** + * Construct a type with a set of properties K of type T + */ + labels?: { [key: string]: string }; + /** + * A short (typically relatively few words, on one line) description of the entity. + */ + description?: string; + /** + * A display name of the entity, to be presented in user interfaces instead of the `name` property above, when available. This field is sometimes useful when the `name` is cumbersome or ends up being perceived as overly technical. The title generally does not have as stringent format requirements on it, so it may contain special characters and be more explanatory. Do keep it very short though, and avoid situations where a title can be confused with the name of another entity, or where two entities share a title. Note that this is only for display purposes, and may be ignored by some parts of the code. Entity references still always make use of the `name` property, not the title. + */ + title?: string; + /** + * The namespace that the entity belongs to. + */ + namespace?: string; + /** + * The name of the entity. Must be unique within the catalog at any given point in time, for any given namespace + kind pair. This value is part of the technical identifier of the entity, and as such it will appear in URLs, database tables, entity references, and similar. It is subject to restrictions regarding what characters are allowed. If you want to use a different, more human readable string with fewer restrictions on it in user interfaces, see the `title` field below. + */ + name?: string; + /** + * An opaque string that changes for each update operation to any part of the entity, including metadata. This field can not be set by the user at creation time, and the server will reject an attempt to do so. The field will be populated in read operations. The field can (optionally) be specified when performing update or delete operations, and the server will then reject the operation if it does not match the current stored value. + */ + etag?: string; + /** + * A globally unique ID for the entity. This field can not be set by the user at creation time, and the server will reject an attempt to do so. The field will be populated in read operations. The field can (optionally) be specified when performing update or delete operations, but the server is free to reject requests that do so in such a way that it breaks semantics. + */ + uid?: string; +} diff --git a/packages/catalog-client/src/generated/models/RecursivePartialEntityMetaAllOf.model.ts b/packages/catalog-client/src/generated/models/RecursivePartialEntityMetaAllOf.model.ts new file mode 100644 index 0000000000..5111cd7f9f --- /dev/null +++ b/packages/catalog-client/src/generated/models/RecursivePartialEntityMetaAllOf.model.ts @@ -0,0 +1,63 @@ +/* + * 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. + */ + +import { EntityLink } from '../models/EntityLink.model'; + +/** + * Metadata fields common to all versions/kinds of entity. + */ +export interface RecursivePartialEntityMetaAllOf { + /** + * A list of external hyperlinks related to the entity. + */ + links?: Array; + /** + * A list of single-valued strings, to for example classify catalog entities in various ways. + */ + tags?: Array; + /** + * Construct a type with a set of properties K of type T + */ + annotations?: { [key: string]: string }; + /** + * Construct a type with a set of properties K of type T + */ + labels?: { [key: string]: string }; + /** + * A short (typically relatively few words, on one line) description of the entity. + */ + description?: string; + /** + * A display name of the entity, to be presented in user interfaces instead of the `name` property above, when available. This field is sometimes useful when the `name` is cumbersome or ends up being perceived as overly technical. The title generally does not have as stringent format requirements on it, so it may contain special characters and be more explanatory. Do keep it very short though, and avoid situations where a title can be confused with the name of another entity, or where two entities share a title. Note that this is only for display purposes, and may be ignored by some parts of the code. Entity references still always make use of the `name` property, not the title. + */ + title?: string; + /** + * The namespace that the entity belongs to. + */ + namespace?: string; + /** + * The name of the entity. Must be unique within the catalog at any given point in time, for any given namespace + kind pair. This value is part of the technical identifier of the entity, and as such it will appear in URLs, database tables, entity references, and similar. It is subject to restrictions regarding what characters are allowed. If you want to use a different, more human readable string with fewer restrictions on it in user interfaces, see the `title` field below. + */ + name?: string; + /** + * An opaque string that changes for each update operation to any part of the entity, including metadata. This field can not be set by the user at creation time, and the server will reject an attempt to do so. The field will be populated in read operations. The field can (optionally) be specified when performing update or delete operations, and the server will then reject the operation if it does not match the current stored value. + */ + etag?: string; + /** + * A globally unique ID for the entity. This field can not be set by the user at creation time, and the server will reject an attempt to do so. The field will be populated in read operations. The field can (optionally) be specified when performing update or delete operations, but the server is free to reject requests that do so in such a way that it breaks semantics. + */ + uid?: string; +} diff --git a/packages/catalog-client/src/generated/models/RecursivePartialEntityRelation.model.ts b/packages/catalog-client/src/generated/models/RecursivePartialEntityRelation.model.ts new file mode 100644 index 0000000000..50635b69f4 --- /dev/null +++ b/packages/catalog-client/src/generated/models/RecursivePartialEntityRelation.model.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +/** + * A relation of a specific type to another entity in the catalog. + */ +export interface RecursivePartialEntityRelation { + /** + * The entity ref of the target of this relation. + */ + targetRef?: string; + /** + * The type of the relation. + */ + type?: string; +} diff --git a/packages/catalog-client/src/generated/models/RefreshEntityRequest.model.ts b/packages/catalog-client/src/generated/models/RefreshEntityRequest.model.ts new file mode 100644 index 0000000000..573523385b --- /dev/null +++ b/packages/catalog-client/src/generated/models/RefreshEntityRequest.model.ts @@ -0,0 +1,26 @@ +/* + * 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. + */ + +/** + * Options for requesting a refresh of entities in the catalog. + */ +export interface RefreshEntityRequest { + authorizationToken?: string; + /** + * The reference to a single entity that should be refreshed + */ + entityRef: string; +} diff --git a/packages/catalog-client/src/generated/models/ValidateEntity400Response.model.ts b/packages/catalog-client/src/generated/models/ValidateEntity400Response.model.ts new file mode 100644 index 0000000000..0031b2edc2 --- /dev/null +++ b/packages/catalog-client/src/generated/models/ValidateEntity400Response.model.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +import { ValidateEntity400ResponseErrorsInner } from '../models/ValidateEntity400ResponseErrorsInner.model'; + +export interface ValidateEntity400Response { + errors: Array; +} diff --git a/packages/catalog-client/src/generated/models/ValidateEntity400ResponseErrorsInner.model.ts b/packages/catalog-client/src/generated/models/ValidateEntity400ResponseErrorsInner.model.ts new file mode 100644 index 0000000000..6223df27af --- /dev/null +++ b/packages/catalog-client/src/generated/models/ValidateEntity400ResponseErrorsInner.model.ts @@ -0,0 +1,21 @@ +/* + * 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 interface ValidateEntity400ResponseErrorsInner { + [key: string]: any; + name: string; + message: string; +} diff --git a/packages/catalog-client/src/generated/models/ValidateEntityRequest.model.ts b/packages/catalog-client/src/generated/models/ValidateEntityRequest.model.ts new file mode 100644 index 0000000000..d5ce1be5c9 --- /dev/null +++ b/packages/catalog-client/src/generated/models/ValidateEntityRequest.model.ts @@ -0,0 +1,20 @@ +/* + * 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 interface ValidateEntityRequest { + location: string; + entity: { [key: string]: any }; +} diff --git a/packages/catalog-client/src/generated/models/index.ts b/packages/catalog-client/src/generated/models/index.ts new file mode 100644 index 0000000000..5a93dbb33a --- /dev/null +++ b/packages/catalog-client/src/generated/models/index.ts @@ -0,0 +1,52 @@ +/* + * 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 * from '../models/AnalyzeLocationEntityField.model'; +export * from '../models/AnalyzeLocationExistingEntity.model'; +export * from '../models/AnalyzeLocationGenerateEntity.model'; +export * from '../models/AnalyzeLocationRequest.model'; +export * from '../models/AnalyzeLocationResponse.model'; +export * from '../models/CreateLocation201Response.model'; +export * from '../models/CreateLocationRequest.model'; +export * from '../models/EntitiesBatchResponse.model'; +export * from '../models/EntitiesQueryResponse.model'; +export * from '../models/EntitiesQueryResponsePageInfo.model'; +export * from '../models/Entity.model'; +export * from '../models/EntityAncestryResponse.model'; +export * from '../models/EntityAncestryResponseItemsInner.model'; +export * from '../models/EntityFacet.model'; +export * from '../models/EntityFacetsResponse.model'; +export * from '../models/EntityLink.model'; +export * from '../models/EntityMeta.model'; +export * from '../models/EntityRelation.model'; +export * from '../models/ErrorError.model'; +export * from '../models/ErrorRequest.model'; +export * from '../models/ErrorResponse.model'; +export * from '../models/GetEntitiesByRefsRequest.model'; +export * from '../models/GetLocations200ResponseInner.model'; +export * from '../models/Location.model'; +export * from '../models/LocationInput.model'; +export * from '../models/LocationSpec.model'; +export * from '../models/ModelError.model'; +export * from '../models/NullableEntity.model'; +export * from '../models/RecursivePartialEntity.model'; +export * from '../models/RecursivePartialEntityMeta.model'; +export * from '../models/RecursivePartialEntityMetaAllOf.model'; +export * from '../models/RecursivePartialEntityRelation.model'; +export * from '../models/RefreshEntityRequest.model'; +export * from '../models/ValidateEntity400Response.model'; +export * from '../models/ValidateEntity400ResponseErrorsInner.model'; +export * from '../models/ValidateEntityRequest.model'; diff --git a/packages/catalog-client/src/generated/pluginId.ts b/packages/catalog-client/src/generated/pluginId.ts new file mode 100644 index 0000000000..c8c8ce1ca3 --- /dev/null +++ b/packages/catalog-client/src/generated/pluginId.ts @@ -0,0 +1,17 @@ +/* + * 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 const pluginId = 'catalog'; diff --git a/packages/catalog-client/src/generated/types/discovery.ts b/packages/catalog-client/src/generated/types/discovery.ts new file mode 100644 index 0000000000..a7f87d3780 --- /dev/null +++ b/packages/catalog-client/src/generated/types/discovery.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +/** + * This is a copy of the DiscoveryApi, to avoid importing core-plugin-api. + */ +export type DiscoveryApi = { + getBaseUrl(pluginId: string): Promise; +}; diff --git a/packages/catalog-client/src/generated/types/fetch.ts b/packages/catalog-client/src/generated/types/fetch.ts new file mode 100644 index 0000000000..3de56c028e --- /dev/null +++ b/packages/catalog-client/src/generated/types/fetch.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +/** + * This is a copy of FetchApi, to avoid importing core-plugin-api. + */ +export type FetchApi = { + fetch: typeof fetch; +}; diff --git a/packages/catalog-model/alpha-api-report.md b/packages/catalog-model/api-report-alpha.md similarity index 100% rename from packages/catalog-model/alpha-api-report.md rename to packages/catalog-model/api-report-alpha.md diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 30d971fb30..5b554ad74f 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,69 @@ # @backstage/cli +## 0.25.0-next.2 + +### Patch Changes + +- 32018ff: Enable the `tsx` loader to work on Node 18.19 and up +- a3edc18: Updated dependency `vite-plugin-node-polyfills` to `^0.17.0`. +- 627554e: Updated dependency `@rollup/plugin-node-resolve` to `^15.0.0`. +- c07cee5: Updated dependency `@rollup/plugin-json` to `^6.0.0`. +- 2565cc8: Updated dependency `@rollup/plugin-commonjs` to `^25.0.0`. +- Updated dependencies + - @backstage/config-loader@1.6.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/eslint-plugin@0.1.4-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/release-manifests@0.0.11 + - @backstage/types@1.1.1 + +## 0.25.0-next.1 + +### Minor Changes + +- 38340678c3: Updates the ESLint config to ignore issues created by generated files in `**/src/generated/**`. + +### Patch Changes + +- 0ffee55010: Toned down the warning message when git is not found +- c6f3743172: Added a warning when starting a standalone backend plugin that hasn't been updated to the new backend system. +- 3e358b0dff: Added deprecation warning for React Router v6 beta, please make sure you have migrated your apps to use React Router v6 stable as support for the beta version will be removed. See the [migration tutorial](https://backstage.io/docs/tutorials/react-router-stable-migration) for more information. +- 8056425e09: Updated dependency `@typescript-eslint/eslint-plugin` to `6.12.0`. +- 33e96e59e7: Switched the `@typescript-eslint/eslint-plugin` dependency back to using a `^` version range. +- Updated dependencies + - @backstage/eslint-plugin@0.1.4-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/release-manifests@0.0.11 + - @backstage/types@1.1.1 + +## 0.24.1-next.0 + +### Patch Changes + +- 8cda3c72f2: Tweaked Node.js version check for when to use the new module register API with the new backend `package start` command. +- 017c425f93: Updated dependency `@typescript-eslint/eslint-plugin` to `6.11.0`. +- Updated dependencies + - @backstage/integration@1.8.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/eslint-plugin@0.1.3 + - @backstage/release-manifests@0.0.11 + - @backstage/types@1.1.1 + ## 0.24.0 ### Minor Changes diff --git a/packages/cli/config/eslint-factory.js b/packages/cli/config/eslint-factory.js index 58a9362051..3717943427 100644 --- a/packages/cli/config/eslint-factory.js +++ b/packages/cli/config/eslint-factory.js @@ -66,7 +66,7 @@ function createConfig(dir, extraConfig = {}) { ...(extraExtends ?? []), ], parser: '@typescript-eslint/parser', - plugins: ['import', ...(plugins ?? [])], + plugins: ['import', 'unused-imports', ...(plugins ?? [])], env: { jest: true, ...env, @@ -165,6 +165,23 @@ function createConfig(dir, extraConfig = {}) { ], }, }, + { + files: ['**/src/generated/**/*.ts'], + rules: { + ...tsRules, + 'no-unused-vars': 'off', + 'unused-imports/no-unused-imports': 'error', + 'unused-imports/no-unused-vars': [ + 'warn', + { + vars: 'all', + varsIgnorePattern: '^_', + args: 'none', + argsIgnorePattern: '^_', + }, + ], + }, + }, ...(overrides ?? []), ], }; diff --git a/packages/cli/package.json b/packages/cli/package.json index d08b0b033f..997ec0d067 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli", "description": "CLI for developing Backstage plugins and apps", - "version": "0.24.0", + "version": "0.25.0-next.2", "publishConfig": { "access": "public" }, @@ -46,9 +46,9 @@ "@octokit/oauth-app": "^4.2.0", "@octokit/request": "^6.0.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", - "@rollup/plugin-commonjs": "^23.0.0", - "@rollup/plugin-json": "^5.0.0", - "@rollup/plugin-node-resolve": "^13.0.6", + "@rollup/plugin-commonjs": "^25.0.0", + "@rollup/plugin-json": "^6.0.0", + "@rollup/plugin-node-resolve": "^15.0.0", "@rollup/plugin-yaml": "^4.0.0", "@spotify/eslint-config-base": "^14.0.0", "@spotify/eslint-config-react": "^14.0.0", @@ -64,11 +64,11 @@ "@swc/jest": "^0.2.22", "@types/jest": "^29.0.0", "@types/webpack-env": "^1.15.2", - "@typescript-eslint/eslint-plugin": "6.10.0", + "@typescript-eslint/eslint-plugin": "^6.12.0", "@typescript-eslint/parser": "^6.7.2", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "^3.0.0-rc.4", - "bfj": "^7.0.2", + "bfj": "^8.0.0", "buffer": "^6.0.3", "chalk": "^4.0.0", "chokidar": "^3.3.1", @@ -89,6 +89,7 @@ "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-react": "^7.28.0", "eslint-plugin-react-hooks": "^4.3.0", + "eslint-plugin-unused-imports": "^3.0.0", "eslint-webpack-plugin": "^3.1.1", "express": "^4.17.1", "fork-ts-checker-webpack-plugin": "^7.0.0-alpha.8", @@ -129,7 +130,7 @@ "swc-loader": "^0.2.3", "tar": "^6.1.12", "terser-webpack-plugin": "^5.1.3", - "tsx": "^3.14.0", + "tsx": "^4.0.0", "util": "^0.12.3", "webpack": "^5.70.0", "webpack-dev-server": "^4.7.3", @@ -176,7 +177,7 @@ "@vitejs/plugin-react": "^4.0.4", "vite": "^4.4.9", "vite-plugin-html": "^3.2.0", - "vite-plugin-node-polyfills": "^0.16.0" + "vite-plugin-node-polyfills": "^0.17.0" }, "peerDependenciesMeta": { "@vitejs/plugin-react": { diff --git a/packages/cli/src/commands/start/command.ts b/packages/cli/src/commands/start/command.ts index 48122d5ac0..427f8b6efb 100644 --- a/packages/cli/src/commands/start/command.ts +++ b/packages/cli/src/commands/start/command.ts @@ -16,7 +16,7 @@ import { OptionValues } from 'commander'; import { findRoleFromCommand } from '../../lib/role'; -import { startBackend } from './startBackend'; +import { startBackend, startBackendPlugin } from './startBackend'; import { startFrontend } from './startFrontend'; export async function command(opts: OptionValues): Promise { @@ -31,10 +31,11 @@ export async function command(opts: OptionValues): Promise { switch (role) { case 'backend': + return startBackend(options); case 'backend-plugin': case 'backend-plugin-module': case 'node-library': - return startBackend(options); + return startBackendPlugin(options); case 'frontend': return startFrontend({ ...options, diff --git a/packages/cli/src/commands/start/startBackend.ts b/packages/cli/src/commands/start/startBackend.ts index 967a1108a0..25758a0939 100644 --- a/packages/cli/src/commands/start/startBackend.ts +++ b/packages/cli/src/commands/start/startBackend.ts @@ -26,17 +26,7 @@ interface StartBackendOptions { } export async function startBackend(options: StartBackendOptions) { - const hasDev = await fs.pathExists(paths.resolveTarget('dev')); - if (hasDev) { - const waitForExit = await startBackendExperimental({ - entry: 'dev/index', - checksEnabled: false, // not supported - inspectEnabled: options.inspectEnabled, - inspectBrkEnabled: options.inspectBrkEnabled, - }); - - await waitForExit(); - } else if (!process.env.LEGACY_BACKEND_START) { + if (!process.env.LEGACY_BACKEND_START) { const waitForExit = await startBackendExperimental({ entry: 'src/index', checksEnabled: false, // not supported @@ -46,12 +36,7 @@ export async function startBackend(options: StartBackendOptions) { await waitForExit(); } else { - // Cleaning dist/ before we start the dev process helps work around an issue - // where we end up with the entrypoint executing multiple times, causing - // a port bind conflict among other things. - await fs.remove(paths.resolveTarget('dist')); - - const waitForExit = await serveBackend({ + const waitForExit = await cleanDistAndServeBackend({ entry: 'src/index', checksEnabled: options.checksEnabled, inspectEnabled: options.inspectEnabled, @@ -61,3 +46,63 @@ export async function startBackend(options: StartBackendOptions) { await waitForExit(); } } + +export async function startBackendPlugin(options: StartBackendOptions) { + if (!process.env.LEGACY_BACKEND_START) { + const hasDevIndexEntry = await fs.pathExists( + paths.resolveTarget('dev', 'index.ts'), + ); + const hasSrcIndexEntry = await fs.pathExists( + paths.resolveTarget('src', 'run.ts'), + ); + + if (!hasDevIndexEntry && !hasSrcIndexEntry) { + console.warn( + hasSrcIndexEntry + ? `The 'dev' directory is missing. The plugin might not be updated for the new backend system. To run, use "LEGACY_BACKEND_START=1 yarn start".` + : `The 'dev' directory is missing. Please create a proper dev/index.ts in order to start the plugin.`, + ); + return; + } + + const waitForExit = await startBackendExperimental({ + entry: 'dev/index', + checksEnabled: false, // not supported + inspectEnabled: options.inspectEnabled, + inspectBrkEnabled: options.inspectBrkEnabled, + }); + + await waitForExit(); + } else { + const hasEntry = await fs.pathExists(paths.resolveTarget('src', 'run.ts')); + if (!hasEntry) { + console.warn( + `src/run.ts is missing. Please create the file or run the command without LEGACY_BACKEND_START`, + ); + return; + } + + const waitForExit = await cleanDistAndServeBackend({ + entry: 'src/run', + checksEnabled: options.checksEnabled, + inspectEnabled: options.inspectEnabled, + inspectBrkEnabled: options.inspectBrkEnabled, + }); + + await waitForExit(); + } +} + +async function cleanDistAndServeBackend(options: { + entry: string; + checksEnabled: boolean; + inspectEnabled: boolean; + inspectBrkEnabled: boolean; +}) { + // Cleaning dist/ before we start the dev process helps work around an issue + // where we end up with the entrypoint executing multiple times, causing + // a port bind conflict among other things. + await fs.remove(paths.resolveTarget('dist')); + + return serveBackend(options); +} diff --git a/packages/cli/src/lib/bundler/config.ts b/packages/cli/src/lib/bundler/config.ts index 542cc83ce9..a9d5c2aa67 100644 --- a/packages/cli/src/lib/bundler/config.ts +++ b/packages/cli/src/lib/bundler/config.ts @@ -55,18 +55,24 @@ export function resolveBaseUrl(config: Config): URL { async function readBuildInfo() { const timestamp = Date.now(); - let commit = 'unknown'; + let commit: string | undefined; try { commit = await runPlain('git', 'rev-parse', 'HEAD'); } catch (error) { - console.warn(`WARNING: Failed to read git commit, ${error}`); + // ignore, see below } - let gitVersion = 'unknown'; + let gitVersion: string | undefined; try { gitVersion = await runPlain('git', 'describe', '--always'); } catch (error) { - console.warn(`WARNING: Failed to describe git version, ${error}`); + // ignore, see below + } + + if (commit === undefined || gitVersion === undefined) { + console.info( + 'NOTE: Did not compute git version or commit hash, could not execute the git command line utility', + ); } const { version: packageVersion } = await fs.readJson( @@ -75,10 +81,10 @@ async function readBuildInfo() { return { cliVersion: version, - gitVersion, + gitVersion: gitVersion ?? 'unknown', packageVersion, timestamp, - commit, + commit: commit ?? 'unknown', }; } diff --git a/packages/cli/src/lib/bundler/server.ts b/packages/cli/src/lib/bundler/server.ts index bd70b2b074..2fd1385584 100644 --- a/packages/cli/src/lib/bundler/server.ts +++ b/packages/cli/src/lib/bundler/server.ts @@ -72,6 +72,20 @@ export async function serveBundle(options: ServeOptions) { ), ); } + + if ( + targetPkg.dependencies?.['react-router']?.includes('beta') || + targetPkg.dependencies?.['react-router-dom']?.includes('beta') + ) { + // eslint-disable-next-line no-console + console.warn( + chalk.yellow(` +DEPRECATION WARNING: React Router Beta is deprecated and support for it will be removed in a future release. + Please migrate to use React Router v6 stable. + See https://backstage.io/docs/tutorials/react-router-stable-migration +`), + ); + } } checkReactVersion(); diff --git a/packages/cli/src/lib/experimental/startBackendExperimental.ts b/packages/cli/src/lib/experimental/startBackendExperimental.ts index af6e33a1e4..0ca3b182b5 100644 --- a/packages/cli/src/lib/experimental/startBackendExperimental.ts +++ b/packages/cli/src/lib/experimental/startBackendExperimental.ts @@ -28,7 +28,10 @@ import { paths } from '../paths'; import spawn from 'cross-spawn'; const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(Number); -const supportsModuleLoaderRegister = nodeMajor >= 20 && nodeMinor >= 6; +const supportsModuleLoaderRegister = + nodeMajor > 20 || + (nodeMajor === 20 && nodeMinor >= 6) || + (nodeMajor === 18 && nodeMinor >= 19); const loaderArgs = [ '--require', diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index 169e2e45df..d5526dd62e 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/config-loader +## 1.6.0-next.0 + +### Minor Changes + +- 24f5a85: Add "path" to `TransformFunc` context + +### Patch Changes + +- Updated dependencies + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 1.5.3 ### Patch Changes diff --git a/packages/config-loader/api-report.md b/packages/config-loader/api-report.md index 9f55a27bf7..66572dd960 100644 --- a/packages/config-loader/api-report.md +++ b/packages/config-loader/api-report.md @@ -274,6 +274,7 @@ export type TransformFunc = ( value: T, context: { visibility: ConfigVisibility; + path: string; }, ) => T | undefined; ``` diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 8a41d7548f..e908afa6a1 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config-loader", "description": "Config loading functionality used by Backstage backend, and CLI", - "version": "1.5.3", + "version": "1.6.0-next.0", "publishConfig": { "access": "public", "main": "dist/index.cjs.js", diff --git a/packages/config-loader/src/schema/filtering.ts b/packages/config-loader/src/schema/filtering.ts index 1b7bbf43c1..9c1c2fbda5 100644 --- a/packages/config-loader/src/schema/filtering.ts +++ b/packages/config-loader/src/schema/filtering.ts @@ -68,7 +68,7 @@ export function filterByVisibility( if (typeof jsonVal !== 'object') { if (isVisible) { if (transformFunc) { - return transformFunc(jsonVal, { visibility }); + return transformFunc(jsonVal, { visibility, path: filterPath }); } return jsonVal; } diff --git a/packages/config-loader/src/schema/types.ts b/packages/config-loader/src/schema/types.ts index dc8da64038..8f679c93fc 100644 --- a/packages/config-loader/src/schema/types.ts +++ b/packages/config-loader/src/schema/types.ts @@ -105,11 +105,22 @@ export type ValidationFunc = (configs: AppConfig[]) => ValidationResult; /** * A function used to transform primitive configuration values. * + * The "path" in the context is a JQ-style path to the current value from + * within the original object passed to filterByVisibility(). + * For example, "field.list[2]" would refer to: + * \{ + * field: [ + * "foo", + * "bar", + * "baz" -- this one + * ] + * \} + * * @public */ export type TransformFunc = ( value: T, - context: { visibility: ConfigVisibility }, + context: { visibility: ConfigVisibility; path: string }, ) => T | undefined; /** diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index 2a96790527..2a0e26c1e7 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/core-app-api +## 1.11.2-next.1 + +### Patch Changes + +- 3e358b0dff: Added deprecation warning for React Router v6 beta, please make sure you have migrated your apps to use React Router v6 stable as support for the beta version will be removed. See the [migration tutorial](https://backstage.io/docs/tutorials/react-router-stable-migration) for more information. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## 1.11.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + ## 1.11.1 ### Patch Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 1465b6d2dd..b18f31eb4f 100644 --- a/packages/core-app-api/package.json +++ b/packages/core-app-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-app-api", "description": "Core app API used by Backstage apps", - "version": "1.11.1", + "version": "1.11.2-next.1", "publishConfig": { "access": "public" }, diff --git a/packages/core-app-api/src/app/AppManager.tsx b/packages/core-app-api/src/app/AppManager.tsx index 37407283b5..c8cdfd7c23 100644 --- a/packages/core-app-api/src/app/AppManager.tsx +++ b/packages/core-app-api/src/app/AppManager.tsx @@ -240,11 +240,21 @@ export class AppManager implements BackstageApp { ); const { routing, featureFlags, routeBindings } = useMemo(() => { + const usesReactRouterBeta = isReactRouterBeta(); + if (usesReactRouterBeta) { + // eslint-disable-next-line no-console + console.warn(` +DEPRECATION WARNING: React Router Beta is deprecated and support for it will be removed in a future release. + Please migrate to use React Router v6 stable. + See https://backstage.io/docs/tutorials/react-router-stable-migration +`); + } + const result = traverseElementTree({ root: children, discoverers: [childDiscoverer, routeElementDiscoverer], collectors: { - routing: isReactRouterBeta() + routing: usesReactRouterBeta ? routingV1Collector : routingV2Collector, collectedPlugins: pluginCollector, diff --git a/packages/core-compat-api/CHANGELOG.md b/packages/core-compat-api/CHANGELOG.md index 244e7c4f23..cd069b966f 100644 --- a/packages/core-compat-api/CHANGELOG.md +++ b/packages/core-compat-api/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/core-compat-api +## 0.1.0-next.2 + +### Minor Changes + +- cf5cc4c: Discover plugins and routes recursively beneath the root routes in `collectLecacyRoutes` + +### Patch Changes + +- 8226442: Added `compatWrapper`, which can be used to wrap any React element to provide bi-directional interoperability between the `@backstage/core-*-api` and `@backstage/frontend-*-api` APIs. +- 8f5d6c1: Updates to match the new extension input wrapping. +- b7adf24: Delete alpha DI compatibility helper for components, migrating components should be simple without a helper. +- 046e443: Updates for compatibility with the new extension IDs. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/version-bridge@1.0.7 + +## 0.0.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/core-app-api@1.11.2-next.1 + +## 0.0.1-next.0 + +### Patch Changes + +- c219b168aa: Made package public so it can be published + +## 0.0.2-next.0 + +### Patch Changes + +- 03d0b6dcdc: Added `convertLegacyRouteRef` utility to convert existing route refs to be used with the new experimental packages. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/core-app-api@1.11.2-next.0 + ## 0.0.1 ### Patch Changes diff --git a/packages/core-compat-api/api-report.md b/packages/core-compat-api/api-report.md index 877aefa24f..58d5a2f094 100644 --- a/packages/core-compat-api/api-report.md +++ b/packages/core-compat-api/api-report.md @@ -11,6 +11,7 @@ import { ExtensionOverrides } from '@backstage/frontend-plugin-api'; import { ExternalRouteRef } from '@backstage/core-plugin-api'; import { ExternalRouteRef as ExternalRouteRef_2 } from '@backstage/frontend-plugin-api'; import { default as React_2 } from 'react'; +import { ReactNode } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { RouteRef as RouteRef_2 } from '@backstage/frontend-plugin-api'; import { SubRouteRef } from '@backstage/core-plugin-api'; @@ -21,6 +22,9 @@ export function collectLegacyRoutes( flatRoutesElement: JSX.Element, ): BackstagePlugin[]; +// @public +export function compatWrapper(element: ReactNode): React_2.JSX.Element; + // @public (undocumented) export function convertLegacyApp( rootElement: React_2.JSX.Element, diff --git a/packages/core-compat-api/package.json b/packages/core-compat-api/package.json index 7ead3d858f..b2ee3869d3 100644 --- a/packages/core-compat-api/package.json +++ b/packages/core-compat-api/package.json @@ -1,10 +1,9 @@ { "name": "@backstage/core-compat-api", - "version": "0.0.1", + "version": "0.1.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", - "private": true, "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -23,23 +22,28 @@ "prepack": "backstage-cli package prepack", "postpack": "backstage-cli package postpack" }, - "devDependencies": { - "@backstage/cli": "workspace:^", - "@backstage/plugin-puppetdb": "workspace:^", - "@backstage/plugin-stackstorm": "workspace:^", - "@oriflame/backstage-plugin-score-card": "^0.7.0", - "@testing-library/jest-dom": "^6.0.0" + "dependencies": { + "@backstage/core-app-api": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", + "@backstage/version-bridge": "workspace:^", + "@types/react": "^16.13.1 || ^17.0.0" }, - "files": [ - "dist" - ], "peerDependencies": { "react": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, - "dependencies": { - "@backstage/core-app-api": "workspace:^", - "@backstage/core-plugin-api": "workspace:^", - "@backstage/frontend-plugin-api": "workspace:^" - } + "devDependencies": { + "@backstage/cli": "workspace:^", + "@backstage/frontend-test-utils": "workspace:^", + "@backstage/plugin-catalog": "workspace:^", + "@backstage/plugin-puppetdb": "workspace:^", + "@backstage/plugin-stackstorm": "workspace:^", + "@oriflame/backstage-plugin-score-card": "^0.7.0", + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0" + }, + "files": [ + "dist" + ] } diff --git a/packages/core-compat-api/src/collectLegacyRoutes.test.tsx b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx index 85fed83e8c..862ef68bb5 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.test.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx @@ -15,13 +15,23 @@ */ import { FlatRoutes } from '@backstage/core-app-api'; +import { + CatalogEntityPage, + CatalogIndexPage, + EntityAboutCard, + EntityLayout, + EntitySwitch, + isKind, +} from '@backstage/plugin-catalog'; import { PuppetDbPage } from '@backstage/plugin-puppetdb'; import { StackstormPage } from '@backstage/plugin-stackstorm'; import { ScoreBoardPage } from '@oriflame/backstage-plugin-score-card'; -import React from 'react'; -import { Route } from 'react-router-dom'; +import React, { Fragment } from 'react'; +import { Route, Routes } from 'react-router-dom'; import { collectLegacyRoutes } from './collectLegacyRoutes'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalBackstagePlugin } from '../../frontend-plugin-api/src/wiring/createPlugin'; describe('collectLegacyRoutes', () => { it('should collect legacy routes', () => { @@ -37,7 +47,7 @@ describe('collectLegacyRoutes', () => { expect( collected.map(p => ({ id: p.id, - extensions: p.extensions.map(e => ({ + extensions: toInternalBackstagePlugin(p).extensions.map(e => ({ id: e.id, attachTo: e.attachTo, disabled: e.disabled, @@ -49,13 +59,13 @@ describe('collectLegacyRoutes', () => { id: 'score-card', extensions: [ { - id: 'plugin.score-card.page', - attachTo: { id: 'core.routes', input: 'routes' }, + id: 'page:score-card', + attachTo: { id: 'core/routes', input: 'routes' }, disabled: false, defaultConfig: { path: 'score-board' }, }, { - id: 'apis.plugin.scoringdata.service', + id: 'api:plugin.scoringdata.service', attachTo: { id: 'core', input: 'apis' }, disabled: false, }, @@ -65,13 +75,13 @@ describe('collectLegacyRoutes', () => { id: 'stackstorm', extensions: [ { - id: 'plugin.stackstorm.page', - attachTo: { id: 'core.routes', input: 'routes' }, + id: 'page:stackstorm', + attachTo: { id: 'core/routes', input: 'routes' }, disabled: false, defaultConfig: { path: 'stackstorm' }, }, { - id: 'apis.plugin.stackstorm.service', + id: 'api:plugin.stackstorm.service', attachTo: { id: 'core', input: 'apis' }, disabled: false, }, @@ -81,19 +91,149 @@ describe('collectLegacyRoutes', () => { id: 'puppetDb', extensions: [ { - id: 'plugin.puppetDb.page', - attachTo: { id: 'core.routes', input: 'routes' }, + id: 'page:puppetDb', + attachTo: { id: 'core/routes', input: 'routes' }, disabled: false, defaultConfig: { path: 'puppetdb' }, }, { - id: 'plugin.puppetDb.page2', - attachTo: { id: 'core.routes', input: 'routes' }, + id: 'page:puppetDb/1', + attachTo: { id: 'core/routes', input: 'routes' }, disabled: false, defaultConfig: { path: 'puppetdb' }, }, { - id: 'apis.plugin.puppetdb.service', + id: 'api:plugin.puppetdb.service', + attachTo: { id: 'core', input: 'apis' }, + disabled: false, + }, + ], + }, + ]); + }); + + it('supports recursion into children, including passing through fragments', () => { + const collected = collectLegacyRoutes( + + } /> + } + > + + + + + } + /> + + + + + + + + + + + + + + + + , + ); + + expect( + collected.map(p => ({ + id: p.id, + extensions: toInternalBackstagePlugin(p).extensions.map(e => ({ + id: e.id, + attachTo: e.attachTo, + disabled: e.disabled, + defaultConfig: e.configSchema?.parse({}), + })), + })), + ).toEqual([ + { + id: 'catalog', + extensions: [ + { + id: 'page:catalog', + attachTo: { id: 'core/routes', input: 'routes' }, + disabled: false, + defaultConfig: { path: 'catalog' }, + }, + { + id: 'page:catalog/1', + attachTo: { id: 'core/routes', input: 'routes' }, + defaultConfig: { path: 'catalog/:namespace/:kind/:name' }, + disabled: false, + }, + { + id: 'routing-shim:catalog/2', + attachTo: { + id: 'page:catalog/1', + input: 'childRoutingShims', + }, + defaultConfig: undefined, + disabled: false, + }, + { + id: 'routing-shim:catalog/3', + attachTo: { + id: 'routing-shim:catalog/2', + input: 'childRoutingShims', + }, + defaultConfig: undefined, + disabled: false, + }, + { + id: 'routing-shim:catalog/4', + attachTo: { + id: 'routing-shim:catalog/3', + input: 'childRoutingShims', + }, + defaultConfig: undefined, + disabled: false, + }, + { + id: 'api:plugin.catalog.service', + attachTo: { + id: 'core', + input: 'apis', + }, + defaultConfig: undefined, + disabled: false, + }, + { + id: 'api:catalog-react.starred-entities', + attachTo: { + id: 'core', + input: 'apis', + }, + defaultConfig: undefined, + disabled: false, + }, + { + id: 'api:plugin.catalog.entity-presentation', + attachTo: { + id: 'core', + input: 'apis', + }, + defaultConfig: undefined, + disabled: false, + }, + ], + }, + { + id: 'score-card', + extensions: [ + { + id: 'api:plugin.scoringdata.service', attachTo: { id: 'core', input: 'apis' }, disabled: false, }, diff --git a/packages/core-compat-api/src/collectLegacyRoutes.tsx b/packages/core-compat-api/src/collectLegacyRoutes.tsx index 037107bfda..729ead2786 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.tsx @@ -14,20 +14,24 @@ * limitations under the License. */ -import React, { ReactNode } from 'react'; -import { - Extension, - createApiExtension, - createPageExtension, - createPlugin, - BackstagePlugin, -} from '@backstage/frontend-plugin-api'; -import { Route, Routes } from 'react-router-dom'; import { + AnyRouteRefParams, BackstagePlugin as LegacyBackstagePlugin, RouteRef, getComponentData, } from '@backstage/core-plugin-api'; +import { + BackstagePlugin, + ExtensionDefinition, + coreExtensionData, + createApiExtension, + createExtension, + createExtensionInput, + createPageExtension, + createPlugin, +} from '@backstage/frontend-plugin-api'; +import React, { Children, ReactNode, isValidElement } from 'react'; +import { Route, Routes } from 'react-router-dom'; import { convertLegacyRouteRef } from './convertLegacyRouteRef'; /* @@ -58,59 +62,150 @@ Existing tasks: */ +// Creates a shim extension whose purpose is to build up the tree (anchored at +// the root page) of paths/routeRefs so that the app can bind them properly. +function makeRoutingShimExtension(options: { + name: string; + parentExtensionId: string; + routePath?: string; + routeRef?: RouteRef; +}) { + const { name, parentExtensionId, routePath, routeRef } = options; + return createExtension({ + kind: 'routing-shim', + name, + attachTo: { id: parentExtensionId, input: 'childRoutingShims' }, + inputs: { + childRoutingShims: createExtensionInput({ + routePath: coreExtensionData.routePath.optional(), + routeRef: coreExtensionData.routeRef.optional(), + }), + }, + output: { + routePath: coreExtensionData.routePath.optional(), + routeRef: coreExtensionData.routeRef.optional(), + }, + factory: () => ({ + routePath, + routeRef: routeRef ? convertLegacyRouteRef(routeRef) : undefined, + }), + }); +} + +function visitRouteChildren(options: { + children: ReactNode; + parentExtensionId: string; + context: { + pluginId: string; + extensions: ExtensionDefinition[]; + getUniqueName: () => string; + discoverPlugin: (plugin: LegacyBackstagePlugin) => void; + }; +}): void { + const { children, parentExtensionId, context } = options; + const { pluginId, extensions, getUniqueName, discoverPlugin } = context; + + Children.forEach(children, node => { + if (!isValidElement(node)) { + return; + } + + const plugin = getComponentData(node, 'core.plugin'); + const routeRef = getComponentData>( + node, + 'core.mountPoint', + ); + const routePath: string | undefined = node.props?.path; + + if (plugin) { + // We just mark the plugin as discovered, but don't change the context + discoverPlugin(plugin); + } + + let nextParentExtensionId = parentExtensionId; + if (routeRef || routePath) { + const nextParentExtensionName = getUniqueName(); + nextParentExtensionId = `routing-shim:${pluginId}/${nextParentExtensionName}`; + extensions.push( + makeRoutingShimExtension({ + name: nextParentExtensionName, + parentExtensionId, + routePath, + routeRef, + }), + ); + } + + visitRouteChildren({ + children: node.props.children, + parentExtensionId: nextParentExtensionId, + context, + }); + }); +} + /** @public */ export function collectLegacyRoutes( flatRoutesElement: JSX.Element, ): BackstagePlugin[] { - const createdPluginIds = new Map< + const pluginExtensions = new Map< LegacyBackstagePlugin, - Extension[] + ExtensionDefinition[] >(); + const getUniqueName = (() => { + let currentIndex = 1; + return () => String(currentIndex++); + })(); + + const getPluginExtensions = (plugin: LegacyBackstagePlugin) => { + let extensions = pluginExtensions.get(plugin); + if (!extensions) { + extensions = []; + pluginExtensions.set(plugin, extensions); + } + return extensions; + }; + React.Children.forEach( flatRoutesElement.props.children, (route: ReactNode) => { - if (!React.isValidElement(route)) { - return; - } - // TODO(freben): Handle feature flag and permissions framework wrapper elements - if (route.type !== Route) { + if (!React.isValidElement(route) || route.type !== Route) { return; } const routeElement = route.props.element; - - // TODO: to support deeper extension component, e.g. hidden within , use https://github.com/backstage/backstage/blob/518a34646b79ec2028cc0ed6bc67d4366c51c4d6/packages/core-app-api/src/routing/collectors.tsx#L69 + const path: string | undefined = route.props.path; const plugin = getComponentData( routeElement, 'core.plugin', ); - if (!plugin) { - return; - } - const routeRef = getComponentData( routeElement, 'core.mountPoint', ); + if (!plugin || !path) { + return; + } - const pluginId = plugin.getId(); + const extensions = getPluginExtensions(plugin); + const pageExtensionName = extensions.length ? getUniqueName() : undefined; + const pageExtensionId = `page:${plugin.getId()}${ + pageExtensionName ? `/${pageExtensionName}` : pageExtensionName + }`; - const detectedExtensions = - createdPluginIds.get(plugin) ?? new Array>(); - createdPluginIds.set(plugin, detectedExtensions); - - const path: string = route.props.path; - - detectedExtensions.push( + extensions.push( createPageExtension({ - id: `plugin.${pluginId}.page${ - detectedExtensions.length ? detectedExtensions.length + 1 : '' - }`, + name: pageExtensionName, defaultPath: path[0] === '/' ? path.slice(1) : path, routeRef: routeRef ? convertLegacyRouteRef(routeRef) : undefined, - + inputs: { + childRoutingShims: createExtensionInput({ + routePath: coreExtensionData.routePath.optional(), + routeRef: coreExtensionData.routeRef.optional(), + }), + }, loader: async () => route.props.children ? ( @@ -123,18 +218,27 @@ export function collectLegacyRoutes( ), }), ); + + visitRouteChildren({ + children: route.props.children, + parentExtensionId: pageExtensionId, + context: { + pluginId: plugin.getId(), + extensions, + getUniqueName, + discoverPlugin: getPluginExtensions, + }, + }); }, ); - return Array.from(createdPluginIds).map(([plugin, extensions]) => + return Array.from(pluginExtensions).map(([plugin, extensions]) => createPlugin({ id: plugin.getId(), extensions: [ ...extensions, ...Array.from(plugin.getApis()).map(factory => - createApiExtension({ - factory, - }), + createApiExtension({ factory }), ), ], }), diff --git a/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx b/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx new file mode 100644 index 0000000000..099993a392 --- /dev/null +++ b/packages/core-compat-api/src/compatWrapper/BackwardsCompatProvider.tsx @@ -0,0 +1,129 @@ +/* + * 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. + */ + +import React, { useMemo } from 'react'; +import { ReactNode } from 'react'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { AppContextProvider } from '../../../core-app-api/src/app/AppContext'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { + components as defaultComponents, + icons as defaultIcons, +} from '../../../app-defaults/src/defaults'; +import { + BackstagePlugin as NewBackstagePlugin, + appTreeApiRef, + useApi, +} from '@backstage/frontend-plugin-api'; +import { + AppComponents, + IconComponent, + BackstagePlugin as LegacyBackstagePlugin, +} from '@backstage/core-plugin-api'; +import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; + +// Make sure that we only convert each new plugin instance to its legacy equivalent once +const legacyPluginStore = getOrCreateGlobalSingleton( + 'legacy-plugin-compatibility-store', + () => new WeakMap(), +); + +function toLegacyPlugin(plugin: NewBackstagePlugin): LegacyBackstagePlugin { + let legacy = legacyPluginStore.get(plugin); + if (legacy) { + return legacy; + } + + const errorMsg = 'Not implemented in legacy plugin compatibility layer'; + const notImplemented = () => { + throw new Error(errorMsg); + }; + + legacy = { + getId(): string { + return plugin.id; + }, + get routes() { + return {}; + }, + get externalRoutes() { + return {}; + }, + getApis: notImplemented, + getFeatureFlags: notImplemented, + provide: notImplemented, + }; + + legacyPluginStore.set(plugin, legacy); + return legacy; +} + +// Recreates the old AppContext APIs using the various new APIs that replaced it +function LegacyAppContextProvider(props: { children: ReactNode }) { + const appTreeApi = useApi(appTreeApiRef); + + const appContext = useMemo(() => { + const { tree } = appTreeApi.getTree(); + + let gatheredPlugins: LegacyBackstagePlugin[] | undefined = undefined; + + return { + getPlugins(): LegacyBackstagePlugin[] { + if (gatheredPlugins) { + return gatheredPlugins; + } + + const pluginSet = new Set(); + for (const node of tree.nodes.values()) { + const plugin = node.spec.source; + if (plugin) { + pluginSet.add(toLegacyPlugin(plugin)); + } + } + gatheredPlugins = Array.from(pluginSet); + + return gatheredPlugins; + }, + + // TODO: Grab these from new API once it exists + getSystemIcon(key: string): IconComponent | undefined { + return key in defaultIcons + ? defaultIcons[key as keyof typeof defaultIcons] + : undefined; + }, + + // TODO: Grab these from new API once it exists + getSystemIcons(): Record { + return defaultIcons; + }, + + // TODO: Grab these from new API once it exists + getComponents(): AppComponents { + return defaultComponents; + }, + }; + }, [appTreeApi]); + + return ( + + {props.children} + + ); +} + +export function BackwardsCompatProvider(props: { children: ReactNode }) { + return {props.children}; +} diff --git a/packages/core-compat-api/src/compatWrapper/ForwardsCompatProvider.tsx b/packages/core-compat-api/src/compatWrapper/ForwardsCompatProvider.tsx new file mode 100644 index 0000000000..5544862aee --- /dev/null +++ b/packages/core-compat-api/src/compatWrapper/ForwardsCompatProvider.tsx @@ -0,0 +1,23 @@ +/* + * 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. + */ + +import React from 'react'; +import { ReactNode } from 'react'; + +export function ForwardsCompatProvider(props: { children: ReactNode }) { + // TODO(Rugvip): Implement + return <>{props.children}; +} diff --git a/packages/core-compat-api/src/compatWrapper/compatWrapper.test.tsx b/packages/core-compat-api/src/compatWrapper/compatWrapper.test.tsx new file mode 100644 index 0000000000..b2ad7f3d0c --- /dev/null +++ b/packages/core-compat-api/src/compatWrapper/compatWrapper.test.tsx @@ -0,0 +1,67 @@ +/* + * 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. + */ + +import React from 'react'; +import { + coreExtensionData, + createExtension, +} from '@backstage/frontend-plugin-api'; +import { createExtensionTester } from '@backstage/frontend-test-utils'; +import { screen } from '@testing-library/react'; +import { compatWrapper } from './compatWrapper'; +import { useApp } from '@backstage/core-plugin-api'; + +describe('BackwardsCompatProvider', () => { + it('should convert the app context', () => { + // TODO(Rugvip): Replace with the new renderInTestApp once it's available, and have some plugins + createExtensionTester( + createExtension({ + attachTo: { id: 'ignored', input: 'ignored' }, + output: { + element: coreExtensionData.reactElement, + }, + factory() { + function Component() { + const app = useApp(); + return ( +
+ plugins: + {app + .getPlugins() + .map(p => p.getId()) + .join(', ')} + {'\n'} + components: {Object.keys(app.getComponents()).join(', ')} + {'\n'} + icons: {Object.keys(app.getSystemIcons()).join(', ')} +
+ ); + } + + return { + element: compatWrapper(), + }; + }, + }), + ).render(); + + expect(screen.getByTestId('ctx').textContent).toMatchInlineSnapshot(` + "plugins: + components: Progress, Router, NotFoundErrorPage, BootErrorPage, ErrorBoundaryFallback + icons: brokenImage, catalog, scaffolder, techdocs, search, chat, dashboard, docs, email, github, group, help, kind:api, kind:component, kind:domain, kind:group, kind:location, kind:system, kind:user, kind:resource, kind:template, user, warning" + `); + }); +}); diff --git a/packages/core-compat-api/src/compatWrapper/compatWrapper.tsx b/packages/core-compat-api/src/compatWrapper/compatWrapper.tsx new file mode 100644 index 0000000000..cd7378a384 --- /dev/null +++ b/packages/core-compat-api/src/compatWrapper/compatWrapper.tsx @@ -0,0 +1,42 @@ +/* + * 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. + */ + +import React from 'react'; +import { useVersionedContext } from '@backstage/version-bridge'; +import { ReactNode } from 'react'; +import { BackwardsCompatProvider } from './BackwardsCompatProvider'; +import { ForwardsCompatProvider } from './ForwardsCompatProvider'; + +function BidirectionalCompatProvider(props: { children: ReactNode }) { + const isInNewApp = !useVersionedContext<{ 1: unknown }>('app-context'); + + if (isInNewApp) { + return ; + } + + return ; +} + +/** + * Wraps a React element in a bidirectional compatibility provider, allow APIs + * from `@backstage/core-plugin-api` to be used in an app from `@backstage/frontend-app-api`, + * and APIs from `@backstage/frontend-plugin-api` to be used in an app from `@backstage/core-app-api`. + * + * @public + */ +export function compatWrapper(element: ReactNode) { + return {element}; +} diff --git a/packages/core-compat-api/src/compatWrapper/index.ts b/packages/core-compat-api/src/compatWrapper/index.ts new file mode 100644 index 0000000000..42a8ff6dd4 --- /dev/null +++ b/packages/core-compat-api/src/compatWrapper/index.ts @@ -0,0 +1,17 @@ +/* + * 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 { compatWrapper } from './compatWrapper'; diff --git a/packages/core-compat-api/src/convertLegacyApp.test.tsx b/packages/core-compat-api/src/convertLegacyApp.test.tsx index 0f1f6145c9..9fae0128b0 100644 --- a/packages/core-compat-api/src/convertLegacyApp.test.tsx +++ b/packages/core-compat-api/src/convertLegacyApp.test.tsx @@ -59,13 +59,13 @@ describe('convertLegacyApp', () => { id: 'score-card', extensions: [ { - id: 'plugin.score-card.page', - attachTo: { id: 'core.routes', input: 'routes' }, + id: 'page:score-card', + attachTo: { id: 'core/routes', input: 'routes' }, disabled: false, defaultConfig: { path: 'score-board' }, }, { - id: 'apis.plugin.scoringdata.service', + id: 'api:plugin.scoringdata.service', attachTo: { id: 'core', input: 'apis' }, disabled: false, }, @@ -75,13 +75,13 @@ describe('convertLegacyApp', () => { id: 'stackstorm', extensions: [ { - id: 'plugin.stackstorm.page', - attachTo: { id: 'core.routes', input: 'routes' }, + id: 'page:stackstorm', + attachTo: { id: 'core/routes', input: 'routes' }, disabled: false, defaultConfig: { path: 'stackstorm' }, }, { - id: 'apis.plugin.stackstorm.service', + id: 'api:plugin.stackstorm.service', attachTo: { id: 'core', input: 'apis' }, disabled: false, }, @@ -91,19 +91,19 @@ describe('convertLegacyApp', () => { id: 'puppetDb', extensions: [ { - id: 'plugin.puppetDb.page', - attachTo: { id: 'core.routes', input: 'routes' }, + id: 'page:puppetDb', + attachTo: { id: 'core/routes', input: 'routes' }, disabled: false, defaultConfig: { path: 'puppetdb' }, }, { - id: 'plugin.puppetDb.page2', - attachTo: { id: 'core.routes', input: 'routes' }, + id: 'page:puppetDb/1', + attachTo: { id: 'core/routes', input: 'routes' }, disabled: false, defaultConfig: { path: 'puppetdb' }, }, { - id: 'apis.plugin.puppetdb.service', + id: 'api:plugin.puppetdb.service', attachTo: { id: 'core', input: 'apis' }, disabled: false, }, @@ -113,13 +113,13 @@ describe('convertLegacyApp', () => { id: undefined, extensions: [ { - id: 'core.layout', + id: 'core/layout', attachTo: { id: 'core', input: 'root' }, disabled: false, }, { - id: 'core.nav', - attachTo: { id: 'core.layout', input: 'nav' }, + id: 'core/nav', + attachTo: { id: 'core/layout', input: 'nav' }, disabled: true, }, ], diff --git a/packages/core-compat-api/src/convertLegacyApp.ts b/packages/core-compat-api/src/convertLegacyApp.ts index 93521b3955..9fe07cc783 100644 --- a/packages/core-compat-api/src/convertLegacyApp.ts +++ b/packages/core-compat-api/src/convertLegacyApp.ts @@ -100,7 +100,8 @@ export function convertLegacyApp( const [routesEl] = routesEls; const CoreLayoutOverride = createExtension({ - id: 'core.layout', + namespace: 'core', + name: 'layout', attachTo: { id: 'core', input: 'root' }, inputs: { content: createExtensionInput( @@ -116,13 +117,18 @@ export function convertLegacyApp( factory({ inputs }) { // Clone the root element, this replaces the FlatRoutes declared in the app with out content input return { - element: React.cloneElement(rootEl, undefined, inputs.content.element), + element: React.cloneElement( + rootEl, + undefined, + inputs.content.output.element, + ), }; }, }); const CoreNavOverride = createExtension({ - id: 'core.nav', - attachTo: { id: 'core.layout', input: 'nav' }, + namespace: 'core', + name: 'nav', + attachTo: { id: 'core/layout', input: 'nav' }, output: {}, factory: () => ({}), disabled: true, diff --git a/packages/core-compat-api/src/convertLegacyRouteRef.ts b/packages/core-compat-api/src/convertLegacyRouteRef.ts index 2495f3719c..c5ee603722 100644 --- a/packages/core-compat-api/src/convertLegacyRouteRef.ts +++ b/packages/core-compat-api/src/convertLegacyRouteRef.ts @@ -91,6 +91,7 @@ export function convertLegacyRouteRef( if (type === 'absolute') { const legacyRef = ref as LegacyRouteRef; + const legacyRefStr = String(legacyRef); const newRef = toInternalRouteRef( createRouteRef<{ [key in string]: string }>({ params: legacyRef.params as string[], @@ -104,18 +105,19 @@ export function convertLegacyRouteRef( return newRef.getParams(); }, getDescription() { - return newRef.getDescription(); + return legacyRefStr; }, setId(id: string) { newRef.setId(id); }, toString() { - return newRef.toString(); + return legacyRefStr; }, }); } if (type === 'sub') { const legacyRef = ref as LegacySubRouteRef; + const legacyRefStr = String(legacyRef); const newRef = toInternalSubRouteRef( createSubRouteRef({ path: legacyRef.path, @@ -133,15 +135,16 @@ export function convertLegacyRouteRef( return newRef.getParent(); }, getDescription() { - return newRef.getDescription(); + return legacyRefStr; }, toString() { - return newRef.toString(); + return legacyRefStr; }, }); } if (type === 'external') { const legacyRef = ref as LegacyExternalRouteRef; + const legacyRefStr = String(legacyRef); const newRef = toInternalExternalRouteRef( createExternalRouteRef<{ [key in string]: string }>({ params: legacyRef.params as string[], @@ -157,13 +160,13 @@ export function convertLegacyRouteRef( return newRef.getParams(); }, getDescription() { - return newRef.getDescription(); + return legacyRefStr; }, setId(id: string) { newRef.setId(id); }, toString() { - return newRef.toString(); + return legacyRefStr; }, }); } diff --git a/packages/core-compat-api/src/index.ts b/packages/core-compat-api/src/index.ts index 421ced7054..cb62654684 100644 --- a/packages/core-compat-api/src/index.ts +++ b/packages/core-compat-api/src/index.ts @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +export * from './compatWrapper'; + export { collectLegacyRoutes } from './collectLegacyRoutes'; export { convertLegacyApp } from './convertLegacyApp'; export { convertLegacyRouteRef } from './convertLegacyRouteRef'; diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index 8105c3c832..4702443de1 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/core-components +## 0.13.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.7 + +## 0.13.9-next.1 + +### Patch Changes + +- e8f2acef80: Added a new `/testUtils` sub-path that initially exports a `mockBreakpoint` helper. +- 07dfdf3702: Updated dependency `linkifyjs` to `4.1.3`. +- a518c5a25b: Updated dependency `@react-hookz/web` to `^23.0.0`. +- f291757e70: Update `linkify-react` to version `4.1.3` +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/version-bridge@1.0.7 + +## 0.13.9-next.0 + +### Patch Changes + +- 381ed86d5e: Add missing export for IconLinkVertical +- 5c8a3e3960: Minor improvements to `Table` component. +- 4d9e3b39e4: Register component overrides in the global `OverrideComponentNameToClassKeys` provided by `@backstage/theme`. This will in turn will provide component style override types for `createUnifiedTheme`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.7 + ## 0.13.8 ### Patch Changes diff --git a/packages/core-components/api-report-testUtils.md b/packages/core-components/api-report-testUtils.md new file mode 100644 index 0000000000..93a6bb2a07 --- /dev/null +++ b/packages/core-components/api-report-testUtils.md @@ -0,0 +1,10 @@ +## API Report File for "@backstage/core-components" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +// @public +export function mockBreakpoint(options: { matches: boolean }): void; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index d03d51f4fd..cca7017089 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -8,7 +8,6 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstageIdentityApi } from '@backstage/core-plugin-api'; import { BackstagePalette } from '@backstage/theme'; -import { BackstageTheme } from '@backstage/theme'; import { BackstageUserIdentity } from '@backstage/core-plugin-api'; import { BottomNavigationActionProps } from '@material-ui/core/BottomNavigationAction'; import { ButtonProps as ButtonProps_2 } from '@material-ui/core/Button'; @@ -541,6 +540,17 @@ export type HorizontalScrollGridClassKey = | 'buttonLeft' | 'buttonRight'; +// @public (undocumented) +export function IconLinkVertical({ + color, + disabled, + href, + icon, + label, + onClick, + title, +}: IconLinkVerticalProps): React_2.JSX.Element; + // @public (undocumented) export type IconLinkVerticalClassKey = | 'link' diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 7a031a09f6..e657e50b9d 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,11 +1,9 @@ { "name": "@backstage/core-components", "description": "Core components used by Backstage plugins and apps", - "version": "0.13.8", + "version": "0.13.9-next.2", "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts" + "access": "public" }, "backstage": { "role": "web-library" @@ -22,6 +20,21 @@ "license": "Apache-2.0", "main": "src/index.ts", "types": "src/index.ts", + "exports": { + ".": "./src/index.ts", + "./testUtils": "./src/testUtils.ts", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "testUtils": [ + "src/testUtils.ts" + ], + "package.json": [ + "package.json" + ] + } + }, "sideEffects": false, "scripts": { "build": "backstage-cli package build", @@ -43,7 +56,7 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", - "@react-hookz/web": "^20.0.0", + "@react-hookz/web": "^23.0.0", "@types/react": "^16.13.1 || ^17.0.0", "@types/react-sparklines": "^1.7.0", "@types/react-text-truncate": "^0.14.0", @@ -55,8 +68,8 @@ "dagre": "^0.8.5", "history": "^5.0.0", "immer": "^9.0.1", - "linkify-react": "4.1.2", - "linkifyjs": "4.1.2", + "linkify-react": "4.1.3", + "linkifyjs": "4.1.3", "lodash": "^4.17.21", "pluralize": "^8.0.0", "qs": "^6.9.4", diff --git a/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx b/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx index 3270cac176..6eb274b015 100644 --- a/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx +++ b/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; + import Box from '@material-ui/core/Box'; import { useTheme } from '@material-ui/core/styles'; import React from 'react'; @@ -83,7 +83,7 @@ export function CodeSnippet(props: CodeSnippetProps) { customStyle, showCopyCodeButton = false, } = props; - const theme = useTheme(); + const theme = useTheme(); const mode = theme.palette.type === 'dark' ? dark : docco; const highlightColor = theme.palette.type === 'dark' ? '#256bf3' : '#e6ffed'; diff --git a/packages/core-components/src/components/CreateButton/CreateButton.tsx b/packages/core-components/src/components/CreateButton/CreateButton.tsx index d5d7080851..beca7e8c73 100644 --- a/packages/core-components/src/components/CreateButton/CreateButton.tsx +++ b/packages/core-components/src/components/CreateButton/CreateButton.tsx @@ -14,13 +14,13 @@ * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; import Button from '@material-ui/core/Button'; import IconButton from '@material-ui/core/IconButton'; import useMediaQuery from '@material-ui/core/useMediaQuery'; import React from 'react'; import { Link as RouterLink, LinkProps } from 'react-router-dom'; import AddCircleOutline from '@material-ui/icons/AddCircleOutline'; +import { Theme } from '@material-ui/core/styles'; /** * Properties for {@link CreateButton} @@ -38,7 +38,7 @@ export type CreateButtonProps = { */ export function CreateButton(props: CreateButtonProps) { const { title, to } = props; - const isXSScreen = useMediaQuery(theme => + const isXSScreen = useMediaQuery(theme => theme.breakpoints.down('xs'), ); diff --git a/packages/core-components/src/components/DependencyGraph/DefaultLabel.tsx b/packages/core-components/src/components/DependencyGraph/DefaultLabel.tsx index 677782cf57..d4a91e50db 100644 --- a/packages/core-components/src/components/DependencyGraph/DefaultLabel.tsx +++ b/packages/core-components/src/components/DependencyGraph/DefaultLabel.tsx @@ -16,14 +16,13 @@ import React from 'react'; import makeStyles from '@material-ui/core/styles/makeStyles'; -import { BackstageTheme } from '@backstage/theme'; import { DependencyGraphTypes as Types } from './types'; /** @public */ export type DependencyGraphDefaultLabelClassKey = 'text'; const useStyles = makeStyles( - (theme: BackstageTheme) => ({ + theme => ({ text: { fill: theme.palette.textContrast, }, diff --git a/packages/core-components/src/components/DependencyGraph/DefaultNode.tsx b/packages/core-components/src/components/DependencyGraph/DefaultNode.tsx index 5c28375118..81a918c7b8 100644 --- a/packages/core-components/src/components/DependencyGraph/DefaultNode.tsx +++ b/packages/core-components/src/components/DependencyGraph/DefaultNode.tsx @@ -16,14 +16,13 @@ import React from 'react'; import { makeStyles } from '@material-ui/core/styles'; -import { BackstageTheme } from '@backstage/theme'; import { DependencyGraphTypes as Types } from './types'; /** @public */ export type DependencyGraphDefaultNodeClassKey = 'node' | 'text'; const useStyles = makeStyles( - (theme: BackstageTheme) => ({ + theme => ({ node: { fill: theme.palette.primary.light, stroke: theme.palette.primary.light, diff --git a/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx b/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx index 3dd1025b8f..d4907d2a18 100644 --- a/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx +++ b/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx @@ -20,7 +20,6 @@ import * as d3Selection from 'd3-selection'; import useTheme from '@material-ui/core/styles/useTheme'; import dagre from 'dagre'; import debounce from 'lodash/debounce'; -import { BackstageTheme } from '@backstage/theme'; import { DependencyGraphTypes as Types } from './types'; import { Node } from './Node'; import { Edge, GraphEdge } from './Edge'; @@ -205,7 +204,7 @@ export function DependencyGraph( fit = 'grow', ...svgProps } = props; - const theme: BackstageTheme = useTheme(); + const theme = useTheme(); const [containerWidth, setContainerWidth] = React.useState(100); const [containerHeight, setContainerHeight] = React.useState(100); diff --git a/packages/core-components/src/components/DependencyGraph/Edge.tsx b/packages/core-components/src/components/DependencyGraph/Edge.tsx index 4e3ba96e48..05e068eca4 100644 --- a/packages/core-components/src/components/DependencyGraph/Edge.tsx +++ b/packages/core-components/src/components/DependencyGraph/Edge.tsx @@ -18,7 +18,6 @@ import React from 'react'; import * as d3Shape from 'd3-shape'; import isFinite from 'lodash/isFinite'; import makeStyles from '@material-ui/core/styles/makeStyles'; -import { BackstageTheme } from '@backstage/theme'; import { DependencyGraphTypes as Types } from './types'; import { EDGE_TEST_ID, LABEL_TEST_ID } from './constants'; import { DefaultLabel } from './DefaultLabel'; @@ -42,7 +41,7 @@ export type GraphEdge = Types.DependencyEdge & export type DependencyGraphEdgeClassKey = 'path' | 'label'; const useStyles = makeStyles( - (theme: BackstageTheme) => ({ + theme => ({ path: { strokeWidth: 1, stroke: theme.palette.textSubtle, diff --git a/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx b/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx index 9b74b1e9b8..649043fc21 100644 --- a/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx +++ b/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx @@ -19,7 +19,6 @@ import { useApi, storageApiRef } from '@backstage/core-plugin-api'; import useObservable from 'react-use/lib/useObservable'; import classNames from 'classnames'; import { makeStyles } from '@material-ui/core/styles'; -import { BackstageTheme } from '@backstage/theme'; import Snackbar from '@material-ui/core/Snackbar'; import SnackbarContent from '@material-ui/core/SnackbarContent'; import IconButton from '@material-ui/core/IconButton'; @@ -42,7 +41,7 @@ export type DismissableBannerClassKey = export type DismissbleBannerClassKey = DismissableBannerClassKey; const useStyles = makeStyles( - (theme: BackstageTheme) => ({ + theme => ({ root: { padding: theme.spacing(0), marginBottom: theme.spacing(0), diff --git a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx index efbfdb9999..81b4714531 100644 --- a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx +++ b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; import Box from '@material-ui/core/Box'; import Button from '@material-ui/core/Button'; import { makeStyles } from '@material-ui/core/styles'; @@ -54,7 +53,7 @@ type Props = { */ export type MissingAnnotationEmptyStateClassKey = 'code'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ code: { borderRadius: 6, diff --git a/packages/core-components/src/components/HeaderIconLinkRow/index.ts b/packages/core-components/src/components/HeaderIconLinkRow/index.ts index f2207d32c5..84bb915945 100644 --- a/packages/core-components/src/components/HeaderIconLinkRow/index.ts +++ b/packages/core-components/src/components/HeaderIconLinkRow/index.ts @@ -15,6 +15,7 @@ */ export { HeaderIconLinkRow } from './HeaderIconLinkRow'; +export { IconLinkVertical } from './IconLinkVertical'; export type { HeaderIconLinkRowClassKey } from './HeaderIconLinkRow'; export type { IconLinkVerticalProps, diff --git a/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.tsx b/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.tsx index c4c9dadb78..e89b7896dd 100644 --- a/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.tsx +++ b/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.tsx @@ -16,7 +16,7 @@ import Box from '@material-ui/core/Box'; import Grid from '@material-ui/core/Grid'; import IconButton from '@material-ui/core/IconButton'; -import { makeStyles, Theme } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/core/styles'; import ChevronLeftIcon from '@material-ui/icons/ChevronLeft'; import ChevronRightIcon from '@material-ui/icons/ChevronRight'; import classNames from 'classnames'; @@ -68,7 +68,7 @@ export type HorizontalScrollGridClassKey = | 'buttonLeft' | 'buttonRight'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ root: { position: 'relative', diff --git a/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx b/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx index 425e723052..b422a62b6c 100644 --- a/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx +++ b/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx @@ -18,13 +18,12 @@ import { makeStyles } from '@material-ui/core/styles'; import ReactMarkdown, { Options } from 'react-markdown'; import gfm from 'remark-gfm'; import React from 'react'; -import { BackstageTheme } from '@backstage/theme'; import { CodeSnippet } from '../CodeSnippet'; import { HeadingProps } from 'react-markdown/lib/ast-to-react'; export type MarkdownContentClassKey = 'markdown'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ markdown: { '& table': { diff --git a/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx b/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx index c7707c07d5..782624362d 100644 --- a/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx +++ b/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { makeStyles, Theme } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/core/styles'; import ListItem from '@material-ui/core/ListItem'; import ListItemAvatar from '@material-ui/core/ListItemAvatar'; import ListItemText from '@material-ui/core/ListItemText'; @@ -26,7 +26,7 @@ import { PendingOAuthRequest } from '@backstage/core-plugin-api'; export type LoginRequestListItemClassKey = 'root'; -const useItemStyles = makeStyles( +const useItemStyles = makeStyles( theme => ({ root: { paddingLeft: theme.spacing(3), diff --git a/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx b/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx index 8fdace3766..7c17e74e4a 100644 --- a/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx +++ b/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { makeStyles, Theme } from '@material-ui/core/styles'; +import { makeStyles } from '@material-ui/core/styles'; import Dialog from '@material-ui/core/Dialog'; import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; @@ -37,7 +37,7 @@ export type OAuthRequestDialogClassKey = | 'contentList' | 'actionButtons'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ dialog: { paddingTop: theme.spacing(1), diff --git a/packages/core-components/src/components/Progress/Progress.tsx b/packages/core-components/src/components/Progress/Progress.tsx index eb17b9eb25..6d1281edd5 100644 --- a/packages/core-components/src/components/Progress/Progress.tsx +++ b/packages/core-components/src/components/Progress/Progress.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; + import Box from '@material-ui/core/Box'; import LinearProgress, { LinearProgressProps, @@ -22,7 +22,7 @@ import { useTheme } from '@material-ui/core/styles'; import React, { PropsWithChildren, useEffect, useState } from 'react'; export function Progress(props: PropsWithChildren) { - const theme = useTheme(); + const theme = useTheme(); const [isVisible, setIsVisible] = useState(false); useEffect(() => { diff --git a/packages/core-components/src/components/ProgressBars/Gauge.tsx b/packages/core-components/src/components/ProgressBars/Gauge.tsx index ca84a5f480..088e369e62 100644 --- a/packages/core-components/src/components/ProgressBars/Gauge.tsx +++ b/packages/core-components/src/components/ProgressBars/Gauge.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { BackstagePalette, BackstageTheme } from '@backstage/theme'; +import { BackstagePalette } from '@backstage/theme'; import { makeStyles, useTheme } from '@material-ui/core/styles'; import { Circle } from 'rc-progress'; import React, { ReactNode, useEffect, useState } from 'react'; @@ -28,7 +28,7 @@ export type GaugeClassKey = | 'circle' | 'colorUnknown'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ root: { position: 'relative', @@ -123,7 +123,7 @@ export function Gauge(props: GaugeProps) { const [hoverRef, setHoverRef] = useState(null); const { getColor = getProgressColor } = props; const classes = useStyles(props); - const { palette } = useTheme(); + const { palette } = useTheme(); const { value, fractional, inverse, unit, max, description } = { ...defaultGaugeProps, ...props, diff --git a/packages/core-components/src/components/ProgressBars/LinearGauge.tsx b/packages/core-components/src/components/ProgressBars/LinearGauge.tsx index 8d45b83571..a41b41f3dc 100644 --- a/packages/core-components/src/components/ProgressBars/LinearGauge.tsx +++ b/packages/core-components/src/components/ProgressBars/LinearGauge.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; + import { useTheme } from '@material-ui/core/styles'; import Tooltip from '@material-ui/core/Tooltip'; import Typography from '@material-ui/core/Typography'; @@ -33,7 +33,7 @@ type Props = { export function LinearGauge(props: Props) { const { value, getColor = getProgressColor, width = 'thick' } = props; - const { palette } = useTheme(); + const { palette } = useTheme(); if (isNaN(value)) { return null; } diff --git a/packages/core-components/src/components/Status/Status.tsx b/packages/core-components/src/components/Status/Status.tsx index 364193e383..615eed6aec 100644 --- a/packages/core-components/src/components/Status/Status.tsx +++ b/packages/core-components/src/components/Status/Status.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; + import { makeStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import classNames from 'classnames'; @@ -28,7 +28,7 @@ export type StatusClassKey = | 'running' | 'aborted'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ status: { fontWeight: theme.typography.fontWeightMedium, diff --git a/packages/core-components/src/components/SupportButton/SupportButton.tsx b/packages/core-components/src/components/SupportButton/SupportButton.tsx index a07c03b7d2..726500c77e 100644 --- a/packages/core-components/src/components/SupportButton/SupportButton.tsx +++ b/packages/core-components/src/components/SupportButton/SupportButton.tsx @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { useApp } from '@backstage/core-plugin-api'; -import { BackstageTheme } from '@backstage/theme'; import Box from '@material-ui/core/Box'; import Button from '@material-ui/core/Button'; import DialogActions from '@material-ui/core/DialogActions'; @@ -24,7 +24,7 @@ import ListItemText from '@material-ui/core/ListItemText'; import MenuItem from '@material-ui/core/MenuItem'; import MenuList from '@material-ui/core/MenuList'; import Popover from '@material-ui/core/Popover'; -import { makeStyles } from '@material-ui/core/styles'; +import { Theme, makeStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import useMediaQuery from '@material-ui/core/useMediaQuery'; import React, { MouseEventHandler, useState } from 'react'; @@ -91,7 +91,7 @@ export function SupportButton(props: SupportButtonProps) { const [popoverOpen, setPopoverOpen] = useState(false); const [anchorEl, setAnchorEl] = useState(null); const classes = useStyles(); - const isSmallScreen = useMediaQuery(theme => + const isSmallScreen = useMediaQuery(theme => theme.breakpoints.down('sm'), ); diff --git a/packages/core-components/src/components/Table/Filters.tsx b/packages/core-components/src/components/Table/Filters.tsx index 24eaa98cb5..568b22b933 100644 --- a/packages/core-components/src/components/Table/Filters.tsx +++ b/packages/core-components/src/components/Table/Filters.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; + import Box from '@material-ui/core/Box'; import Button from '@material-ui/core/Button'; import { makeStyles } from '@material-ui/core/styles'; @@ -24,7 +24,7 @@ import { SelectProps } from '../Select/Select'; export type TableFiltersClassKey = 'root' | 'value' | 'heder' | 'filters'; -const useFilterStyles = makeStyles( +const useFilterStyles = makeStyles( theme => ({ root: { height: '100%', diff --git a/packages/core-components/src/components/Table/SubvalueCell.tsx b/packages/core-components/src/components/Table/SubvalueCell.tsx index cc577b7456..8ccebbe65a 100644 --- a/packages/core-components/src/components/Table/SubvalueCell.tsx +++ b/packages/core-components/src/components/Table/SubvalueCell.tsx @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; + import Box from '@material-ui/core/Box'; import { makeStyles } from '@material-ui/core/styles'; import React from 'react'; export type SubvalueCellClassKey = 'value' | 'subvalue'; -const useSubvalueCellStyles = makeStyles( +const useSubvalueCellStyles = makeStyles( theme => ({ value: { marginBottom: theme.spacing(0.75), diff --git a/packages/core-components/src/components/Table/Table.tsx b/packages/core-components/src/components/Table/Table.tsx index e4ee9b5995..4aba7445b3 100644 --- a/packages/core-components/src/components/Table/Table.tsx +++ b/packages/core-components/src/components/Table/Table.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; + import MTable, { Column, Icons, @@ -25,7 +25,12 @@ import MTable, { } from '@material-table/core'; import Box from '@material-ui/core/Box'; import IconButton from '@material-ui/core/IconButton'; -import { makeStyles, useTheme, withStyles } from '@material-ui/core/styles'; +import { + makeStyles, + Theme, + useTheme, + withStyles, +} from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import AddBox from '@material-ui/icons/AddBox'; import ArrowUpward from '@material-ui/icons/ArrowUpward'; @@ -48,12 +53,13 @@ import React, { ReactNode, useCallback, useEffect, + useMemo, useState, } from 'react'; import { SelectProps } from '../Select/Select'; import { Filter, Filters, SelectedFilters, Without } from './Filters'; -import CircularProgress from '@material-ui/core/CircularProgress'; +import { TableLoadingBody } from './TableLoadingBody'; // Material-table is not using the standard icons available in in material-ui. https://github.com/mbrn/material-table/issues/51 const tableIcons: Icons = { @@ -136,7 +142,7 @@ const StyledMTableToolbar = withStyles( /** @public */ export type FiltersContainerClassKey = 'root' | 'title'; -const useFilterStyles = makeStyles( +const useFilterStyles = makeStyles( theme => ({ root: { display: 'flex', @@ -154,7 +160,7 @@ const useFilterStyles = makeStyles( export type TableClassKey = 'root'; -const useTableStyles = makeStyles( +const useTableStyles = makeStyles( () => ({ root: { display: 'flex', @@ -166,7 +172,7 @@ const useTableStyles = makeStyles( function convertColumns( columns: TableColumn[], - theme: BackstageTheme, + theme: Theme, ): TableColumn[] { return columns.map(column => { const headerStyle: React.CSSProperties = column.headerStyle ?? {}; @@ -303,20 +309,21 @@ export function Table(props: TableProps) { const { data, columns, + emptyContent, options, title, subtitle, + localization, filters, initialState, - emptyContent, onStateChange, components, - isLoading: isLoading, + isLoading: loading, ...restProps } = props; const tableClasses = useTableStyles(); - const theme = useTheme(); + const theme = useTheme(); const calculatedInitialState = { ...defaultInitialState, ...initialState }; @@ -327,14 +334,11 @@ export function Table(props: TableProps) { () => setFiltersOpen(v => !v), [setFiltersOpen], ); - const [selectedFiltersLength, setSelectedFiltersLength] = useState(0); - const [tableData, setTableData] = useState(data as any[]); + const [selectedFilters, setSelectedFilters] = useState( calculatedInitialState.filters, ); - const MTColumns = convertColumns(columns, theme); - const [search, setSearch] = useState(calculatedInitialState.search); useEffect(() => { @@ -352,25 +356,15 @@ export function Table(props: TableProps) { } }, [search, filtersOpen, selectedFilters, onStateChange]); - const defaultOptions: Options = { - headerStyle: { - textTransform: 'uppercase', - }, - }; - const getFieldByTitle = useCallback( (titleValue: string | keyof T) => columns.find(el => el.title === titleValue)?.field, [columns], ); - useEffect(() => { - if (typeof data === 'function') { - return; - } - if (!selectedFilters) { - setTableData(data as any[]); - return; + const tableData = useMemo(() => { + if (typeof data === 'function' || !selectedFilters) { + return data; } const selectedFiltersArray = Object.values(selectedFilters); @@ -396,62 +390,12 @@ export function Table(props: TableProps) { return fieldValue === filterValue; }), ); - setTableData(newData); - } else { - setTableData(data as any[]); + return newData; } - setSelectedFiltersLength(selectedFiltersArray.flat().length); + return data; }, [data, selectedFilters, getFieldByTitle]); - const constructFilters = ( - filterConfig: TableFilter[], - dataValue: any[] | undefined, - ): Filter[] => { - const extractDistinctValues = (field: string | keyof T): Set => { - const distinctValues = new Set(); - const addValue = (value: any) => { - if (value !== undefined && value !== null) { - distinctValues.add(value); - } - }; - - if (dataValue) { - dataValue.forEach(el => { - const value = extractValueByField( - el, - getFieldByTitle(field) as string, - ); - - if (Array.isArray(value)) { - (value as []).forEach(addValue); - } else { - addValue(value); - } - }); - } - - return distinctValues; - }; - - const constructSelect = ( - filter: TableFilter, - ): Without => { - return { - placeholder: 'All results', - label: filter.column, - multiple: filter.type === 'multiple-select', - items: [...extractDistinctValues(filter.column)].sort().map(value => ({ - label: value, - value, - })), - }; - }; - - return filterConfig.map(filter => ({ - type: filter.type, - element: constructSelect(filter), - })); - }; + const selectedFiltersLength = Object.values(selectedFilters).flat().length; const hasFilters = !!filters?.length; const Toolbar = useCallback( @@ -471,50 +415,16 @@ export function Table(props: TableProps) { const hasNoRows = typeof data !== 'function' && data.length === 0; const columnCount = columns.length; - const Body = useCallback( - (bodyProps: any /* no type for this in material-table */) => { - if (isLoading) { - return ( - - - - - - - - - - ); - } - - if (emptyContent && hasNoRows) { - return ( - - - {emptyContent} - - - ); - } - - return ; - }, - [hasNoRows, emptyContent, columnCount, isLoading], + const Body = useMemo( + () => makeBody({ hasNoRows, emptyContent, columnCount, loading }), + [hasNoRows, emptyContent, columnCount, loading], ); return ( {filtersOpen && data && typeof data !== 'function' && filters?.length && ( @@ -522,12 +432,12 @@ export function Table(props: TableProps) { components={{ Header: StyledMTableHeader, - Toolbar, Body, + Toolbar, ...components, }} - options={{ ...defaultOptions, ...options }} - columns={MTColumns} + options={{ headerStyle: { textTransform: 'uppercase' }, ...options }} + columns={convertColumns(columns, theme)} icons={tableIcons} title={ <> @@ -541,10 +451,11 @@ export function Table(props: TableProps) { )} } - data={typeof data === 'function' ? data : tableData} + data={tableData} style={{ width: '100%' }} localization={{ toolbar: { searchPlaceholder: 'Filter', searchTooltip: 'Filter' }, + ...localization, }} {...restProps} /> @@ -553,3 +464,84 @@ export function Table(props: TableProps) { } Table.icons = Object.freeze(tableIcons); + +function makeBody({ + columnCount, + emptyContent, + hasNoRows, + loading, +}: { + hasNoRows: boolean; + emptyContent: ReactNode; + columnCount: number; + loading?: boolean; +}) { + return (bodyProps: any /* no type for this in material-table */) => { + if (loading) { + return ; + } + + if (emptyContent && hasNoRows) { + return ( + + + {emptyContent} + + + ); + } + + return ; + }; +} + +function constructFilters( + filterConfig: TableFilter[], + dataValue: any[] | undefined, + columns: TableColumn[], +): Filter[] { + const extractDistinctValues = (field: string | keyof T): Set => { + const distinctValues = new Set(); + const addValue = (value: any) => { + if (value !== undefined && value !== null) { + distinctValues.add(value); + } + }; + + if (dataValue) { + dataValue.forEach(el => { + const value = extractValueByField( + el, + columns.find(c => c.title === field)?.field as string, + ); + + if (Array.isArray(value)) { + (value as []).forEach(addValue); + } else { + addValue(value); + } + }); + } + + return distinctValues; + }; + + const constructSelect = ( + filter: TableFilter, + ): Without => { + return { + placeholder: 'All results', + label: filter.column, + multiple: filter.type === 'multiple-select', + items: [...extractDistinctValues(filter.column)].sort().map(value => ({ + label: value, + value, + })), + }; + }; + + return filterConfig.map(filter => ({ + type: filter.type, + element: constructSelect(filter), + })); +} diff --git a/packages/core-components/src/components/Table/TableLoadingBody.tsx b/packages/core-components/src/components/Table/TableLoadingBody.tsx new file mode 100644 index 0000000000..3671bf1c51 --- /dev/null +++ b/packages/core-components/src/components/Table/TableLoadingBody.tsx @@ -0,0 +1,44 @@ +/* + * 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. + */ + +import Box from '@material-ui/core/Box'; +import CircularProgress from '@material-ui/core/CircularProgress'; +import React from 'react'; + +/** + * @internal + */ +export function TableLoadingBody(props: { colSpan?: number }) { + return ( + + + + + + + + + + ); +} diff --git a/packages/core-components/src/components/TrendLine/TrendLine.tsx b/packages/core-components/src/components/TrendLine/TrendLine.tsx index b59d748c2c..25d1045e09 100644 --- a/packages/core-components/src/components/TrendLine/TrendLine.tsx +++ b/packages/core-components/src/components/TrendLine/TrendLine.tsx @@ -21,10 +21,9 @@ import { SparklinesLineProps, SparklinesProps, } from 'react-sparklines'; -import { useTheme } from '@material-ui/core/styles'; -import { BackstageTheme } from '@backstage/theme'; +import { Theme, useTheme } from '@material-ui/core/styles'; -function color(data: number[], theme: BackstageTheme): string | undefined { +function color(data: number[], theme: Theme): string | undefined { const lastNum = data[data.length - 1]; if (!lastNum) return undefined; if (lastNum >= 0.9) return theme.palette.status.ok; @@ -36,7 +35,7 @@ export function TrendLine( props: SparklinesProps & Pick & { title?: string }, ) { - const theme = useTheme(); + const theme = useTheme(); if (!props.data) return null; return ( diff --git a/packages/core-components/src/components/WarningPanel/WarningPanel.tsx b/packages/core-components/src/components/WarningPanel/WarningPanel.tsx index 1ed356024c..634b8f7b09 100644 --- a/packages/core-components/src/components/WarningPanel/WarningPanel.tsx +++ b/packages/core-components/src/components/WarningPanel/WarningPanel.tsx @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; -import { makeStyles, darken, lighten } from '@material-ui/core/styles'; + +import { makeStyles, darken, lighten, Theme } from '@material-ui/core/styles'; import Accordion from '@material-ui/core/Accordion'; import AccordionSummary from '@material-ui/core/AccordionSummary'; import AccordionDetails from '@material-ui/core/AccordionDetails'; @@ -27,7 +27,7 @@ import { MarkdownContent } from '../MarkdownContent'; const getWarningTextColor = ( severity: NonNullable, - theme: BackstageTheme, + theme: Theme, ) => { const getColor = theme.palette.type === 'light' ? darken : lighten; return getColor(theme.palette[severity].light, 0.6); @@ -35,13 +35,13 @@ const getWarningTextColor = ( const getWarningBackgroundColor = ( severity: NonNullable, - theme: BackstageTheme, + theme: Theme, ) => { const getBackgroundColor = theme.palette.type === 'light' ? lighten : darken; return getBackgroundColor(theme.palette[severity].light, 0.9); }; -const useErrorOutlineStyles = makeStyles(theme => ({ +const useErrorOutlineStyles = makeStyles(theme => ({ root: { marginRight: theme.spacing(1), fill: ({ severity }: WarningProps) => @@ -68,7 +68,7 @@ export type WarningPanelClassKey = | 'message' | 'details'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ panel: { backgroundColor: ({ severity }: WarningProps) => diff --git a/packages/core-components/src/layout/BottomLink/BottomLink.tsx b/packages/core-components/src/layout/BottomLink/BottomLink.tsx index f385d9ce11..ea706002a4 100644 --- a/packages/core-components/src/layout/BottomLink/BottomLink.tsx +++ b/packages/core-components/src/layout/BottomLink/BottomLink.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; import Box from '@material-ui/core/Box'; import Divider from '@material-ui/core/Divider'; import { makeStyles } from '@material-ui/core/styles'; @@ -26,7 +25,7 @@ import { Link } from '../../components/Link'; /** @public */ export type BottomLinkClassKey = 'root' | 'boxTitle' | 'arrow'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ root: { maxWidth: 'fit-content', diff --git a/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx b/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx index 9cfaac363e..73acf1f650 100644 --- a/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx +++ b/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; import Grid from '@material-ui/core/Grid'; import { makeStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; @@ -34,7 +33,7 @@ interface IErrorPageProps { /** @public */ export type ErrorPageClassKey = 'container' | 'title' | 'subtitle'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ container: { padding: theme.spacing(8), diff --git a/packages/core-components/src/layout/Header/Header.tsx b/packages/core-components/src/layout/Header/Header.tsx index cd2f281d65..c6ceda1070 100644 --- a/packages/core-components/src/layout/Header/Header.tsx +++ b/packages/core-components/src/layout/Header/Header.tsx @@ -15,7 +15,6 @@ */ import { configApiRef, useApi } from '@backstage/core-plugin-api'; -import { BackstageTheme } from '@backstage/theme'; import Box from '@material-ui/core/Box'; import Grid from '@material-ui/core/Grid'; import { makeStyles } from '@material-ui/core/styles'; @@ -39,7 +38,7 @@ export type HeaderClassKey = | 'breadcrumbType' | 'breadcrumbTitle'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ header: { gridArea: 'pageHeader', diff --git a/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx b/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx index fdd48a5d81..6a41d6aedc 100644 --- a/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx +++ b/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; import Grid from '@material-ui/core/Grid'; import { alpha, makeStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; @@ -24,7 +23,7 @@ import { Link } from '../../components/Link'; /** @public */ export type HeaderLabelClassKey = 'root' | 'label' | 'value'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ root: { textAlign: 'left', diff --git a/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx b/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx index 1e4e7dc316..6dc4725f09 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx @@ -13,16 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; + import Box from '@material-ui/core/Box'; -import { createStyles, makeStyles, WithStyles } from '@material-ui/core/styles'; +import { + createStyles, + makeStyles, + Theme, + WithStyles, +} from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import React from 'react'; /** @public */ export type ItemCardHeaderClassKey = 'root'; -const styles = (theme: BackstageTheme) => +const styles = (theme: Theme) => createStyles({ root: { color: theme.palette.common.white, diff --git a/packages/core-components/src/layout/Page/Page.tsx b/packages/core-components/src/layout/Page/Page.tsx index e388e0366a..28194b2889 100644 --- a/packages/core-components/src/layout/Page/Page.tsx +++ b/packages/core-components/src/layout/Page/Page.tsx @@ -15,12 +15,11 @@ */ import React from 'react'; -import { BackstageTheme } from '@backstage/theme'; -import { makeStyles, ThemeProvider } from '@material-ui/core/styles'; +import { makeStyles, Theme, ThemeProvider } from '@material-ui/core/styles'; export type PageClassKey = 'root'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ root: { display: 'grid', @@ -53,7 +52,7 @@ export function Page(props: Props) { const classes = useStyles(); return ( ({ + theme={(baseTheme: Theme) => ({ ...baseTheme, page: baseTheme.getPageTheme({ themeId }), })} diff --git a/packages/core-components/src/layout/Sidebar/Bar.tsx b/packages/core-components/src/layout/Sidebar/Bar.tsx index 8cb43ba007..550c614522 100644 --- a/packages/core-components/src/layout/Sidebar/Bar.tsx +++ b/packages/core-components/src/layout/Sidebar/Bar.tsx @@ -14,10 +14,9 @@ * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; import Box from '@material-ui/core/Box'; import Button from '@material-ui/core/Button'; -import { makeStyles } from '@material-ui/core/styles'; +import { makeStyles, Theme } from '@material-ui/core/styles'; import useMediaQuery from '@material-ui/core/useMediaQuery'; import classnames from 'classnames'; import React, { useContext, useRef, useState } from 'react'; @@ -38,7 +37,7 @@ import { useSidebarPinState } from './SidebarPinStateContext'; /** @public */ export type SidebarClassKey = 'drawer' | 'drawerOpen'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ drawer: { display: 'flex', @@ -133,7 +132,7 @@ const DesktopSidebar = (props: DesktopSidebarProps) => { } = props; const classes = useStyles({ sidebarConfig }); - const isSmallScreen = useMediaQuery( + const isSmallScreen = useMediaQuery( theme => theme.breakpoints.down('md'), { noSsr: true }, ); diff --git a/packages/core-components/src/layout/Sidebar/Intro.tsx b/packages/core-components/src/layout/Sidebar/Intro.tsx index 824e9e42fd..6f75f096fb 100644 --- a/packages/core-components/src/layout/Sidebar/Intro.tsx +++ b/packages/core-components/src/layout/Sidebar/Intro.tsx @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; + import Box from '@material-ui/core/Box'; import Collapse from '@material-ui/core/Collapse'; import IconButton from '@material-ui/core/IconButton'; -import { makeStyles } from '@material-ui/core/styles'; +import { makeStyles, Theme } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import CloseIcon from '@material-ui/icons/Close'; import { useLocalStorageValue } from '@react-hookz/web'; @@ -39,7 +39,7 @@ export type SidebarIntroClassKey = | 'introDismissText' | 'introDismissIcon'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ introCard: props => ({ color: '#b5b5b5', diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index aba4c79181..f9970749d0 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { IconComponent, useAnalytics, useElementFilter, } from '@backstage/core-plugin-api'; -import { BackstageTheme } from '@backstage/theme'; import Badge from '@material-ui/core/Badge'; import Box from '@material-ui/core/Box'; import { makeStyles, styled, Theme } from '@material-ui/core/styles'; @@ -90,7 +90,7 @@ export type SidebarItemClassKey = | 'selected'; const makeSidebarStyles = (sidebarConfig: SidebarConfig) => - makeStyles( + makeStyles( theme => ({ root: { color: theme.palette.navigation.color, @@ -501,7 +501,7 @@ const SidebarItemWithSubmenu = ({ const [isHoveredOn, setIsHoveredOn] = useState(false); const location = useLocation(); const isActive = useLocationMatch(children, location); - const isSmallScreen = useMediaQuery((theme: BackstageTheme) => + const isSmallScreen = useMediaQuery((theme: Theme) => theme.breakpoints.down('sm'), ); @@ -726,7 +726,7 @@ export const SidebarExpandButton = () => { const { sidebarConfig } = useContext(SidebarConfigContext); const classes = useMemoStyles(sidebarConfig); const { isOpen, setOpen } = useSidebarOpenState(); - const isSmallScreen = useMediaQuery( + const isSmallScreen = useMediaQuery( theme => theme.breakpoints.down('md'), { noSsr: true }, ); diff --git a/packages/core-components/src/layout/Sidebar/MobileSidebar.test.tsx b/packages/core-components/src/layout/Sidebar/MobileSidebar.test.tsx index 7012afabf1..c29276a6cf 100644 --- a/packages/core-components/src/layout/Sidebar/MobileSidebar.test.tsx +++ b/packages/core-components/src/layout/Sidebar/MobileSidebar.test.tsx @@ -14,7 +14,8 @@ * limitations under the License. */ -import { mockBreakpoint, renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp } from '@backstage/test-utils'; +import { mockBreakpoint } from '@backstage/core-components/testUtils'; import CreateComponentIcon from '@material-ui/icons/AddCircleOutline'; import HomeIcon from '@material-ui/icons/Home'; import LayersIcon from '@material-ui/icons/Layers'; diff --git a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx index 88d653cea5..bc38f5510c 100644 --- a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx +++ b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx @@ -15,11 +15,10 @@ */ import { useElementFilter } from '@backstage/core-plugin-api'; -import { BackstageTheme } from '@backstage/theme'; import BottomNavigation from '@material-ui/core/BottomNavigation'; import Box from '@material-ui/core/Box'; import IconButton from '@material-ui/core/IconButton'; -import { makeStyles } from '@material-ui/core/styles'; +import { Theme, makeStyles } from '@material-ui/core/styles'; import Drawer from '@material-ui/core/Drawer'; import Typography from '@material-ui/core/Typography'; import CloseIcon from '@material-ui/icons/Close'; @@ -51,7 +50,7 @@ type OverlayMenuProps = { children?: React.ReactNode; }; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ root: { position: 'fixed', diff --git a/packages/core-components/src/layout/Sidebar/Page.tsx b/packages/core-components/src/layout/Sidebar/Page.tsx index c0107256e1..09d5bd910c 100644 --- a/packages/core-components/src/layout/Sidebar/Page.tsx +++ b/packages/core-components/src/layout/Sidebar/Page.tsx @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; + import Box from '@material-ui/core/Box'; -import { makeStyles } from '@material-ui/core/styles'; +import { makeStyles, Theme } from '@material-ui/core/styles'; import useMediaQuery from '@material-ui/core/useMediaQuery'; import React, { createContext, @@ -34,7 +34,7 @@ import { SidebarPinStateProvider } from './SidebarPinStateContext'; export type SidebarPageClassKey = 'root'; const useStyles = makeStyles< - BackstageTheme, + Theme, { sidebarConfig: SidebarConfig; isPinned: boolean } >( theme => ({ @@ -107,10 +107,9 @@ export function SidebarPage(props: SidebarPageProps) { LocalStorage.setSidebarPinState(isPinned); }, [isPinned]); - const isMobile = useMediaQuery( - theme => theme.breakpoints.down('xs'), - { noSsr: true }, - ); + const isMobile = useMediaQuery(theme => theme.breakpoints.down('xs'), { + noSsr: true, + }); const toggleSidebarPinState = () => setIsPinned(!isPinned); diff --git a/packages/core-components/src/layout/Sidebar/SidebarGroup.test.tsx b/packages/core-components/src/layout/Sidebar/SidebarGroup.test.tsx index 687140277a..b59395efab 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarGroup.test.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarGroup.test.tsx @@ -14,7 +14,8 @@ * limitations under the License. */ -import { mockBreakpoint, renderInTestApp } from '@backstage/test-utils'; +import { mockBreakpoint } from '@backstage/core-components/testUtils'; +import { renderInTestApp } from '@backstage/test-utils'; import HomeIcon from '@material-ui/icons/Home'; import LayersIcon from '@material-ui/icons/Layers'; import LibraryBooks from '@material-ui/icons/LibraryBooks'; diff --git a/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx b/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx index 2ce68cd51a..7944728af6 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarGroup.tsx @@ -15,11 +15,10 @@ * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; import BottomNavigationAction, { BottomNavigationActionProps, } from '@material-ui/core/BottomNavigationAction'; -import { makeStyles } from '@material-ui/core/styles'; +import { Theme, makeStyles } from '@material-ui/core/styles'; import React, { useContext } from 'react'; import { useLocation } from 'react-router-dom'; import { Link } from '../../components/Link/Link'; @@ -48,7 +47,7 @@ export interface SidebarGroupProps extends BottomNavigationActionProps { children?: React.ReactNode; } -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ root: { flexGrow: 0, diff --git a/packages/core-components/src/layout/Sidebar/SidebarSubmenu.tsx b/packages/core-components/src/layout/Sidebar/SidebarSubmenu.tsx index 85ba923672..6b6951d023 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarSubmenu.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarSubmenu.tsx @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; + import Box from '@material-ui/core/Box'; -import { makeStyles } from '@material-ui/core/styles'; +import { makeStyles, Theme } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import classnames from 'classnames'; import React, { ReactNode, useContext, useEffect, useState } from 'react'; @@ -28,7 +28,7 @@ import { import { useSidebarOpenState } from './SidebarOpenStateContext'; const useStyles = makeStyles< - BackstageTheme, + Theme, { submenuConfig: SubmenuConfig; left: number } >( theme => ({ diff --git a/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx b/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx index d1925036bb..0503f58f1c 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarSubmenuItem.tsx @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import React, { useContext, useState } from 'react'; import { resolvePath, useLocation, useResolvedPath } from 'react-router-dom'; import { makeStyles } from '@material-ui/core/styles'; @@ -21,7 +22,6 @@ import Typography from '@material-ui/core/Typography'; import { Link } from '../../components/Link'; import { IconComponent } from '@backstage/core-plugin-api'; import classnames from 'classnames'; -import { BackstageTheme } from '@backstage/theme'; import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown'; import ArrowDropUpIcon from '@material-ui/icons/ArrowDropUp'; import { SidebarItemWithSubmenuContext } from './config'; @@ -29,7 +29,7 @@ import { isLocationMatch } from './utils'; import Box from '@material-ui/core/Box'; import Button from '@material-ui/core/Button'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ item: { height: 48, diff --git a/packages/core-components/src/overridableComponents.ts b/packages/core-components/src/overridableComponents.ts index c872317049..750303e4df 100644 --- a/packages/core-components/src/overridableComponents.ts +++ b/packages/core-components/src/overridableComponents.ts @@ -173,3 +173,8 @@ export type BackstageOverrides = Overrides & { StyleRules >; }; + +declare module '@backstage/theme' { + interface OverrideComponentNameToClassKeys + extends BackstageComponentsNameToClassKey {} +} diff --git a/packages/core-components/src/testUtils.ts b/packages/core-components/src/testUtils.ts new file mode 100644 index 0000000000..17bb0db63b --- /dev/null +++ b/packages/core-components/src/testUtils.ts @@ -0,0 +1,43 @@ +/* + * 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. + */ + +/** + * This is a mocking method suggested in the Jest docs, as it is not implemented in JSDOM yet. + * It can be used to mock values for the Material UI `useMediaQuery` hook if it is used in a tested component. + * + * For issues checkout the documentation: + * https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom + * + * If there are any updates from Material UI React on testing `useMediaQuery` this mock should be replaced + * https://mui.com/material-ui/react-use-media-query/#testing + * + * @public + */ +export function mockBreakpoint(options: { matches: boolean }) { + Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation(query => ({ + matches: options.matches ?? false, + media: query, + onchange: null, + addListener: jest.fn(), // deprecated + removeListener: jest.fn(), // deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), + }); +} diff --git a/packages/core-plugin-api/CHANGELOG.md b/packages/core-plugin-api/CHANGELOG.md index 8633872a15..eab6b0519b 100644 --- a/packages/core-plugin-api/CHANGELOG.md +++ b/packages/core-plugin-api/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/core-plugin-api +## 1.8.1-next.1 + +### Patch Changes + +- 0c93dc37b2: The `createTranslationRef` function from the `/alpha` subpath can now also accept a nested object structure of default translation messages, which will be flatted using `.` separators. +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## 1.8.1-next.0 + +### Patch Changes + +- 03d0b6dcdc: Removed the alpha `convertLegacyRouteRef` utility, which as been moved to `@backstage/core-compat-api` +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + ## 1.8.0 ### Minor Changes diff --git a/packages/core-plugin-api/alpha-api-report.md b/packages/core-plugin-api/api-report-alpha.md similarity index 92% rename from packages/core-plugin-api/alpha-api-report.md rename to packages/core-plugin-api/api-report-alpha.md index ba3583142f..c0f0d02535 100644 --- a/packages/core-plugin-api/alpha-api-report.md +++ b/packages/core-plugin-api/api-report-alpha.md @@ -39,19 +39,17 @@ export function createTranslationMessages< // @alpha (undocumented) export function createTranslationRef< TId extends string, - const TMessages extends { - [key in string]: string; - }, + const TNestedMessages extends AnyNestedMessages, TTranslations extends { [language in string]: () => Promise<{ default: { - [key in keyof TMessages]: string | null; + [key in keyof FlattenedMessages]: string | null; }; }>; }, >( - config: TranslationRefOptions, -): TranslationRef; + config: TranslationRefOptions, +): TranslationRef>; // @alpha (undocumented) export function createTranslationResource< @@ -169,13 +167,11 @@ export interface TranslationRef< // @alpha (undocumented) export interface TranslationRefOptions< TId extends string, - TMessages extends { - [key in string]: string; - }, + TNestedMessages extends AnyNestedMessages, TTranslations extends { [language in string]: () => Promise<{ default: { - [key in keyof TMessages]: string | null; + [key in keyof FlattenedMessages]: string | null; }; }>; }, @@ -183,7 +179,7 @@ export interface TranslationRefOptions< // (undocumented) id: TId; // (undocumented) - messages: TMessages; + messages: TNestedMessages; // (undocumented) translations?: TTranslations; } diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 57e3c35b95..3b0bc1f34b 100644 --- a/packages/core-plugin-api/package.json +++ b/packages/core-plugin-api/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-plugin-api", "description": "Core API used by Backstage plugins", - "version": "1.8.0", + "version": "1.8.1-next.1", "publishConfig": { "access": "public" }, diff --git a/packages/core-plugin-api/src/translation/TranslationRef.test.ts b/packages/core-plugin-api/src/translation/TranslationRef.test.ts index b73b521774..d1fde0810f 100644 --- a/packages/core-plugin-api/src/translation/TranslationRef.test.ts +++ b/packages/core-plugin-api/src/translation/TranslationRef.test.ts @@ -34,6 +34,40 @@ describe('TranslationRefImpl', () => { expect(internalRef.getDefaultMessages()).toEqual({ key: 'value' }); }); + it('should create a TranslationRef instance with nested messages', () => { + const ref = createTranslationRef({ + id: 'test', + messages: { + key: 'value', + 'nested.conflict1': 'outer conflict1', + nested: { + key: 'nested value', + key2: 'nested value2', + conflict1: 'inner conflict1', + conflict2: 'inner conflict2', + inner: { + key: 'inner value', + }, + }, + 'nested.conflict2': 'outer conflict2', + }, + }); + + const internalRef = toInternalTranslationRef(ref); + + expect(internalRef.$$type).toBe('@backstage/TranslationRef'); + expect(internalRef.version).toBe('v1'); + expect(internalRef.id).toBe('test'); + expect(internalRef.getDefaultMessages()).toEqual({ + key: 'value', + 'nested.key': 'nested value', + 'nested.key2': 'nested value2', + 'nested.conflict1': 'inner conflict1', + 'nested.inner.key': 'inner value', + 'nested.conflict2': 'outer conflict2', + }); + }); + it('should be created with lazy translations', async () => { const ref = createTranslationRef({ id: 'test', diff --git a/packages/core-plugin-api/src/translation/TranslationRef.ts b/packages/core-plugin-api/src/translation/TranslationRef.ts index 345a9c3f65..c2ac7a5ce3 100644 --- a/packages/core-plugin-api/src/translation/TranslationRef.ts +++ b/packages/core-plugin-api/src/translation/TranslationRef.ts @@ -34,6 +34,43 @@ export interface TranslationRef< /** @internal */ type AnyMessages = { [key in string]: string }; +/** @ignore */ +type AnyNestedMessages = { [key in string]: AnyNestedMessages | string }; + +/** + * Flattens a nested message declaration into a flat object with dot-separated keys. + * + * @ignore + */ +type FlattenedMessages = + // Flatten out object keys into a union structure of objects, e.g. { a: 'a', b: 'b' } -> { a: 'a' } | { b: 'b' } + // Any nested object will be flattened into the individual unions, e.g. { a: 'a', b: { x: 'x', y: 'y' } } -> { a: 'a' } | { 'b.x': 'x', 'b.y': 'y' } + // We create this structure by first nesting the desired union types into the original object, and + // then extract them by indexing with `keyof TMessages` to form the union. + // Throughout this the objects are wrapped up in a function parameter, which allows us to have the + // final step of flipping this unions around to an intersection by inferring the function parameter. + { + [TKey in keyof TMessages]: ( + _: TMessages[TKey] extends infer TValue // "local variable" for the value + ? TValue extends AnyNestedMessages + ? FlattenedMessages extends infer TNested // Recurse into nested messages, "local variable" for the result + ? { + [TNestedKey in keyof TNested as `${TKey & string}.${TNestedKey & + string}`]: TNested[TNestedKey]; + } + : never + : { [_ in TKey]: TValue } // Primitive object values are passed through with the same key + : never, + ) => void; + // The `[keyof TMessages]` extracts the object values union from our flattened structure, still wrapped up in function parameters. + // The `extends (_: infer TIntersection) => void` flips the union to an intersection, at which point we have the correct type. + }[keyof TMessages] extends (_: infer TIntersection) => void + ? // This object mapping just expands similar to the Expand<> utility type, providing nicer type hints + { + readonly [TExpandKey in keyof TIntersection]: TIntersection[TExpandKey]; + } + : never; + /** @internal */ export interface InternalTranslationRef< TId extends string = string, @@ -49,31 +86,53 @@ export interface InternalTranslationRef< /** @alpha */ export interface TranslationRefOptions< TId extends string, - TMessages extends { [key in string]: string }, + TNestedMessages extends AnyNestedMessages, TTranslations extends { [language in string]: () => Promise<{ - default: { [key in keyof TMessages]: string | null }; + default: { + [key in keyof FlattenedMessages]: string | null; + }; }>; }, > { id: TId; - messages: TMessages; + messages: TNestedMessages; translations?: TTranslations; } +function flattenMessages(nested: AnyNestedMessages): AnyMessages { + const entries = new Array<[string, string]>(); + + function visit(obj: AnyNestedMessages, prefix: string): void { + for (const [key, value] of Object.entries(obj)) { + if (typeof value === 'string') { + entries.push([prefix + key, value]); + } else { + visit(value, `${prefix}${key}.`); + } + } + } + + visit(nested, ''); + + return Object.fromEntries(entries); +} + /** @internal */ class TranslationRefImpl< TId extends string, - TMessages extends { [key in string]: string }, -> implements InternalTranslationRef + TNestedMessages extends AnyNestedMessages, +> implements InternalTranslationRef> { #id: TId; - #messages: TMessages; + #messages: FlattenedMessages; #resources: TranslationResource | undefined; - constructor(options: TranslationRefOptions) { + constructor(options: TranslationRefOptions) { this.#id = options.id; - this.#messages = options.messages; + this.#messages = flattenMessages( + options.messages, + ) as FlattenedMessages; } $$type = '@backstage/TranslationRef' as const; @@ -108,15 +167,17 @@ class TranslationRefImpl< /** @alpha */ export function createTranslationRef< TId extends string, - const TMessages extends { [key in string]: string }, + const TNestedMessages extends AnyNestedMessages, TTranslations extends { [language in string]: () => Promise<{ - default: { [key in keyof TMessages]: string | null }; + default: { + [key in keyof FlattenedMessages]: string | null; + }; }>; }, >( - config: TranslationRefOptions, -): TranslationRef { + config: TranslationRefOptions, +): TranslationRef> { const ref = new TranslationRefImpl(config); if (config.translations) { ref.setDefaultResource( @@ -132,7 +193,7 @@ export function createTranslationRef< /** @internal */ export function toInternalTranslationRef< TId extends string, - TMessages extends { [key in string]: string }, + TMessages extends AnyMessages, >(ref: TranslationRef): InternalTranslationRef { const r = ref as InternalTranslationRef; if (r.$$type !== '@backstage/TranslationRef') { diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index f6951e72e6..5407afcbe8 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/create-app +## 0.5.8-next.3 + +### Patch Changes + +- a96c2d4: Include the `` for group entities by default +- Updated dependencies + - @backstage/cli-common@0.1.13 + +## 0.5.8-next.2 + +### Patch Changes + +- 375b6f7d68: CircelCI plugin moved permanently +- Updated dependencies + - @backstage/cli-common@0.1.13 + +## 0.5.8-next.1 + +### Patch Changes + +- Bumped create-app version. + +## 0.5.8-next.0 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.13 + ## 0.5.7 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 3b6d5ec8b5..c4deda095f 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/create-app", "description": "A CLI that helps you create your own Backstage app", - "version": "0.5.7", + "version": "0.5.8-next.3", "publishConfig": { "access": "public" }, diff --git a/packages/create-app/src/lib/versions.ts b/packages/create-app/src/lib/versions.ts index 81bae3c0b8..03ef32d921 100644 --- a/packages/create-app/src/lib/versions.ts +++ b/packages/create-app/src/lib/versions.ts @@ -58,7 +58,6 @@ import { version as pluginCatalogBackend } from '../../../../plugins/catalog-bac import { version as pluginCatalogBackendModuleScaffolderEntityModel } from '../../../../plugins/catalog-backend-module-scaffolder-entity-model/package.json'; import { version as pluginCatalogGraph } from '../../../../plugins/catalog-graph/package.json'; import { version as pluginCatalogImport } from '../../../../plugins/catalog-import/package.json'; -import { version as pluginCircleci } from '../../../../plugins/circleci/package.json'; import { version as pluginExplore } from '../../../../plugins/explore/package.json'; import { version as pluginGithubActions } from '../../../../plugins/github-actions/package.json'; import { version as pluginLighthouse } from '../../../../plugins/lighthouse/package.json'; @@ -111,7 +110,6 @@ export const packageVersions = { pluginCatalogBackendModuleScaffolderEntityModel, '@backstage/plugin-catalog-graph': pluginCatalogGraph, '@backstage/plugin-catalog-import': pluginCatalogImport, - '@backstage/plugin-circleci': pluginCircleci, '@backstage/plugin-explore': pluginExplore, '@backstage/plugin-github-actions': pluginGithubActions, '@backstage/plugin-lighthouse': pluginLighthouse, diff --git a/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx b/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx index 6722ea2d03..7c6a71e070 100644 --- a/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/components/catalog/EntityPage.tsx @@ -300,9 +300,12 @@ const groupPage = ( - + + + + diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index f9020aaf13..bcb9033618 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/dev-utils +## 1.0.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/app-defaults@1.4.6-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + +## 1.0.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/app-defaults@1.4.6-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 1.0.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/app-defaults@1.4.6-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/catalog-model@1.4.3 + ## 1.0.23 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index fe25d1c0ef..914dccf0a5 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/dev-utils", "description": "Utilities for developing Backstage plugins.", - "version": "1.0.23", + "version": "1.0.25-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/packages/dev-utils/src/components/EntityGridItem/EntityGridItem.tsx b/packages/dev-utils/src/components/EntityGridItem/EntityGridItem.tsx index a66550a4d2..55bac24a34 100644 --- a/packages/dev-utils/src/components/EntityGridItem/EntityGridItem.tsx +++ b/packages/dev-utils/src/components/EntityGridItem/EntityGridItem.tsx @@ -16,11 +16,10 @@ import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { BackstageTheme } from '@backstage/theme'; -import { Grid, GridProps, makeStyles } from '@material-ui/core'; +import { Grid, GridProps, Theme, makeStyles } from '@material-ui/core'; import React from 'react'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ root: ({ entity }) => ({ position: 'relative', diff --git a/packages/e2e-test-utils/playwright-api-report.md b/packages/e2e-test-utils/api-report-playwright.md similarity index 100% rename from packages/e2e-test-utils/playwright-api-report.md rename to packages/e2e-test-utils/api-report-playwright.md diff --git a/packages/e2e-test/CHANGELOG.md b/packages/e2e-test/CHANGELOG.md index 988b7c95ae..f412da8738 100644 --- a/packages/e2e-test/CHANGELOG.md +++ b/packages/e2e-test/CHANGELOG.md @@ -1,5 +1,39 @@ # e2e-test +## 0.2.10-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.8-next.3 + - @backstage/cli-common@0.1.13 + - @backstage/errors@1.2.3 + +## 0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.8-next.2 + - @backstage/cli-common@0.1.13 + - @backstage/errors@1.2.3 + +## 0.2.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.8-next.1 + +## 0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.8-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/errors@1.2.3 + ## 0.2.9 ### Patch Changes diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 018c679132..c4ea45fb91 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -1,7 +1,7 @@ { "name": "e2e-test", "description": "E2E test for verifying Backstage packages", - "version": "0.2.9", + "version": "0.2.10-next.3", "private": true, "backstage": { "role": "cli" diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 56ed54388a..6335f22f3c 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/eslint-plugin +## 0.1.4-next.0 + +### Patch Changes + +- 107dc46ab1: The `no-undeclared-imports` rule will now prefer using version queries that already exist en the repo for the same dependency type when installing new packages. + ## 0.1.3 ### Patch Changes diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 34a8205868..656ec78580 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/eslint-plugin", "description": "Backstage ESLint plugin", - "version": "0.1.3", + "version": "0.1.4-next.0", "publishConfig": { "access": "public" }, diff --git a/packages/eslint-plugin/rules/no-undeclared-imports.js b/packages/eslint-plugin/rules/no-undeclared-imports.js index c986b52c65..d2c92ccb8a 100644 --- a/packages/eslint-plugin/rules/no-undeclared-imports.js +++ b/packages/eslint-plugin/rules/no-undeclared-imports.js @@ -121,6 +121,39 @@ function getAddFlagForDepsField(depsField) { } } +/** + * Looks up the most common version range for a dependency if it already exists in the repo. + * + * @param {string} name + * @param {string} flag + * @param {getPackageMap.PackageMap} packages + * @returns {string} + */ +function addVersionQuery(name, flag, packages) { + const rangeCounts = new Map(); + + for (const pkg of packages.list) { + const deps = + flag === '--dev' + ? pkg.packageJson.devDependencies + : flag === '--peer' + ? pkg.packageJson.peerDependencies + : pkg.packageJson.dependencies; + const range = deps?.[name]; + if (range) { + rangeCounts.set(range, (rangeCounts.get(range) ?? 0) + 1); + } + } + + const mostCommonRange = [...rangeCounts.entries()].sort( + (a, b) => b[1] - a[1], + )[0]?.[0]; + if (!mostCommonRange) { + return name; + } + return `${name}@${mostCommonRange}`; +} + /** @type {import('eslint').Rule.RuleModule} */ module.exports = { meta: { @@ -177,13 +210,22 @@ module.exports = { } for (const [flag, names] of Object.entries(byFlag)) { + // Look up existing version queries in the repo for the same dependency + const namesWithQuery = [...names].map(name => + addVersionQuery(name, flag, packages), + ); + // The security implication of this is a bit interesting, as crafted add-import // directives could be used to install malicious packages. However, the same is true - // for adding malicious packages to package.json, so there's significant difference. - execFileSync('yarn', ['add', ...(flag ? [flag] : []), ...names], { - cwd: localPkg.dir, - stdio: 'inherit', - }); + // for adding malicious packages to package.json, so there's no significant difference. + execFileSync( + 'yarn', + ['add', ...(flag ? [flag] : []), ...namesWithQuery], + { + cwd: localPkg.dir, + stdio: 'inherit', + }, + ); } // This switches all import directives back to the original import. diff --git a/packages/frontend-app-api/CHANGELOG.md b/packages/frontend-app-api/CHANGELOG.md index 80fd99e370..5867ae9ab5 100644 --- a/packages/frontend-app-api/CHANGELOG.md +++ b/packages/frontend-app-api/CHANGELOG.md @@ -1,5 +1,68 @@ # @backstage/frontend-app-api +## 0.4.0-next.2 + +### Minor Changes + +- ea06590: The app no longer provides the `AppContext` from `@backstage/core-plugin-api`. Components that require this context to be available should use the `compatWrapper` helper from `@backstage/core-compat-api`. + +### Patch Changes + +- aeb8008: Add support for translation extensions. +- b7adf24: Use the new plugin type for error boundary components. +- 8f5d6c1: Updates to match the new extension input wrapping. +- cb4197a: Forward ` node`` instead of `extensionId` to resolved extension inputs. +- 8837a96: Updates to match the introduction of `ExtensionDefinition` and new extension ID naming patterns. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## 0.4.0-next.1 + +### Minor Changes + +- e539735435: Updated core extension structure to make space for the sign-in page by adding `core.router`. + +### Patch Changes + +- 5eb6b8a7bc: Added the nav logo extension for customization of sidebar logo +- 1f12fb762c: Create a core components extension that allows adopters to override core app components such as `Progress`, `BootErrorPage`, `NotFoundErrorPage` and `ErrorBoundaryFallback`. +- 59709286b3: Collect and register feature flags from plugins and extension overrides. +- f27ee7d937: Migrate analytics route tracker component. +- a5a04739e1: Updates to provide `node` to extension factories instead of `id` and `source`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## 0.3.1-next.0 + +### Patch Changes + +- 60d6eb544e: Removed `@backstage/plugin-graphiql` dependency. +- 9ad4039efa: Bringing over apis from core-plugin-api +- b8cb7804c8: Added `createSpecializedApp`, which is a synchronous version of `createApp` where config and features already need to be loaded. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + ## 0.3.0 ### Minor Changes diff --git a/packages/frontend-app-api/api-report.md b/packages/frontend-app-api/api-report.md index 3d6d936018..3ca51f6331 100644 --- a/packages/frontend-app-api/api-report.md +++ b/packages/frontend-app-api/api-report.md @@ -41,6 +41,15 @@ export function createApp(options?: { // @public (undocumented) export function createExtensionTree(options: { config: Config }): ExtensionTree; +// @public +export function createSpecializedApp(options?: { + features?: (BackstagePlugin | ExtensionOverrides)[]; + config?: ConfigApi; + bindRoutes?(context: { bind: AppRouteBinder }): void; +}): { + createRoot(): JSX_2.Element; +}; + // @public (undocumented) export interface ExtensionTree { // (undocumented) diff --git a/packages/frontend-app-api/package.json b/packages/frontend-app-api/package.json index 9d35a7daf4..64c1b9defc 100644 --- a/packages/frontend-app-api/package.json +++ b/packages/frontend-app-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-app-api", - "version": "0.3.0", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/frontend-app-api/src/apis/implementations/ComponentsApi/ComponentsApi.ts b/packages/frontend-app-api/src/apis/implementations/ComponentsApi/ComponentsApi.ts new file mode 100644 index 0000000000..4d8bc47e24 --- /dev/null +++ b/packages/frontend-app-api/src/apis/implementations/ComponentsApi/ComponentsApi.ts @@ -0,0 +1,39 @@ +/* + * 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. + */ + +import { ComponentType } from 'react'; +import { ComponentRef, ComponentsApi } from '@backstage/frontend-plugin-api'; + +/** + * Implementation for the {@linkComponentApi} + * + * @internal + */ +export class DefaultComponentsApi implements ComponentsApi { + #components: Map, ComponentType>; + + constructor(components: Map, any>) { + this.#components = components; + } + + getComponent(ref: ComponentRef): ComponentType { + const impl = this.#components.get(ref); + if (!impl) { + throw new Error(`No implementation found for component ref ${ref}`); + } + return impl; + } +} diff --git a/packages/frontend-app-api/src/apis/implementations/ComponentsApi/index.ts b/packages/frontend-app-api/src/apis/implementations/ComponentsApi/index.ts new file mode 100644 index 0000000000..f04059c54f --- /dev/null +++ b/packages/frontend-app-api/src/apis/implementations/ComponentsApi/index.ts @@ -0,0 +1,17 @@ +/* + * 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 { DefaultComponentsApi } from './ComponentsApi'; diff --git a/packages/frontend-app-api/src/extensions/Core.tsx b/packages/frontend-app-api/src/extensions/Core.tsx index 60772d435c..6c6e208b5b 100644 --- a/packages/frontend-app-api/src/extensions/Core.tsx +++ b/packages/frontend-app-api/src/extensions/Core.tsx @@ -18,10 +18,11 @@ import { coreExtensionData, createExtension, createExtensionInput, + createTranslationExtension, } from '@backstage/frontend-plugin-api'; export const Core = createExtension({ - id: 'core', + namespace: 'core', attachTo: { id: 'root', input: 'default' }, // ignored inputs: { apis: createExtensionInput({ @@ -30,6 +31,12 @@ export const Core = createExtension({ themes: createExtensionInput({ theme: coreExtensionData.theme, }), + components: createExtensionInput({ + component: coreExtensionData.component, + }), + translations: createExtensionInput({ + translation: createTranslationExtension.translationDataRef, + }), root: createExtensionInput( { element: coreExtensionData.reactElement, @@ -42,7 +49,7 @@ export const Core = createExtension({ }, factory({ inputs }) { return { - root: inputs.root.element, + root: inputs.root.output.element, }; }, }); diff --git a/packages/frontend-app-api/src/extensions/CoreLayout.tsx b/packages/frontend-app-api/src/extensions/CoreLayout.tsx index 97f49acac9..e4f86256f2 100644 --- a/packages/frontend-app-api/src/extensions/CoreLayout.tsx +++ b/packages/frontend-app-api/src/extensions/CoreLayout.tsx @@ -23,8 +23,9 @@ import { import { SidebarPage } from '@backstage/core-components'; export const CoreLayout = createExtension({ - id: 'core.layout', - attachTo: { id: 'core', input: 'root' }, + namespace: 'core', + name: 'layout', + attachTo: { id: 'core/router', input: 'children' }, inputs: { nav: createExtensionInput( { @@ -46,8 +47,8 @@ export const CoreLayout = createExtension({ return { element: ( - {inputs.nav.element} - {inputs.content.element} + {inputs.nav.output.element} + {inputs.content.output.element} ), }; diff --git a/packages/frontend-app-api/src/extensions/CoreNav.tsx b/packages/frontend-app-api/src/extensions/CoreNav.tsx index 37ce50276b..ab9f29a15d 100644 --- a/packages/frontend-app-api/src/extensions/CoreNav.tsx +++ b/packages/frontend-app-api/src/extensions/CoreNav.tsx @@ -19,6 +19,7 @@ import { createExtension, coreExtensionData, createExtensionInput, + LogoElements, NavTarget, useRouteRef, } from '@backstage/frontend-plugin-api'; @@ -51,14 +52,16 @@ const useSidebarLogoStyles = makeStyles({ }, }); -const SidebarLogo = () => { +const SidebarLogo = (props: LogoElements) => { const classes = useSidebarLogoStyles(); const { isOpen } = useSidebarOpenState(); return (
- {isOpen ? : } + {isOpen + ? props?.logoFull ?? + : props?.logoIcon ?? }
); @@ -72,12 +75,22 @@ const SidebarNavItem = (props: NavTarget) => { }; export const CoreNav = createExtension({ - id: 'core.nav', - attachTo: { id: 'core.layout', input: 'nav' }, + namespace: 'core', + name: 'nav', + attachTo: { id: 'core/layout', input: 'nav' }, inputs: { items: createExtensionInput({ target: coreExtensionData.navTarget, }), + logos: createExtensionInput( + { + elements: coreExtensionData.logoElements, + }, + { + singleton: true, + optional: true, + }, + ), }, output: { element: coreExtensionData.reactElement, @@ -86,10 +99,10 @@ export const CoreNav = createExtension({ return { element: ( - + {inputs.items.map((item, index) => ( - + ))} ), diff --git a/packages/frontend-app-api/src/extensions/CoreRouter.tsx b/packages/frontend-app-api/src/extensions/CoreRouter.tsx new file mode 100644 index 0000000000..4dc73c91af --- /dev/null +++ b/packages/frontend-app-api/src/extensions/CoreRouter.tsx @@ -0,0 +1,183 @@ +/* + * 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. + */ + +import React, { ComponentType, ReactNode, useContext, useState } from 'react'; +import { + coreExtensionData, + createExtension, + createExtensionInput, +} from '@backstage/frontend-plugin-api'; +import { + ConfigApi, + IdentityApi, + SignInPageProps, + configApiRef, + useApi, +} from '@backstage/core-plugin-api'; +import { InternalAppContext } from '../wiring/InternalAppContext'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy'; +import { BrowserRouter } from 'react-router-dom'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { signInPageComponentDataRef } from '../../../frontend-plugin-api/src/extensions/createSignInPageExtension'; +import { RouteTracker } from '../routing/RouteTracker'; + +export const CoreRouter = createExtension({ + namespace: 'core', + name: 'router', + attachTo: { id: 'core', input: 'root' }, + inputs: { + signInPage: createExtensionInput( + { + component: signInPageComponentDataRef, + }, + { singleton: true, optional: true }, + ), + children: createExtensionInput( + { + element: coreExtensionData.reactElement, + }, + { singleton: true }, + ), + }, + output: { + element: coreExtensionData.reactElement, + }, + factory({ inputs }) { + return { + element: ( + + {inputs.children.output.element} + + ), + }; + }, +}); + +/** + * Read the configured base path. + * + * The returned path does not have a trailing slash. + */ +function getBasePath(configApi: ConfigApi) { + let { pathname } = new URL( + configApi.getOptionalString('app.baseUrl') ?? '/', + 'http://sample.dev', // baseUrl can be specified as just a path + ); + pathname = pathname.replace(/\/*$/, ''); + return pathname; +} + +// This wraps the sign-in page and waits for sign-in to be completed before rendering the app +function SignInPageWrapper({ + component: Component, + appIdentityProxy, + children, +}: { + component: ComponentType; + appIdentityProxy: AppIdentityProxy; + children: ReactNode; +}) { + const [identityApi, setIdentityApi] = useState(); + const configApi = useApi(configApiRef); + const basePath = getBasePath(configApi); + + if (!identityApi) { + return ; + } + + appIdentityProxy.setTarget(identityApi, { + signOutTargetUrl: basePath || '/', + }); + return <>{children}; +} + +/** + * Props for the {@link AppRouter} component. + * @public + */ +export interface AppRouterProps { + children?: ReactNode; + SignInPageComponent?: ComponentType; +} + +/** + * App router and sign-in page wrapper. + * + * @public + * @remarks + * + * The AppRouter provides the routing context and renders the sign-in page. + * Until the user has successfully signed in, this component will render + * the sign-in page. Once the user has signed-in, it will instead render + * the app, while providing routing and route tracking for the app. + */ +export function AppRouter(props: AppRouterProps) { + const { children, SignInPageComponent } = props; + + const configApi = useApi(configApiRef); + const basePath = getBasePath(configApi); + const internalAppContext = useContext(InternalAppContext); + if (!internalAppContext) { + throw new Error('AppRouter must be rendered within the AppProvider'); + } + const { routeObjects, appIdentityProxy } = internalAppContext; + + // If the app hasn't configured a sign-in page, we just continue as guest. + if (!SignInPageComponent) { + appIdentityProxy.setTarget( + { + getUserId: () => 'guest', + getIdToken: async () => undefined, + getProfile: () => ({ + email: 'guest@example.com', + displayName: 'Guest', + }), + getProfileInfo: async () => ({ + email: 'guest@example.com', + displayName: 'Guest', + }), + getBackstageIdentity: async () => ({ + type: 'user', + userEntityRef: 'user:default/guest', + ownershipEntityRefs: ['user:default/guest'], + }), + getCredentials: async () => ({}), + signOut: async () => {}, + }, + { signOutTargetUrl: basePath || '/' }, + ); + + return ( + + + {children} + + ); + } + + return ( + + + + {children} + + + ); +} diff --git a/packages/frontend-app-api/src/extensions/CoreRoutes.tsx b/packages/frontend-app-api/src/extensions/CoreRoutes.tsx index 985fd07be9..155a5b60fa 100644 --- a/packages/frontend-app-api/src/extensions/CoreRoutes.tsx +++ b/packages/frontend-app-api/src/extensions/CoreRoutes.tsx @@ -19,12 +19,15 @@ import { createExtension, coreExtensionData, createExtensionInput, + coreComponentRefs, + useComponentRef, } from '@backstage/frontend-plugin-api'; import { useRoutes } from 'react-router-dom'; export const CoreRoutes = createExtension({ - id: 'core.routes', - attachTo: { id: 'core.layout', input: 'content' }, + namespace: 'core', + name: 'routes', + attachTo: { id: 'core/layout', input: 'content' }, inputs: { routes: createExtensionInput({ path: coreExtensionData.routePath, @@ -37,13 +40,21 @@ export const CoreRoutes = createExtension({ }, factory({ inputs }) { const Routes = () => { - const element = useRoutes( - inputs.routes.map(route => ({ - path: `${route.path}/*`, - element: route.element, - })), + const NotFoundErrorPage = useComponentRef( + coreComponentRefs.notFoundErrorPage, ); + const element = useRoutes([ + ...inputs.routes.map(route => ({ + path: `${route.output.path}/*`, + element: route.output.element, + })), + { + path: '*', + element: , + }, + ]); + return element; }; return { diff --git a/packages/frontend-app-api/src/extensions/components.tsx b/packages/frontend-app-api/src/extensions/components.tsx new file mode 100644 index 0000000000..44d479f170 --- /dev/null +++ b/packages/frontend-app-api/src/extensions/components.tsx @@ -0,0 +1,56 @@ +/* + * 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. + */ + +import React from 'react'; +// TODO: Dependency on MUI should be removed from core packages +import { Button } from '@material-ui/core'; + +import { + createComponentExtension, + coreComponentRefs, +} from '@backstage/frontend-plugin-api'; +import { ErrorPanel } from '@backstage/core-components'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { components as defaultComponents } from '../../../app-defaults/src/defaults'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports + +export const DefaultProgressComponent = createComponentExtension({ + ref: coreComponentRefs.progress, + component: { sync: () => defaultComponents.Progress }, +}); + +export const DefaultNotFoundErrorPageComponent = createComponentExtension({ + ref: coreComponentRefs.notFoundErrorPage, + component: { sync: () => defaultComponents.NotFoundErrorPage }, +}); + +export const DefaultErrorBoundaryComponent = createComponentExtension({ + ref: coreComponentRefs.errorBoundaryFallback, + component: { + sync: () => props => { + const { plugin, error, resetError } = props; + const title = `Error in ${plugin?.id}`; + + return ( + + + + ); + }, + }, +}); diff --git a/packages/frontend-app-api/src/routing/RouteTracker.test.tsx b/packages/frontend-app-api/src/routing/RouteTracker.test.tsx new file mode 100644 index 0000000000..0e66d0e50d --- /dev/null +++ b/packages/frontend-app-api/src/routing/RouteTracker.test.tsx @@ -0,0 +1,254 @@ +/* + * 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. + */ +import { TestApiProvider } from '@backstage/test-utils'; +import React, { useEffect } from 'react'; +import { BackstageRouteObject } from './types'; +import { fireEvent, render } from '@testing-library/react'; +import { RouteTracker } from './RouteTracker'; +import { Link, MemoryRouter, Route, Routes } from 'react-router-dom'; +import { createPlugin } from '@backstage/core-plugin-api'; +import { + createRouteRef, + AnalyticsApi, + analyticsApiRef, + AppNode, + useAnalytics, +} from '@backstage/frontend-plugin-api'; +import { MATCH_ALL_ROUTE } from './extractRouteInfoFromAppNode'; + +describe('RouteTracker', () => { + const routeRef0 = createRouteRef(); + const routeRef1 = createRouteRef(); + const routeRef2 = createRouteRef(); + const plugin0 = createPlugin({ id: 'home' }); + const plugin1 = createPlugin({ id: 'plugin1' }); + const plugin2 = createPlugin({ id: 'plugin2' }); + + const routeObjects: BackstageRouteObject[] = [ + { + path: '', + element:
home page
, + routeRefs: new Set([routeRef0]), + plugins: new Set([plugin0]), + caseSensitive: false, + children: [MATCH_ALL_ROUTE], + appNode: { + spec: { extension: { id: 'home.page.index' }, source: { id: 'home' } }, + } as AppNode, + }, + { + path: '/path/:p1/:p2', + element: go, + routeRefs: new Set([routeRef1]), + plugins: new Set([plugin1]), + caseSensitive: false, + children: [MATCH_ALL_ROUTE], + appNode: { + spec: { + extension: { id: 'plugin1.page.index' }, + source: { id: 'plugin1' }, + }, + } as AppNode, + }, + { + path: '/path2/:param', + element:
hi there
, + routeRefs: new Set([routeRef2]), + plugins: new Set([plugin2]), + caseSensitive: false, + children: [MATCH_ALL_ROUTE], + appNode: { + spec: { + extension: { id: 'plugin2.page.index' }, + source: { id: 'plugin2' }, + }, + } as AppNode, + }, + ]; + + const mockedAnalytics: jest.Mocked = { + captureEvent: jest.fn(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should capture the navigate event on load', async () => { + render( + + + + + , + ); + + expect(mockedAnalytics.captureEvent).toHaveBeenCalledWith({ + action: 'navigate', + attributes: { + p1: 'foo', + p2: 'bar', + }, + context: { + extensionId: 'plugin1.page.index', + pluginId: 'plugin1', + }, + subject: '/path/foo/bar', + value: undefined, + }); + }); + + it('should capture the navigate event on route change', async () => { + const { getByText } = render( + + + + + + {routeObjects.map(({ path, element }) => ( + + ))} + + + , + ); + + fireEvent.click(getByText('go')); + + expect(mockedAnalytics.captureEvent).toHaveBeenCalledWith({ + action: 'navigate', + attributes: { + param: 'hello', + }, + context: { + extensionId: 'plugin2.page.index', + pluginId: 'plugin2', + }, + subject: '/path2/hello', + value: undefined, + }); + }); + + it('should capture path query and hash', async () => { + render( + + + + + , + ); + + expect(mockedAnalytics.captureEvent).toHaveBeenCalledWith({ + action: 'navigate', + attributes: { + p1: 'foo', + p2: 'bar', + }, + context: { + extensionId: 'plugin1.page.index', + pluginId: 'plugin1', + }, + subject: '/path/foo/bar?q=1#header-1', + value: undefined, + }); + }); + + it('should match the root path and send relevant context', async () => { + render( + + + + + , + ); + + expect(mockedAnalytics.captureEvent).toHaveBeenCalledWith({ + action: 'navigate', + attributes: {}, + context: { + extensionId: 'home.page.index', + pluginId: 'home', + }, + subject: '/', + value: undefined, + }); + }); + + it('should return default context when it would have otherwise matched on the root path', async () => { + const Dummy = () => { + const analytics = useAnalytics(); + useEffect(() => { + analytics.captureEvent('click', 'test', {}); + }, [analytics]); + return
dummy
; + }; + + render( + + + + + } /> + + + , + ); + + expect(mockedAnalytics.captureEvent).toHaveBeenNthCalledWith(1, { + action: 'navigate', + attributes: {}, + context: { + extensionId: 'App', + pluginId: 'root', + }, + subject: '/not-routable-extension', + value: undefined, + }); + expect(mockedAnalytics.captureEvent).toHaveBeenNthCalledWith(2, { + action: 'click', + attributes: undefined, + context: { + extensionId: 'App', + pluginId: 'root', + }, + subject: 'test', + value: undefined, + }); + }); + + it('should return parent route context on navigating to a sub-route', async () => { + render( + + + + + , + ); + + expect(mockedAnalytics.captureEvent).toHaveBeenCalledWith({ + action: 'navigate', + attributes: { + param: 'param-value', + }, + context: { + extensionId: 'plugin2.page.index', + pluginId: 'plugin2', + }, + subject: '/path2/param-value/sub-route', + value: undefined, + }); + }); +}); diff --git a/packages/frontend-app-api/src/routing/RouteTracker.tsx b/packages/frontend-app-api/src/routing/RouteTracker.tsx new file mode 100644 index 0000000000..8cddca5c68 --- /dev/null +++ b/packages/frontend-app-api/src/routing/RouteTracker.tsx @@ -0,0 +1,129 @@ +/* + * 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. + */ + +import React, { useEffect } from 'react'; +import { matchRoutes, useLocation } from 'react-router-dom'; +import { + useAnalytics, + AnalyticsContext, + AnalyticsEventAttributes, +} from '@backstage/frontend-plugin-api'; +import { BackstageRouteObject } from './types'; + +/** + * Returns an extension context given the current pathname and a list of + * Backstage route objects. + */ +const getExtensionContext = ( + pathname: string, + routes: BackstageRouteObject[], +) => { + try { + // Find matching routes for the given path name. + const matches = matchRoutes(routes, { pathname }); + + // Of the matching routes, get the last (e.g. most specific) instance of + // the BackstageRouteObject that contains a routeRef. Filtering by routeRef + // ensures subRouteRefs are aligned to their parent routes' context. + const routeMatch = matches + ?.filter(match => match?.route.routeRefs?.size > 0) + .pop(); + const routeObject = routeMatch?.route; + + // If there is no route object, then allow inheritance of default context. + if (!routeObject) { + return undefined; + } + + // If the matched route is the root route (no path), and the pathname is + // not the path of the homepage, then inherit from the default context. + if (routeObject.path === '' && pathname !== '/') { + return undefined; + } + + const params = Object.entries( + routeMatch?.params || {}, + ).reduce((acc, [key, value]) => { + if (value !== undefined && key !== '*') { + acc[key] = value; + } + return acc; + }, {}); + + const plugin = routeObject.appNode?.spec.source; + const extension = routeObject.appNode?.spec.extension; + + return { + params, + pluginId: plugin?.id || 'root', + extensionId: extension?.id || 'App', + }; + } catch { + return undefined; + } +}; + +/** + * Performs the actual event capture on render. + */ +const TrackNavigation = ({ + pathname, + search, + hash, + attributes, +}: { + pathname: string; + search: string; + hash: string; + attributes?: AnalyticsEventAttributes; +}) => { + const analytics = useAnalytics(); + useEffect(() => { + analytics.captureEvent('navigate', `${pathname}${search}${hash}`, { + attributes, + }); + }, [analytics, pathname, search, hash, attributes]); + + return null; +}; + +/** + * Logs a "navigate" event with appropriate plugin-level analytics context + * attributes each time the user navigates to a page. + */ +export const RouteTracker = ({ + routeObjects, +}: { + routeObjects: BackstageRouteObject[]; +}) => { + const { pathname, search, hash } = useLocation(); + + const { params, ...attributes } = getExtensionContext( + pathname, + routeObjects, + ) || { params: {} }; + + return ( + + + + ); +}; diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts index c44c10180a..f0ce6ac590 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.test.ts @@ -19,7 +19,8 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { extractRouteInfoFromAppNode } from './extractRouteInfoFromAppNode'; import { AnyRouteRefParams, - Extension, + AppNode, + ExtensionDefinition, RouteRef, coreExtensionData, createExtension, @@ -29,10 +30,7 @@ import { } from '@backstage/frontend-plugin-api'; import { MockConfigApi } from '@backstage/test-utils'; import { createAppTree } from '../tree'; -import { Core } from '../extensions/Core'; -import { CoreRoutes } from '../extensions/CoreRoutes'; -import { CoreNav } from '../extensions/CoreNav'; -import { CoreLayout } from '../extensions/CoreLayout'; +import { builtinExtensions } from '../wiring/createApp'; const ref1 = createRouteRef(); const ref2 = createRouteRef(); @@ -42,16 +40,16 @@ const ref5 = createRouteRef(); const refOrder: RouteRef[] = [ref1, ref2, ref3, ref4, ref5]; function createTestExtension(options: { - id: string; + name: string; parent?: string; path?: string; routeRef?: RouteRef; }) { return createExtension({ - id: options.id, + name: options.name, attachTo: options.parent - ? { id: options.parent, input: 'children' } - : { id: 'core.routes', input: 'routes' }, + ? { id: `test/${options.parent}`, input: 'children' } + : { id: 'core/routes', input: 'routes' }, output: { element: coreExtensionData.reactElement, path: coreExtensionData.routePath.optional(), @@ -72,14 +70,14 @@ function createTestExtension(options: { }); } -function routeInfoFromExtensions(extensions: Extension[]) { +function routeInfoFromExtensions(extensions: ExtensionDefinition[]) { const plugin = createPlugin({ id: 'test', extensions, }); const tree = createAppTree({ config: new MockConfigApi({}), - builtinExtensions: [Core, CoreRoutes, CoreNav, CoreLayout], + builtinExtensions, features: [plugin], }); @@ -98,8 +96,10 @@ function routeObj( children: any[] = [], type: 'mounted' | 'gathered' = 'mounted', backstagePlugin?: BackstagePlugin, + appNode?: AppNode, ) { return { + appNode, path: path, caseSensitive: false, element: type, @@ -122,33 +122,33 @@ describe('discovery', () => { it('should collect routes', () => { const info = routeInfoFromExtensions([ createTestExtension({ - id: 'nothing', + name: 'nothing', path: 'nothing', }), createTestExtension({ - id: 'page1', + name: 'page1', path: 'foo', routeRef: ref1, }), createTestExtension({ - id: 'page2', + name: 'page2', parent: 'page1', path: 'bar/:id', routeRef: ref2, }), createTestExtension({ - id: 'page3', + name: 'page3', parent: 'page2', path: 'baz', routeRef: ref3, }), createTestExtension({ - id: 'page4', + name: 'page4', path: 'divsoup', routeRef: ref4, }), createTestExtension({ - id: 'page5', + name: 'page5', parent: 'page1', path: 'blop', routeRef: ref5, @@ -170,7 +170,14 @@ describe('discovery', () => { [ref5, ref1], ]); expect(info.routeObjects).toEqual([ - routeObj('nothing', []), + routeObj( + 'nothing', + [], + undefined, + undefined, + undefined, + expect.any(Object), + ), routeObj( 'foo', [ref1], @@ -178,45 +185,70 @@ describe('discovery', () => { routeObj( 'bar/:id', [ref2], - [routeObj('baz', [ref3], undefined, undefined, expect.any(Object))], + [ + routeObj( + 'baz', + [ref3], + undefined, + undefined, + expect.any(Object), + expect.any(Object), + ), + ], undefined, expect.any(Object), + expect.any(Object), + ), + routeObj( + 'blop', + [ref5], + undefined, + undefined, + expect.any(Object), + expect.any(Object), ), - routeObj('blop', [ref5], undefined, undefined, expect.any(Object)), ], undefined, expect.any(Object), + expect.any(Object), + ), + routeObj( + 'divsoup', + [ref4], + undefined, + undefined, + expect.any(Object), + expect.any(Object), ), - routeObj('divsoup', [ref4], undefined, undefined, expect.any(Object)), ]); }); it('should handle all react router Route patterns', () => { const info = routeInfoFromExtensions([ createTestExtension({ - id: 'page1', + name: 'page1', path: 'foo', routeRef: ref1, }), createTestExtension({ - id: 'page2', + name: 'page2', parent: 'page1', path: 'bar/:id', routeRef: ref2, }), createTestExtension({ - id: 'page3', + name: 'page3', path: 'baz', routeRef: ref3, }), createTestExtension({ - id: 'page4', + name: 'page4', parent: 'page3', path: 'divsoup', routeRef: ref4, }), createTestExtension({ - id: 'page5', + name: 'page5', parent: 'page3', path: 'blop', routeRef: ref5, @@ -242,29 +274,29 @@ describe('discovery', () => { it('should strip leading slashes in route paths', () => { const info = routeInfoFromExtensions([ createTestExtension({ - id: 'page1', + name: 'page1', path: '/foo', routeRef: ref1, }), createTestExtension({ - id: 'page2', + name: 'page2', parent: 'page1', path: '/bar/:id', routeRef: ref2, }), createTestExtension({ - id: 'page3', + name: 'page3', path: '/baz', routeRef: ref3, }), createTestExtension({ - id: 'page4', + name: 'page4', parent: 'page3', path: '/divsoup', routeRef: ref4, }), createTestExtension({ - id: 'page5', + name: 'page5', parent: 'page3', path: '/blop', routeRef: ref5, @@ -290,44 +322,44 @@ describe('discovery', () => { it('should use the route aggregator key to bind child routes to the same path', () => { const info = routeInfoFromExtensions([ createTestExtension({ - id: 'foo', + name: 'foo', path: 'foo', }), createTestExtension({ - id: 'page1', + name: 'page1', parent: 'foo', routeRef: ref1, }), createTestExtension({ - id: 'fooChild', + name: 'fooChild', parent: 'foo', }), createTestExtension({ - id: 'page2', + name: 'page2', parent: 'fooChild', routeRef: ref2, }), createTestExtension({ - id: 'fooEmpty', + name: 'fooEmpty', parent: 'foo', }), createTestExtension({ - id: 'page3', + name: 'page3', path: 'bar', routeRef: ref3, }), createTestExtension({ - id: 'page3Child', + name: 'page3Child', parent: 'page3', path: '', }), createTestExtension({ - id: 'page4', + name: 'page4', parent: 'page3Child', routeRef: ref4, }), createTestExtension({ - id: 'page5', + name: 'page5', parent: 'page4', routeRef: ref5, }), @@ -348,13 +380,30 @@ describe('discovery', () => { [ref5, ref3], ]); expect(info.routeObjects).toEqual([ - routeObj('foo', [ref1, ref2], [], 'mounted', expect.any(Object)), + routeObj( + 'foo', + [ref1, ref2], + [], + 'mounted', + expect.any(Object), + expect.any(Object), + ), routeObj( 'bar', [ref3], - [routeObj('', [ref4, ref5], [], 'mounted', expect.any(Object))], + [ + routeObj( + '', + [ref4, ref5], + [], + 'mounted', + expect.any(Object), + expect.any(Object), + ), + ], 'mounted', expect.any(Object), + expect.any(Object), ), ]); }); @@ -362,34 +411,34 @@ describe('discovery', () => { it('should use the route aggregator but stop when encountering explicit path', () => { const info = routeInfoFromExtensions([ createTestExtension({ - id: 'page1', + name: 'page1', path: 'foo', routeRef: ref1, }), createTestExtension({ - id: 'page1Child', + name: 'page1Child', parent: 'page1', path: 'bar', }), createTestExtension({ - id: 'page2', + name: 'page2', parent: 'page1Child', routeRef: ref2, }), createTestExtension({ - id: 'page3', + name: 'page3', parent: 'page2', path: 'baz', routeRef: ref3, }), createTestExtension({ - id: 'page4', + name: 'page4', parent: 'page3', path: '/blop', routeRef: ref4, }), createTestExtension({ - id: 'page5', + name: 'page5', parent: 'page2', routeRef: ref5, }), @@ -428,18 +477,22 @@ describe('discovery', () => { undefined, undefined, expect.any(Object), + expect.any(Object), ), ], undefined, expect.any(Object), + expect.any(Object), ), ], 'mounted', expect.any(Object), + expect.any(Object), ), ], undefined, expect.any(Object), + expect.any(Object), ), ]); }); @@ -447,34 +500,34 @@ describe('discovery', () => { it('should account for loose route paths', () => { const info = routeInfoFromExtensions([ createTestExtension({ - id: 'r', + name: 'r', path: 'r', }), createTestExtension({ - id: 'page1', + name: 'page1', parent: 'r', path: 'x', routeRef: ref1, }), createTestExtension({ - id: 'y', + name: 'y', path: 'y', parent: 'r', }), createTestExtension({ - id: 'page2', + name: 'page2', parent: 'y', path: '1', routeRef: ref2, }), createTestExtension({ - id: 'page3', + name: 'page3', parent: 'page2', path: 'a', routeRef: ref3, }), createTestExtension({ - id: 'page4', + name: 'page4', parent: 'page2', path: 'b', routeRef: ref4, @@ -498,7 +551,14 @@ describe('discovery', () => { 'r', [], [ - routeObj('x', [ref1], [], 'mounted', expect.any(Object)), + routeObj( + 'x', + [ref1], + [], + 'mounted', + expect.any(Object), + expect.any(Object), + ), routeObj( 'y', [], @@ -513,6 +573,7 @@ describe('discovery', () => { undefined, 'mounted', expect.any(Object), + expect.any(Object), ), routeObj( 'b', @@ -520,15 +581,22 @@ describe('discovery', () => { undefined, 'mounted', expect.any(Object), + expect.any(Object), ), ], 'mounted', expect.any(Object), + expect.any(Object), ), ], 'mounted', + undefined, + expect.any(Object), ), ], + undefined, + undefined, + expect.any(Object), ), ]); }); diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts index 43955328a8..17afbeb4c9 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromAppNode.ts @@ -15,10 +15,9 @@ */ import { RouteRef, coreExtensionData } from '@backstage/frontend-plugin-api'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { toLegacyPlugin } from '../wiring/createApp'; import { BackstageRouteObject } from './types'; import { AppNode } from '@backstage/frontend-plugin-api'; +import { toLegacyPlugin } from './toLegacyPlugin'; // We always add a child that matches all subroutes but without any route refs. This makes // sure that we're always able to match each route no matter how deep the navigation goes. @@ -85,6 +84,7 @@ export function extractRouteInfoFromAppNode(node: AppNode): { caseSensitive: false, children: [MATCH_ALL_ROUTE], plugins: new Set(), + appNode: current, }; parentChildren.push(currentObj); diff --git a/packages/frontend-app-api/src/routing/toLegacyPlugin.ts b/packages/frontend-app-api/src/routing/toLegacyPlugin.ts new file mode 100644 index 0000000000..2d04d04dda --- /dev/null +++ b/packages/frontend-app-api/src/routing/toLegacyPlugin.ts @@ -0,0 +1,55 @@ +/* + * 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. + */ + +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; +import { BackstagePlugin as LegacyBackstagePlugin } from '@backstage/core-plugin-api'; +import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; + +// Make sure that we only convert each new plugin instance to its legacy equivalent once +const legacyPluginStore = getOrCreateGlobalSingleton( + 'legacy-plugin-compatibility-store', + () => new WeakMap(), +); + +export function toLegacyPlugin(plugin: BackstagePlugin): LegacyBackstagePlugin { + let legacy = legacyPluginStore.get(plugin); + if (legacy) { + return legacy; + } + + const errorMsg = 'Not implemented in legacy plugin compatibility layer'; + const notImplemented = () => { + throw new Error(errorMsg); + }; + + legacy = { + getId(): string { + return plugin.id; + }, + get routes() { + return {}; + }, + get externalRoutes() { + return {}; + }, + getApis: notImplemented, + getFeatureFlags: notImplemented, + provide: notImplemented, + }; + + legacyPluginStore.set(plugin, legacy); + return legacy; +} diff --git a/packages/frontend-app-api/src/routing/types.ts b/packages/frontend-app-api/src/routing/types.ts index 5f1ed9be84..05ea73dff8 100644 --- a/packages/frontend-app-api/src/routing/types.ts +++ b/packages/frontend-app-api/src/routing/types.ts @@ -15,6 +15,7 @@ */ import { + AppNode, ExternalRouteRef, RouteRef, SubRouteRef, @@ -35,4 +36,5 @@ export interface BackstageRouteObject { path: string; routeRefs: Set; plugins: Set; + appNode?: AppNode; } diff --git a/packages/frontend-app-api/src/tree/createAppTree.test.ts b/packages/frontend-app-api/src/tree/createAppTree.test.ts index 667e3a6fc3..15c8ab4750 100644 --- a/packages/frontend-app-api/src/tree/createAppTree.test.ts +++ b/packages/frontend-app-api/src/tree/createAppTree.test.ts @@ -54,12 +54,11 @@ describe('createAppTree', () => { it('throws an error when a core extension is overridden', () => { const config = new MockConfigApi({}); const features = [ - createPlugin({ - id: 'plugin', + createExtensionOverrides({ extensions: [ createExtension({ - id: 'core', - attachTo: { id: 'core.routes', input: 'route' }, + name: 'core', + attachTo: { id: 'core/routes', input: 'route' }, inputs: {}, output: {}, factory: () => ({}), @@ -70,33 +69,7 @@ describe('createAppTree', () => { expect(() => createAppTree({ features, config, builtinExtensions: [] }), ).toThrow( - "It is forbidden to override the following extension(s): 'core', which is done by the following plugin(s): 'plugin'", - ); - }); - - it('throws an error when duplicated extensions are detected', () => { - const config = new MockConfigApi({}); - - const ExtensionA = createExtension({ ...extBase, id: 'A' }); - - const ExtensionB = createExtension({ ...extBase, id: 'B' }); - - const PluginA = createPlugin({ - id: 'A', - extensions: [ExtensionA, ExtensionA], - }); - - const PluginB = createPlugin({ - id: 'B', - extensions: [ExtensionA, ExtensionB, ExtensionB], - }); - - const features = [PluginA, PluginB]; - - expect(() => - createAppTree({ features, config, builtinExtensions: [] }), - ).toThrow( - "The following extensions are duplicated: The extension 'A' was provided 2 time(s) by the plugin 'A' and 1 time(s) by the plugin 'B', The extension 'B' was provided 2 time(s) by the plugin 'B'", + "It is forbidden to override the following extension(s): 'core', which is done by one or more extension overrides", ); }); @@ -106,13 +79,13 @@ describe('createAppTree', () => { features: [ createExtensionOverrides({ extensions: [ - createExtension({ ...extBase, id: 'a' }), - createExtension({ ...extBase, id: 'a' }), - createExtension({ ...extBase, id: 'b' }), + createExtension({ ...extBase, name: 'a' }), + createExtension({ ...extBase, name: 'a' }), + createExtension({ ...extBase, name: 'b' }), ], }), createExtensionOverrides({ - extensions: [createExtension({ ...extBase, id: 'b' })], + extensions: [createExtension({ ...extBase, name: 'b' })], }), ], config: new MockConfigApi({}), diff --git a/packages/frontend-app-api/src/tree/instantiateAppNodeTree.test.ts b/packages/frontend-app-api/src/tree/instantiateAppNodeTree.test.ts index 68a95fa1fe..49f6203ce4 100644 --- a/packages/frontend-app-api/src/tree/instantiateAppNodeTree.test.ts +++ b/packages/frontend-app-api/src/tree/instantiateAppNodeTree.test.ts @@ -15,6 +15,7 @@ */ import { + AppNode, Extension, createExtension, createExtensionDataRef, @@ -25,53 +26,71 @@ import { createAppNodeInstance, instantiateAppNodeTree, } from './instantiateAppNodeTree'; -import { AppNodeInstance, AppNodeSpec } from '@backstage/frontend-plugin-api'; +import { AppNodeSpec } from '@backstage/frontend-plugin-api'; import { resolveAppTree } from './resolveAppTree'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { resolveExtensionDefinition } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition'; const testDataRef = createExtensionDataRef('test'); const otherDataRef = createExtensionDataRef('other'); const inputMirrorDataRef = createExtensionDataRef('mirror'); -const simpleExtension = createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - output: { - test: testDataRef, - other: otherDataRef.optional(), - }, - configSchema: createSchemaFromZod(z => - z.object({ - output: z.string().default('test'), - other: z.number().optional(), - }), - ), - factory({ config }) { - return { test: config.output, other: config.other }; - }, -}); +const simpleExtension = resolveExtensionDefinition( + createExtension({ + namespace: 'core', + name: 'test', + attachTo: { id: 'ignored', input: 'ignored' }, + output: { + test: testDataRef, + other: otherDataRef.optional(), + }, + configSchema: createSchemaFromZod(z => + z.object({ + output: z.string().default('test'), + other: z.number().optional(), + }), + ), + factory({ config }) { + return { test: config.output, other: config.other }; + }, + }), +); function makeSpec( extension: Extension, - config?: TConfig, + spec?: Partial, ): AppNodeSpec { return { id: extension.id, attachTo: extension.attachTo, disabled: extension.disabled, extension, - config, source: undefined, + ...spec, + }; +} + +function makeNode( + extension: Extension, + spec?: Partial, +): AppNode { + return { + spec: makeSpec(extension, spec), + edges: { + attachments: new Map(), + }, }; } function makeInstanceWithId( extension: Extension, config?: TConfig, -): { id: string; instance: AppNodeInstance } { +): AppNode { + const node = makeNode(extension, { config }); return { - id: extension.id, + ...node, instance: createAppNodeInstance({ - spec: makeSpec(extension, config), + node, attachments: new Map(), }), }; @@ -80,7 +99,7 @@ function makeInstanceWithId( describe('instantiateAppNodeTree', () => { it('should instantiate a single node', () => { const tree = resolveAppTree('root-node', [ - { ...makeSpec(simpleExtension), id: 'root-node' }, + makeSpec(simpleExtension, { id: 'root-node' }), ]); expect(tree.root.instance).not.toBeDefined(); instantiateAppNodeTree(tree.root); @@ -94,7 +113,7 @@ describe('instantiateAppNodeTree', () => { it('should not instantiate disabled nodes', () => { const tree = resolveAppTree('root-node', [ - { ...makeSpec(simpleExtension), id: 'root-node', disabled: true }, + makeSpec(simpleExtension, { id: 'root-node', disabled: true }), ]); expect(tree.root.instance).not.toBeDefined(); instantiateAppNodeTree(tree.root); @@ -103,10 +122,10 @@ describe('instantiateAppNodeTree', () => { it('should instantiate a node with attachments', () => { const tree = resolveAppTree('root-node', [ - { - ...makeSpec( + makeSpec( + resolveExtensionDefinition( createExtension({ - id: 'root-node', + namespace: 'root-node', attachTo: { id: 'ignored', input: 'ignored' }, inputs: { test: createExtensionInput({ test: testDataRef }), @@ -119,12 +138,11 @@ describe('instantiateAppNodeTree', () => { }, }), ), - }, - { - ...makeSpec(simpleExtension), + ), + makeSpec(simpleExtension, { id: 'child-node', attachTo: { id: 'root-node', input: 'test' }, - }, + }), ]); const childNode = tree.nodes.get('child-node'); @@ -135,8 +153,10 @@ describe('instantiateAppNodeTree', () => { instantiateAppNodeTree(tree.root); expect(tree.root.instance).toBeDefined(); expect(childNode?.instance).toBeDefined(); - expect(tree.root.instance?.getData(inputMirrorDataRef)).toEqual({ - test: [{ test: 'test' }], + expect(tree.root.instance?.getData(inputMirrorDataRef)).toMatchObject({ + test: [ + { node: { spec: { id: 'child-node' } }, output: { test: 'test' } }, + ], }); // Multiple calls should have no effect @@ -149,19 +169,21 @@ describe('instantiateAppNodeTree', () => { const tree = resolveAppTree('root-node', [ { ...makeSpec( - createExtension({ - id: 'root-node', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - test: createExtensionInput({ test: testDataRef }), - }, - output: { - inputMirror: inputMirrorDataRef, - }, - factory({ inputs }) { - return { inputMirror: inputs }; - }, - }), + resolveExtensionDefinition( + createExtension({ + namespace: 'root-node', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + test: createExtensionInput({ test: testDataRef }), + }, + output: { + inputMirror: inputMirrorDataRef, + }, + factory({ inputs }) { + return { inputMirror: inputs }; + }, + }), + ), ), }, { @@ -191,7 +213,7 @@ describe('createAppNodeInstance', () => { it('should create a simple extension instance', () => { const attachments = new Map(); const instance = createAppNodeInstance({ - spec: makeSpec(simpleExtension), + node: makeNode(simpleExtension), attachments, }); @@ -231,159 +253,183 @@ describe('createAppNodeInstance', () => { ]); const instance = createAppNodeInstance({ attachments, - spec: makeSpec( - createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - optionalSingletonPresent: createExtensionInput( - { + node: makeNode( + resolveExtensionDefinition( + createExtension({ + namespace: 'core', + name: 'test', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + optionalSingletonPresent: createExtensionInput( + { + test: testDataRef, + other: otherDataRef.optional(), + }, + { singleton: true, optional: true }, + ), + optionalSingletonMissing: createExtensionInput( + { + test: testDataRef, + other: otherDataRef.optional(), + }, + { singleton: true, optional: true }, + ), + singleton: createExtensionInput( + { + test: testDataRef, + other: otherDataRef.optional(), + }, + { singleton: true }, + ), + many: createExtensionInput({ test: testDataRef, other: otherDataRef.optional(), - }, - { singleton: true, optional: true }, - ), - optionalSingletonMissing: createExtensionInput( - { - test: testDataRef, - other: otherDataRef.optional(), - }, - { singleton: true, optional: true }, - ), - singleton: createExtensionInput( - { - test: testDataRef, - other: otherDataRef.optional(), - }, - { singleton: true }, - ), - many: createExtensionInput({ - test: testDataRef, - other: otherDataRef.optional(), - }), - }, - output: { - inputMirror: inputMirrorDataRef, - }, - factory({ inputs }) { - return { inputMirror: inputs }; - }, - }), + }), + }, + output: { + inputMirror: inputMirrorDataRef, + }, + factory({ inputs }) { + return { inputMirror: inputs }; + }, + }), + ), ), }); expect(Array.from(instance.getDataRefs())).toEqual([inputMirrorDataRef]); - expect(instance.getData(inputMirrorDataRef)).toEqual({ - optionalSingletonPresent: { test: 'optionalSingletonPresent' }, - singleton: { test: 'singleton', other: 2 }, - many: [{ test: 'many1' }, { test: 'many2', other: 3 }], + expect(instance.getData(inputMirrorDataRef)).toMatchObject({ + optionalSingletonPresent: { + node: { spec: { id: 'core/test' } }, + output: { test: 'optionalSingletonPresent' }, + }, + singleton: { + node: { spec: { id: 'core/test' } }, + output: { test: 'singleton', other: 2 }, + }, + many: [ + { node: { spec: { id: 'core/test' } }, output: { test: 'many1' } }, + { + node: { spec: { id: 'core/test' } }, + output: { test: 'many2', other: 3 }, + }, + ], }); }); it('should refuse to create an extension with invalid config', () => { expect(() => createAppNodeInstance({ - spec: { - ...makeSpec(simpleExtension), - config: { other: 'not-a-number' }, - }, + node: makeNode(simpleExtension, { config: { other: 'not-a-number' } }), attachments: new Map(), }), ).toThrow( - "Invalid configuration for extension 'core.test'; caused by Error: Expected number, received string at 'other'", + "Invalid configuration for extension 'core/test'; caused by Error: Expected number, received string at 'other'", ); }); it('should forward extension factory errors', () => { expect(() => createAppNodeInstance({ - spec: makeSpec( - createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - output: {}, - factory() { - const error = new Error('NOPE'); - error.name = 'NopeError'; - throw error; - }, - }), + node: makeNode( + resolveExtensionDefinition( + createExtension({ + namespace: 'core', + name: 'test', + attachTo: { id: 'ignored', input: 'ignored' }, + output: {}, + factory() { + const error = new Error('NOPE'); + error.name = 'NopeError'; + throw error; + }, + }), + ), ), attachments: new Map(), }), ).toThrow( - "Failed to instantiate extension 'core.test'; caused by NopeError: NOPE", + "Failed to instantiate extension 'core/test'; caused by NopeError: NOPE", ); }); it('should refuse to create an instance with duplicate output', () => { expect(() => createAppNodeInstance({ - spec: makeSpec( - createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - output: { - test1: testDataRef, - test2: testDataRef, - }, - factory({}) { - return { test1: 'test', test2: 'test2' }; - }, - }), + node: makeNode( + resolveExtensionDefinition( + createExtension({ + namespace: 'core', + name: 'test', + attachTo: { id: 'ignored', input: 'ignored' }, + output: { + test1: testDataRef, + test2: testDataRef, + }, + factory({}) { + return { test1: 'test', test2: 'test2' }; + }, + }), + ), ), attachments: new Map(), }), ).toThrow( - "Failed to instantiate extension 'core.test', duplicate extension data 'test' received via output 'test2'", + "Failed to instantiate extension 'core/test', duplicate extension data 'test' received via output 'test2'", ); }); it('should refuse to create an instance with disconnected output data', () => { expect(() => createAppNodeInstance({ - spec: makeSpec( - createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - output: { - test: testDataRef, - }, - factory({}) { - return { nonexistent: 'test' } as any; - }, - }), + node: makeNode( + resolveExtensionDefinition( + createExtension({ + namespace: 'core', + name: 'test', + attachTo: { id: 'ignored', input: 'ignored' }, + output: { + test: testDataRef, + }, + factory({}) { + return { nonexistent: 'test' } as any; + }, + }), + ), ), attachments: new Map(), }), ).toThrow( - "Failed to instantiate extension 'core.test', unknown output provided via 'nonexistent'", + "Failed to instantiate extension 'core/test', unknown output provided via 'nonexistent'", ); }); it('should refuse to create an instance with missing required input', () => { expect(() => createAppNodeInstance({ - spec: makeSpec( - createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - singleton: createExtensionInput( - { - test: testDataRef, - }, - { singleton: true }, - ), - }, - output: {}, - factory: () => ({}), - }), + node: makeNode( + resolveExtensionDefinition( + createExtension({ + namespace: 'core', + name: 'test', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + singleton: createExtensionInput( + { + test: testDataRef, + }, + { singleton: true }, + ), + }, + output: {}, + factory: () => ({}), + }), + ), ), attachments: new Map(), }), ).toThrow( - "Failed to instantiate extension 'core.test', input 'singleton' is required but was not received", + "Failed to instantiate extension 'core/test', input 'singleton' is required but was not received", ); }); @@ -408,22 +454,25 @@ describe('createAppNodeInstance', () => { ], ], ]), - spec: makeSpec( - createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - declared: createExtensionInput({ - test: testDataRef, - }), - }, - output: {}, - factory: () => ({}), - }), + node: makeNode( + resolveExtensionDefinition( + createExtension({ + namespace: 'core', + name: 'test', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + declared: createExtensionInput({ + test: testDataRef, + }), + }, + output: {}, + factory: () => ({}), + }), + ), ), }), ).toThrow( - "Failed to instantiate extension 'core.test', received undeclared input 'undeclared' from extension 'core.test'", + "Failed to instantiate extension 'core/test', received undeclared input 'undeclared' from extension 'core/test'", ); }); @@ -443,17 +492,20 @@ describe('createAppNodeInstance', () => { ], ], ]), - spec: makeSpec( - createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - output: {}, - factory: () => ({}), - }), + node: makeNode( + resolveExtensionDefinition( + createExtension({ + namespace: 'core', + name: 'test', + attachTo: { id: 'ignored', input: 'ignored' }, + output: {}, + factory: () => ({}), + }), + ), ), }), ).toThrow( - "Failed to instantiate extension 'core.test', received undeclared inputs 'undeclared1' from extension 'core.test' and 'undeclared2' from extensions 'core.test', 'core.test'", + "Failed to instantiate extension 'core/test', received undeclared inputs 'undeclared1' from extension 'core/test' and 'undeclared2' from extensions 'core/test', 'core/test'", ); }); @@ -469,25 +521,28 @@ describe('createAppNodeInstance', () => { ], ], ]), - spec: makeSpec( - createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - singleton: createExtensionInput( - { - test: testDataRef, - }, - { singleton: true }, - ), - }, - output: {}, - factory: () => ({}), - }), + node: makeNode( + resolveExtensionDefinition( + createExtension({ + namespace: 'core', + name: 'test', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + singleton: createExtensionInput( + { + test: testDataRef, + }, + { singleton: true }, + ), + }, + output: {}, + factory: () => ({}), + }), + ), ), }), ).toThrow( - "Failed to instantiate extension 'core.test', expected exactly one 'singleton' input but received multiple: 'core.test', 'core.test'", + "Failed to instantiate extension 'core/test', expected exactly one 'singleton' input but received multiple: 'core/test', 'core/test'", ); }); @@ -503,25 +558,28 @@ describe('createAppNodeInstance', () => { ], ], ]), - spec: makeSpec( - createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - singleton: createExtensionInput( - { - test: testDataRef, - }, - { singleton: true, optional: true }, - ), - }, - output: {}, - factory: () => ({}), - }), + node: makeNode( + resolveExtensionDefinition( + createExtension({ + namespace: 'core', + name: 'test', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + singleton: createExtensionInput( + { + test: testDataRef, + }, + { singleton: true, optional: true }, + ), + }, + output: {}, + factory: () => ({}), + }), + ), ), }), ).toThrow( - "Failed to instantiate extension 'core.test', expected at most one 'singleton' input but received multiple: 'core.test', 'core.test'", + "Failed to instantiate extension 'core/test', expected at most one 'singleton' input but received multiple: 'core/test', 'core/test'", ); }); @@ -531,25 +589,28 @@ describe('createAppNodeInstance', () => { attachments: new Map([ ['singleton', [makeInstanceWithId(simpleExtension, undefined)]], ]), - spec: makeSpec( - createExtension({ - id: 'core.test', - attachTo: { id: 'ignored', input: 'ignored' }, - inputs: { - singleton: createExtensionInput( - { - other: otherDataRef, - }, - { singleton: true }, - ), - }, - output: {}, - factory: () => ({}), - }), + node: makeNode( + resolveExtensionDefinition( + createExtension({ + namespace: 'core', + name: 'test', + attachTo: { id: 'ignored', input: 'ignored' }, + inputs: { + singleton: createExtensionInput( + { + other: otherDataRef, + }, + { singleton: true }, + ), + }, + output: {}, + factory: () => ({}), + }), + ), ), }), ).toThrow( - "Failed to instantiate extension 'core.test', input 'singleton' did not receive required extension data 'other' from extension 'core.test'", + "Failed to instantiate extension 'core/test', input 'singleton' did not receive required extension data 'other' from extension 'core/test'", ); }); }); diff --git a/packages/frontend-app-api/src/tree/instantiateAppNodeTree.ts b/packages/frontend-app-api/src/tree/instantiateAppNodeTree.ts index 003abbb97e..dee1c83e3f 100644 --- a/packages/frontend-app-api/src/tree/instantiateAppNodeTree.ts +++ b/packages/frontend-app-api/src/tree/instantiateAppNodeTree.ts @@ -18,13 +18,10 @@ import { AnyExtensionDataMap, AnyExtensionInputMap, ExtensionDataRef, + ResolvedExtensionInputs, } from '@backstage/frontend-plugin-api'; import mapValues from 'lodash/mapValues'; -import { - AppNode, - AppNodeInstance, - AppNodeSpec, -} from '@backstage/frontend-plugin-api'; +import { AppNode, AppNodeInstance } from '@backstage/frontend-plugin-api'; type Mutable = { -readonly [P in keyof T]: T[P]; @@ -32,14 +29,14 @@ type Mutable = { function resolveInputData( dataMap: AnyExtensionDataMap, - attachment: { id: string; instance: AppNodeInstance }, + attachment: AppNode, inputName: string, ) { return mapValues(dataMap, ref => { - const value = attachment.instance.getData(ref); + const value = attachment.instance?.getData(ref); if (value === undefined && !ref.config.optional) { throw new Error( - `input '${inputName}' did not receive required extension data '${ref.id}' from extension '${attachment.id}'`, + `input '${inputName}' did not receive required extension data '${ref.id}' from extension '${attachment.spec.id}'`, ); } return value; @@ -48,8 +45,8 @@ function resolveInputData( function resolveInputs( inputMap: AnyExtensionInputMap, - attachments: ReadonlyMap, -) { + attachments: ReadonlyMap, +): ResolvedExtensionInputs { const undeclaredAttachments = Array.from(attachments.entries()).filter( ([inputName]) => inputMap[inputName] === undefined, ); @@ -62,7 +59,7 @@ function resolveInputs( .map( ([k, exts]) => `'${k}' from extension${exts.length > 1 ? 's' : ''} '${exts - .map(e => e.id) + .map(e => e.spec.id) .join("', '")}'`, ) .join(' and ')}`, @@ -74,7 +71,7 @@ function resolveInputs( if (input.config.singleton) { if (attachedNodes.length > 1) { - const attachedNodeIds = attachedNodes.map(e => e.id); + const attachedNodeIds = attachedNodes.map(e => e.spec.id); throw Error( `expected ${ input.config.optional ? 'at most' : 'exactly' @@ -88,22 +85,30 @@ function resolveInputs( } throw Error(`input '${inputName}' is required but was not received`); } - return resolveInputData(input.extensionData, attachedNodes[0], inputName); + return { + node: attachedNodes[0], + output: resolveInputData( + input.extensionData, + attachedNodes[0], + inputName, + ), + }; } - return attachedNodes.map(attachment => - resolveInputData(input.extensionData, attachment, inputName), - ); - }); + return attachedNodes.map(attachment => ({ + node: attachment, + output: resolveInputData(input.extensionData, attachment, inputName), + })); + }) as ResolvedExtensionInputs; } /** @internal */ export function createAppNodeInstance(options: { - spec: AppNodeSpec; - attachments: ReadonlyMap; + node: AppNode; + attachments: ReadonlyMap; }): AppNodeInstance { - const { spec, attachments } = options; - const { id, extension, config, source } = spec; + const { node, attachments } = options; + const { id, extension, config } = node.spec; const extensionData = new Map(); const extensionDataRefs = new Set>(); @@ -118,7 +123,7 @@ export function createAppNodeInstance(options: { try { const namedOutputs = extension.factory({ - source, + node, config: parsedConfig, inputs: resolveInputs(extension.inputs, attachments), }); @@ -139,7 +144,7 @@ export function createAppNodeInstance(options: { } catch (e) { throw new Error( `Failed to instantiate extension '${id}'${ - e.name === 'Error' ? `, ${e.message}` : `; caused by ${e}` + e.name === 'Error' ? `, ${e.message}` : `; caused by ${e.stack}` }`, ); } @@ -167,10 +172,7 @@ export function instantiateAppNodeTree(rootNode: AppNode): void { return undefined; } - const instantiatedAttachments = new Map< - string, - { id: string; instance: AppNodeInstance }[] - >(); + const instantiatedAttachments = new Map(); for (const [input, children] of node.edges.attachments) { const instantiatedChildren = children.flatMap(child => { @@ -178,7 +180,7 @@ export function instantiateAppNodeTree(rootNode: AppNode): void { if (!childInstance) { return []; } - return [{ id: child.spec.id, instance: childInstance }]; + return [child]; }); if (instantiatedChildren.length > 0) { instantiatedAttachments.set(input, instantiatedChildren); @@ -186,7 +188,7 @@ export function instantiateAppNodeTree(rootNode: AppNode): void { } (node as Mutable).instance = createAppNodeInstance({ - spec: node.spec, + node, attachments: instantiatedAttachments, }); diff --git a/packages/frontend-app-api/src/tree/readAppExtensionsConfig.test.ts b/packages/frontend-app-api/src/tree/readAppExtensionsConfig.test.ts index 91f6992f29..504d5a6197 100644 --- a/packages/frontend-app-api/src/tree/readAppExtensionsConfig.test.ts +++ b/packages/frontend-app-api/src/tree/readAppExtensionsConfig.test.ts @@ -25,18 +25,18 @@ describe('readAppExtensionsConfig', () => { it('should disable extension with shorthand notation', () => { expect( readAppExtensionsConfig( - new ConfigReader({ app: { extensions: [{ 'core.router': false }] } }), + new ConfigReader({ app: { extensions: [{ 'core/router': false }] } }), ), ).toEqual([ { - id: 'core.router', + id: 'core/router', disabled: true, }, ]); expect( readAppExtensionsConfig( new ConfigReader({ - app: { extensions: [{ 'core.router': { disabled: true } }] }, + app: { extensions: [{ 'core/router': { disabled: true } }] }, }), ), ).toEqual([ @@ -44,7 +44,7 @@ describe('readAppExtensionsConfig', () => { at: undefined, config: undefined, disabled: true, - id: 'core.router', + id: 'core/router', }, ]); }); @@ -52,33 +52,33 @@ describe('readAppExtensionsConfig', () => { it('should enable extension with shorthand notation', () => { expect( readAppExtensionsConfig( - new ConfigReader({ app: { extensions: ['core.router'] } }), + new ConfigReader({ app: { extensions: ['core/router'] } }), ), ).toEqual([ { - id: 'core.router', + id: 'core/router', disabled: false, }, ]); expect( readAppExtensionsConfig( - new ConfigReader({ app: { extensions: [{ 'core.router': true }] } }), + new ConfigReader({ app: { extensions: [{ 'core/router': true }] } }), ), ).toEqual([ { - id: 'core.router', + id: 'core/router', disabled: false, }, ]); expect( readAppExtensionsConfig( new ConfigReader({ - app: { extensions: [{ 'core.router': { disabled: false } }] }, + app: { extensions: [{ 'core/router': { disabled: false } }] }, }), ), ).toEqual([ { - id: 'core.router', + id: 'core/router', disabled: false, }, ]); @@ -89,12 +89,12 @@ describe('readAppExtensionsConfig', () => { readAppExtensionsConfig( new ConfigReader({ app: { - extensions: [{ 'core.router': 'some-string' }], + extensions: [{ 'core/router': 'some-string' }], }, }), ), ).toThrow( - 'Invalid extension configuration at app.extensions[0][core.router], value must be a boolean or object', + 'Invalid extension configuration at app.extensions[0][core/router], value must be a boolean or object', ); }); @@ -105,7 +105,7 @@ describe('readAppExtensionsConfig', () => { app: { extensions: [ { - 'core.router/routes': { + '': { extension: 'example-package#MyPage', config: { foo: 'bar' }, }, @@ -115,7 +115,7 @@ describe('readAppExtensionsConfig', () => { }), ), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[0], extension ID must not contain slashes; got 'core.router/routes', did you mean 'core.router'?"`, + `"Invalid extension configuration at app.extensions[0], extension ID must not be empty or contain whitespace"`, ); }); }); @@ -156,8 +156,8 @@ describe('expandShorthandExtensionParameters', () => { }); it('supports string key', () => { - expect(run('core.router')).toEqual({ - id: 'core.router', + expect(run('core/router')).toEqual({ + id: 'core/router', disabled: false, }); expect(() => run('')).toThrowErrorMatchingInlineSnapshot( @@ -166,103 +166,100 @@ describe('expandShorthandExtensionParameters', () => { expect(() => run(' a')).toThrowErrorMatchingInlineSnapshot( `"Invalid extension configuration at app.extensions[1], extension ID must not be empty or contain whitespace"`, ); - expect(() => run('core.router/routes')).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1], extension ID must not contain slashes; got 'core.router/routes', did you mean 'core.router'?"`, - ); }); it('supports null value', () => { // this is the result of typing: - // - core.router: + // - core/router: // The missing value is interpreted as null by the yaml parser so we deal with that - expect(run({ 'core.router': null })).toEqual({ - id: 'core.router', + expect(run({ 'core/router': null })).toEqual({ + id: 'core/router', disabled: false, }); }); it('supports boolean value', () => { - expect(run({ 'core.router': true })).toEqual({ - id: 'core.router', + expect(run({ 'core/router': true })).toEqual({ + id: 'core/router', disabled: false, }); - expect(run({ 'core.router': false })).toEqual({ - id: 'core.router', + expect(run({ 'core/router': false })).toEqual({ + id: 'core/router', disabled: true, }); }); it('should not support string values', () => { expect(() => - run({ 'core.router': 'example-package#MyRouter' }), + run({ 'core/router': 'example-package#MyRouter' }), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router], value must be a boolean or object"`, + `"Invalid extension configuration at app.extensions[1][core/router], value must be a boolean or object"`, ); }); it('supports object id only in the key', () => { expect(() => - run({ 'core.router': { id: 'some.id' } }), + run({ 'core/router': { id: 'some.id' } }), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router].id, unknown parameter; expected one of 'attachTo', 'disabled', 'config'"`, + `"Invalid extension configuration at app.extensions[1][core/router].id, unknown parameter; expected one of 'attachTo', 'disabled', 'config'"`, ); }); it('supports object attachTo', () => { expect( run({ - 'core.router': { attachTo: { id: 'other.root', input: 'inputs' } }, + 'core/router': { attachTo: { id: 'other.root', input: 'inputs' } }, }), ).toEqual({ - id: 'core.router', + id: 'core/router', attachTo: { id: 'other.root', input: 'inputs' }, }); expect(() => run({ - 'core.router': { + 'core/router': { id: 'other-id', }, }), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router].id, unknown parameter; expected one of 'attachTo', 'disabled', 'config'"`, + `"Invalid extension configuration at app.extensions[1][core/router].id, unknown parameter; expected one of 'attachTo', 'disabled', 'config'"`, ); }); it('supports object disabled', () => { - expect(run({ 'core.router': { disabled: true } })).toEqual({ - id: 'core.router', + expect(run({ 'core/router': { disabled: true } })).toEqual({ + id: 'core/router', disabled: true, }); - expect(run({ 'core.router': { disabled: false } })).toEqual({ - id: 'core.router', + expect(run({ 'core/router': { disabled: false } })).toEqual({ + id: 'core/router', disabled: false, }); expect(() => - run({ 'core.router': { disabled: 0 } }), + run({ 'core/router': { disabled: 0 } }), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router].disabled, must be a boolean"`, + `"Invalid extension configuration at app.extensions[1][core/router].disabled, must be a boolean"`, ); }); it('supports object config', () => { expect( - run({ 'core.router': { config: { disableRedirects: true } } }), + run({ 'core/router': { config: { disableRedirects: true } } }), ).toEqual({ - id: 'core.router', + id: 'core/router', config: { disableRedirects: true }, }); expect(() => - run({ 'core.router': { config: 0 } }), + run({ 'core/router': { config: 0 } }), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router].config, must be an object"`, + `"Invalid extension configuration at app.extensions[1][core/router].config, must be an object"`, ); }); it('rejects unknown object keys', () => { expect(() => - run({ 'core.router': { foo: { settings: true } } }), + run({ 'core/router': { foo: { settings: true } } }), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router].foo, unknown parameter; expected one of 'attachTo', 'disabled', 'config'"`, + `"Invalid extension configuration at app.extensions[1][core/router].foo, unknown parameter; expected one of 'attachTo', 'disabled', 'config'"`, ); }); }); diff --git a/packages/frontend-app-api/src/tree/readAppExtensionsConfig.ts b/packages/frontend-app-api/src/tree/readAppExtensionsConfig.ts index 2b5b51ce92..cca7064add 100644 --- a/packages/frontend-app-api/src/tree/readAppExtensionsConfig.ts +++ b/packages/frontend-app-api/src/tree/readAppExtensionsConfig.ts @@ -70,15 +70,6 @@ export function expandShorthandExtensionParameters( errorMsg('extension ID must not be empty or contain whitespace'), ); } - - if (id.includes('/')) { - let message = `extension ID must not contain slashes; got '${id}'`; - const good = id.split('/')[0]; - if (good) { - message += `, did you mean '${good}'?`; - } - throw new Error(errorMsg(message)); - } } // Example YAML: diff --git a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts index 39eceaaf28..2e9f73d87b 100644 --- a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts +++ b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts @@ -18,6 +18,7 @@ import { createExtensionOverrides, createPlugin, Extension, + ExtensionDefinition, } from '@backstage/frontend-plugin-api'; import { resolveAppNodeSpecs } from './resolveAppNodeSpecs'; @@ -27,12 +28,26 @@ function makeExt( attachId: string = 'root', ) { return { + $$type: '@backstage/Extension', id, attachTo: { id: attachId, input: 'default' }, disabled: status === 'disabled', } as Extension; } +function makeExtDef( + name: string, + status: 'disabled' | 'enabled' = 'enabled', + attachId: string = 'root', +) { + return { + $$type: '@backstage/ExtensionDefinition', + name, + attachTo: { id: attachId, input: 'default' }, + disabled: status === 'disabled', + } as ExtensionDefinition; +} + describe('resolveAppNodeSpecs', () => { it('should not filter out disabled extension instances', () => { const a = makeExt('a', 'disabled'); @@ -78,9 +93,8 @@ describe('resolveAppNodeSpecs', () => { }); it('should override attachment points', () => { - const a = makeExt('a'); const b = makeExt('b'); - const pluginA = createPlugin({ id: 'test', extensions: [a] }); + const pluginA = createPlugin({ id: 'test', extensions: [makeExtDef('a')] }); expect( resolveAppNodeSpecs({ features: [pluginA], @@ -94,8 +108,8 @@ describe('resolveAppNodeSpecs', () => { }), ).toEqual([ { - id: 'a', - extension: a, + id: 'test/a', + extension: makeExt('test/a'), attachTo: { id: 'root', input: 'default' }, source: pluginA, disabled: false, @@ -110,31 +124,34 @@ describe('resolveAppNodeSpecs', () => { }); it('should fully override configuration and duplicate', () => { - const a = makeExt('a'); - const b = makeExt('b'); - const plugin = createPlugin({ id: 'test', extensions: [a, b] }); + const a = makeExt('test/a'); + const b = makeExt('test/b'); + const plugin = createPlugin({ + id: 'test', + extensions: [makeExtDef('a'), makeExtDef('b')], + }); expect( resolveAppNodeSpecs({ features: [plugin], builtinExtensions: [], parameters: [ { - id: 'a', + id: 'test/a', config: { foo: { bar: 1 } }, }, { - id: 'b', + id: 'test/b', config: { foo: { bar: 2 } }, }, { - id: 'b', + id: 'test/b', config: { foo: { qux: 3 } }, }, ], }), ).toEqual([ { - id: 'a', + id: 'test/a', extension: a, attachTo: { id: 'root', input: 'default' }, source: plugin, @@ -142,7 +159,7 @@ describe('resolveAppNodeSpecs', () => { disabled: false, }, { - id: 'b', + id: 'test/b', extension: b, attachTo: { id: 'root', input: 'default' }, source: plugin, @@ -187,11 +204,12 @@ describe('resolveAppNodeSpecs', () => { }); it('should apply extension overrides', () => { - const a = makeExt('a'); - const b = makeExt('b'); - const plugin = createPlugin({ id: 'test', extensions: [a, b] }); - const aOverride = makeExt('a', 'enabled', 'other'); - const bOverride = makeExt('b', 'disabled', 'other'); + const plugin = createPlugin({ + id: 'test', + extensions: [makeExtDef('a'), makeExtDef('b')], + }); + const aOverride = makeExt('test/a', 'enabled', 'other'); + const bOverride = makeExt('test/b', 'disabled', 'other'); const cOverride = makeExt('c'); expect( @@ -199,7 +217,11 @@ describe('resolveAppNodeSpecs', () => { features: [ plugin, createExtensionOverrides({ - extensions: [aOverride, bOverride, cOverride], + extensions: [ + makeExtDef('test/a', 'enabled', 'other'), + makeExtDef('test/b', 'disabled', 'other'), + makeExtDef('c'), + ], }), ], builtinExtensions: [], @@ -207,14 +229,14 @@ describe('resolveAppNodeSpecs', () => { }), ).toEqual([ { - id: 'a', + id: 'test/a', extension: aOverride, attachTo: { id: 'other', input: 'default' }, source: plugin, disabled: false, }, { - id: 'b', + id: 'test/b', extension: bOverride, attachTo: { id: 'other', input: 'default' }, source: plugin, @@ -231,39 +253,50 @@ describe('resolveAppNodeSpecs', () => { }); it('should use order from configuration when rather than overrides', () => { - const a = makeExt('a', 'disabled'); - const b = makeExt('b', 'disabled'); - const c = makeExt('c', 'disabled'); - const aOverride = makeExt('c', 'disabled'); - const bOverride = makeExt('b', 'disabled'); - const cOverride = makeExt('a', 'disabled'); - const result = resolveAppNodeSpecs({ features: [ - createPlugin({ id: 'test', extensions: [a, b, c] }), + createPlugin({ + id: 'test', + extensions: [ + makeExtDef('a', 'disabled'), + makeExtDef('b', 'disabled'), + makeExtDef('c', 'disabled'), + ], + }), createExtensionOverrides({ - extensions: [cOverride, bOverride, aOverride], + extensions: [ + makeExtDef('test/c', 'disabled'), + makeExtDef('test/b', 'disabled'), + makeExtDef('test/a', 'disabled'), + ], }), ], builtinExtensions: [], - parameters: ['b', 'c', 'a'].map(id => ({ id, disabled: false })), + parameters: ['test/b', 'test/c', 'test/a'].map(id => ({ + id, + disabled: false, + })), }); - expect(result.map(r => r.extension.id)).toEqual(['b', 'c', 'a']); + expect(result.map(r => r.extension.id)).toEqual([ + 'test/b', + 'test/c', + 'test/a', + ]); }); it('throws an error when a forbidden extension is overridden by a plugin', () => { expect(() => resolveAppNodeSpecs({ features: [ - createPlugin({ id: 'test', extensions: [makeExt('forbidden')] }), + createPlugin({ id: 'test', extensions: [makeExtDef('forbidden')] }), ], builtinExtensions: [], parameters: [], - forbidden: new Set(['forbidden']), + forbidden: new Set(['test/forbidden']), }), ).toThrow( - "It is forbidden to override the following extension(s): 'forbidden', which is done by the following plugin(s): 'test'", + "It is forbidden to override the following extension(s): 'test/forbidden', which is done by the following plugin(s): 'test'", ); }); @@ -271,7 +304,7 @@ describe('resolveAppNodeSpecs', () => { expect(() => resolveAppNodeSpecs({ features: [ - createExtensionOverrides({ extensions: [makeExt('forbidden')] }), + createExtensionOverrides({ extensions: [makeExtDef('forbidden')] }), ], builtinExtensions: [], parameters: [], diff --git a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts index 0a024c0a3f..34ec29b8f7 100644 --- a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts +++ b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts @@ -23,6 +23,8 @@ import { import { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides'; import { ExtensionParameters } from './readAppExtensionsConfig'; import { AppNodeSpec } from '@backstage/frontend-plugin-api'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalBackstagePlugin } from '../../../frontend-plugin-api/src/wiring/createPlugin'; /** @internal */ export function resolveAppNodeSpecs(options: { @@ -42,7 +44,10 @@ export function resolveAppNodeSpecs(options: { ); const pluginExtensions = plugins.flatMap(source => { - return source.extensions.map(extension => ({ ...extension, source })); + return toInternalBackstagePlugin(source).extensions.map(extension => ({ + ...extension, + source, + })); }); const overrideExtensions = overrides.flatMap( override => toInternalExtensionOverrides(override).extensions, diff --git a/packages/frontend-app-api/src/tree/resolveAppTree.test.ts b/packages/frontend-app-api/src/tree/resolveAppTree.test.ts index d84064b26a..4fca671554 100644 --- a/packages/frontend-app-api/src/tree/resolveAppTree.test.ts +++ b/packages/frontend-app-api/src/tree/resolveAppTree.test.ts @@ -16,15 +16,17 @@ import { createExtension } from '@backstage/frontend-plugin-api'; import { resolveAppTree } from './resolveAppTree'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { resolveExtensionDefinition } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition'; -const extBaseConfig = { - id: 'test', - attachTo: { id: 'nonexistent', input: 'nonexistent' }, - output: {}, - factory: () => ({}), -}; - -const extension = createExtension(extBaseConfig); +const extension = resolveExtensionDefinition( + createExtension({ + name: 'test', + attachTo: { id: 'nonexistent', input: 'nonexistent' }, + output: {}, + factory: () => ({}), + }), +); const baseSpec = { extension, diff --git a/packages/frontend-app-api/src/wiring/InternalAppContext.ts b/packages/frontend-app-api/src/wiring/InternalAppContext.ts new file mode 100644 index 0000000000..81264bd81b --- /dev/null +++ b/packages/frontend-app-api/src/wiring/InternalAppContext.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 { createContext } from 'react'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy'; +import { BackstageRouteObject } from '../routing/types'; + +export const InternalAppContext = createContext< + | undefined + | { + appIdentityProxy: AppIdentityProxy; + routeObjects: BackstageRouteObject[]; + } +>(undefined); diff --git a/packages/frontend-app-api/src/wiring/createApp.test.tsx b/packages/frontend-app-api/src/wiring/createApp.test.tsx index 80d9f846f0..32773de7e1 100644 --- a/packages/frontend-app-api/src/wiring/createApp.test.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.test.tsx @@ -17,6 +17,9 @@ import { AppTreeApi, appTreeApiRef, + coreExtensionData, + createExtension, + createExtensionOverrides, createPageExtension, createPlugin, createThemeExtension, @@ -25,7 +28,7 @@ import { screen, waitFor } from '@testing-library/react'; import { createApp } from './createApp'; import { MockConfigApi, renderWithEffects } from '@backstage/test-utils'; import React from 'react'; -import { useApi } from '@backstage/core-plugin-api'; +import { featureFlagsApiRef, useApi } from '@backstage/core-plugin-api'; describe('createApp', () => { it('should allow themes to be installed', async () => { @@ -33,7 +36,10 @@ describe('createApp', () => { configLoader: async () => new MockConfigApi({ app: { - extensions: [{ 'themes.light': false }, { 'themes.dark': false }], + extensions: [ + { 'theme:app/light': false }, + { 'theme:app/dark': false }, + ], }, }), features: [ @@ -65,7 +71,6 @@ describe('createApp', () => { id: duplicatedFeatureId, extensions: [ createPageExtension({ - id: 'test.page.first', defaultPath: '/', loader: async () =>
First Page
, }), @@ -75,7 +80,6 @@ describe('createApp', () => { id: duplicatedFeatureId, extensions: [ createPageExtension({ - id: 'test.page.last', defaultPath: '/', loader: async () =>
Last Page
, }), @@ -94,6 +98,59 @@ describe('createApp', () => { ); }); + it('should register feature flags', async () => { + const app = createApp({ + configLoader: async () => new MockConfigApi({}), + features: [ + createPlugin({ + id: 'test', + featureFlags: [{ name: 'test-1' }], + extensions: [ + createExtension({ + name: 'first', + attachTo: { id: 'core', input: 'root' }, + output: { element: coreExtensionData.reactElement }, + factory() { + const Component = () => { + const flagsApi = useApi(featureFlagsApiRef); + return ( +
+ Flags:{' '} + {flagsApi + .getRegisteredFlags() + .map(flag => `${flag.name} from '${flag.pluginId}'`) + .join(', ')} +
+ ); + }; + return { element: }; + }, + }), + ], + }), + createExtensionOverrides({ + featureFlags: [{ name: 'test-2' }], + extensions: [ + createExtension({ + namespace: 'core', + name: 'router', + attachTo: { id: 'core', input: 'root' }, + disabled: true, + output: {}, + factory: () => ({}), + }), + ], + }), + ], + }); + + await renderWithEffects(app.createRoot()); + + await expect( + screen.findByText("Flags: test-1 from 'test', test-2 from ''"), + ).resolves.toBeInTheDocument(); + }); + it('should make the app structure available through the AppTreeApi', async () => { let appTreeApi: AppTreeApi | undefined = undefined; @@ -104,7 +161,6 @@ describe('createApp', () => { id: 'my-plugin', extensions: [ createPageExtension({ - id: 'plugin.my-plugin.page', defaultPath: '/', loader: async () => { const Component = () => { @@ -127,22 +183,31 @@ describe('createApp', () => { expect(String(tree.root)).toMatchInlineSnapshot(` " root [ - - content [ - - routes [ - + + children [ + + content [ + + routes [ + + ] + ] - + nav [ + + ] + ] - nav [ - - ] - + + ] + components [ + + + ] themes [ - - + + ] " `); diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index ca0e1d60d1..c1c1e3e283 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -20,7 +20,10 @@ import { AppTree, appTreeApiRef, BackstagePlugin, + ComponentRef, + componentsApiRef, coreExtensionData, + createTranslationExtension, ExtensionDataRef, ExtensionOverrides, RouteRef, @@ -33,13 +36,10 @@ import { CoreNav } from '../extensions/CoreNav'; import { AnyApiFactory, ApiHolder, - AppComponents, - AppContext, appThemeApiRef, ConfigApi, configApiRef, IconComponent, - BackstagePlugin as LegacyBackstagePlugin, featureFlagsApiRef, attachComponentData, identityApiRef, @@ -59,8 +59,6 @@ import { AppThemeProvider } from '../../../core-app-api/src/app/AppThemeProvider // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { AppContextProvider } from '../../../core-app-api/src/app/AppContext'; -// eslint-disable-next-line @backstage/no-relative-monorepo-imports import { LocalStorageFeatureFlags } from '../../../core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { defaultConfigLoaderSync } from '../../../core-app-api/src/app/defaultConfigLoader'; @@ -71,16 +69,13 @@ import { AppLanguageSelector } from '../../../core-app-api/src/apis/implementati // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { I18nextTranslationApi } from '../../../core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { - apis as defaultApis, - components as defaultComponents, - icons as defaultIcons, -} from '../../../app-defaults/src/defaults'; -import { BrowserRouter, Route } from 'react-router-dom'; +import { resolveExtensionDefinition } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { apis as defaultApis } from '../../../app-defaults/src/defaults'; +import { Route } from 'react-router-dom'; import { SidebarItem } from '@backstage/core-components'; import { DarkTheme, LightTheme } from '../extensions/themes'; import { extractRouteInfoFromAppNode } from '../routing/extractRouteInfoFromAppNode'; -import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; import { appLanguageApiRef, translationApiRef, @@ -90,16 +85,32 @@ import { RoutingProvider } from '../routing/RoutingProvider'; import { resolveRouteBindings } from '../routing/resolveRouteBindings'; import { collectRouteIds } from '../routing/collectRouteIds'; import { createAppTree } from '../tree'; +import { + DefaultProgressComponent, + DefaultErrorBoundaryComponent, + DefaultNotFoundErrorPageComponent, +} from '../extensions/components'; import { AppNode } from '@backstage/frontend-plugin-api'; +import { InternalAppContext } from './InternalAppContext'; +import { CoreRouter } from '../extensions/CoreRouter'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalBackstagePlugin } from '../../../frontend-plugin-api/src/wiring/createPlugin'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides'; +import { DefaultComponentsApi } from '../apis/implementations/ComponentsApi'; -const builtinExtensions = [ +export const builtinExtensions = [ Core, + CoreRouter, CoreRoutes, CoreNav, CoreLayout, + DefaultProgressComponent, + DefaultErrorBoundaryComponent, + DefaultNotFoundErrorPageComponent, LightTheme, DarkTheme, -]; +].map(def => resolveExtensionDefinition(def)); /** @public */ export interface ExtensionTreeNode { @@ -154,7 +165,7 @@ export function createExtensionTree(options: { ); }, getRootRoutes(): JSX.Element[] { - return this.getExtensionAttachments('core.routes', 'routes').map(node => { + return this.getExtensionAttachments('core/routes', 'routes').map(node => { const path = node.getData(coreExtensionData.routePath); const element = node.getData(coreExtensionData.reactElement); const routeRef = node.getData(coreExtensionData.routeRef); @@ -181,7 +192,7 @@ export function createExtensionTree(options: { ); }; - return this.getExtensionAttachments('core.nav', 'items') + return this.getExtensionAttachments('core/nav', 'items') .map((node, index) => { const target = node.getData(coreExtensionData.navTarget); if (!target) { @@ -244,49 +255,18 @@ export function createApp(options?: { const discoveredFeatures = getAvailableFeatures(config); const loadedFeatures = (await options?.featureLoader?.({ config })) ?? []; - const allFeatures = deduplicateFeatures([ - ...discoveredFeatures, - ...loadedFeatures, - ...(options?.features ?? []), - ]); - const tree = createAppTree({ - features: allFeatures, - builtinExtensions, + const app = createSpecializedApp({ config, - }); + features: [ + ...discoveredFeatures, + ...loadedFeatures, + ...(options?.features ?? []), + ], + bindRoutes: options?.bindRoutes, + }).createRoot(); - const appContext = createLegacyAppContext( - allFeatures.filter( - (f): f is BackstagePlugin => f.$$type === '@backstage/BackstagePlugin', - ), - ); - - const routeIds = collectRouteIds(allFeatures); - - const App = () => ( - - - - - {/* TODO: set base path using the logic from AppRouter */} - - {tree.root.instance!.getData(coreExtensionData.reactElement)} - - - - - - ); - - return { default: App }; + return { default: () => app }; } return { @@ -301,65 +281,85 @@ export function createApp(options?: { }; } -// Make sure that we only convert each new plugin instance to its legacy equivalent once -const legacyPluginStore = getOrCreateGlobalSingleton( - 'legacy-plugin-compatibility-store', - () => new WeakMap(), -); +/** + * Synchronous version of {@link createApp}, expecting all features and + * config to have been loaded already. + * @public + */ +export function createSpecializedApp(options?: { + features?: (BackstagePlugin | ExtensionOverrides)[]; + config?: ConfigApi; + bindRoutes?(context: { bind: AppRouteBinder }): void; +}): { createRoot(): JSX.Element } { + const { + features: duplicatedFeatures = [], + config = new ConfigReader({}, 'empty-config'), + } = options ?? {}; -export function toLegacyPlugin(plugin: BackstagePlugin): LegacyBackstagePlugin { - let legacy = legacyPluginStore.get(plugin); - if (legacy) { - return legacy; + const features = deduplicateFeatures(duplicatedFeatures); + + const tree = createAppTree({ + features, + builtinExtensions, + config, + }); + + const appIdentityProxy = new AppIdentityProxy(); + const apiHolder = createApiHolder(tree, config, appIdentityProxy); + + const featureFlagApi = apiHolder.get(featureFlagsApiRef); + if (featureFlagApi) { + for (const feature of features) { + if (feature.$$type === '@backstage/BackstagePlugin') { + toInternalBackstagePlugin(feature).featureFlags.forEach(flag => + featureFlagApi.registerFlag({ + name: flag.name, + pluginId: feature.id, + }), + ); + } + if (feature.$$type === '@backstage/ExtensionOverrides') { + toInternalExtensionOverrides(feature).featureFlags.forEach(flag => + featureFlagApi.registerFlag({ name: flag.name, pluginId: '' }), + ); + } + } } - const errorMsg = 'Not implemented in legacy plugin compatibility layer'; - const notImplemented = () => { - throw new Error(errorMsg); - }; + const routeInfo = extractRouteInfoFromAppNode(tree.root); + const routeBindings = resolveRouteBindings( + options?.bindRoutes, + config, + collectRouteIds(features), + ); + const rootEl = tree.root.instance!.getData(coreExtensionData.reactElement); - legacy = { - getId(): string { - return plugin.id; - }, - get routes() { - return {}; - }, - get externalRoutes() { - return {}; - }, - getApis: notImplemented, - getFeatureFlags: notImplemented, - provide: notImplemented, - }; + const App = () => ( + + + + + {rootEl} + + + + + ); - legacyPluginStore.set(plugin, legacy); - return legacy; -} - -function createLegacyAppContext(plugins: BackstagePlugin[]): AppContext { return { - getPlugins(): LegacyBackstagePlugin[] { - return plugins.map(toLegacyPlugin); - }, - - getSystemIcon(key: string): IconComponent | undefined { - return key in defaultIcons - ? defaultIcons[key as keyof typeof defaultIcons] - : undefined; - }, - - getSystemIcons(): Record { - return defaultIcons; - }, - - getComponents(): AppComponents { - return defaultComponents; + createRoot() { + return ; }, }; } -function createApiHolder(tree: AppTree, configApi: ConfigApi): ApiHolder { +function createApiHolder( + tree: AppTree, + configApi: ConfigApi, + appIdentityProxy: AppIdentityProxy, +): ApiHolder { const factoryRegistry = new ApiFactoryRegistry(); const pluginApis = @@ -374,6 +374,16 @@ function createApiHolder(tree: AppTree, configApi: ConfigApi): ApiHolder { ?.map(e => e.instance?.getData(coreExtensionData.theme)) .filter((x): x is AppTheme => !!x) ?? []; + const translationResources = + tree.root.edges.attachments + .get('translations') + ?.map(e => + e.instance?.getData(createTranslationExtension.translationDataRef), + ) + .filter( + (x): x is typeof createTranslationExtension.translationDataRef.T => !!x, + ) ?? []; + for (const factory of [...defaultApis, ...pluginApis]) { factoryRegistry.register('default', factory); } @@ -388,33 +398,7 @@ function createApiHolder(tree: AppTree, configApi: ConfigApi): ApiHolder { factoryRegistry.register('static', { api: identityApiRef, deps: {}, - factory: () => { - const appIdentityProxy = new AppIdentityProxy(); - // TODO: Remove this when sign-in page is migrated - appIdentityProxy.setTarget( - { - getUserId: () => 'guest', - getIdToken: async () => undefined, - getProfile: () => ({ - email: 'guest@example.com', - displayName: 'Guest', - }), - getProfileInfo: async () => ({ - email: 'guest@example.com', - displayName: 'Guest', - }), - getBackstageIdentity: async () => ({ - type: 'user', - userEntityRef: 'user:default/guest', - ownershipEntityRefs: ['user:default/guest'], - }), - getCredentials: async () => ({}), - signOut: async () => {}, - }, - { signOutTargetUrl: '/' }, - ); - return appIdentityProxy; - }, + factory: () => appIdentityProxy, }); factoryRegistry.register('static', { @@ -425,6 +409,24 @@ function createApiHolder(tree: AppTree, configApi: ConfigApi): ApiHolder { }), }); + const componentsExtensions = + tree.root.edges.attachments + .get('components') + ?.map(e => e.instance?.getData(coreExtensionData.component)) + .filter(x => !!x) ?? []; + + const componentsMap = componentsExtensions.reduce( + (components, component) => + component ? components.set(component.ref, component?.impl) : components, + new Map, any>(), + ); + + factoryRegistry.register('static', { + api: componentsApiRef, + deps: {}, + factory: () => new DefaultComponentsApi(componentsMap), + }); + factoryRegistry.register('static', { api: appThemeApiRef, deps: {}, @@ -438,15 +440,6 @@ function createApiHolder(tree: AppTree, configApi: ConfigApi): ApiHolder { factory: () => AppLanguageSelector.createWithStorage(), }); - factoryRegistry.register('default', { - api: translationApiRef, - deps: { languageApi: appLanguageApiRef }, - factory: ({ languageApi }) => - I18nextTranslationApi.create({ - languageApi, - }), - }); - factoryRegistry.register('static', { api: configApiRef, deps: {}, @@ -459,12 +452,13 @@ function createApiHolder(tree: AppTree, configApi: ConfigApi): ApiHolder { factory: () => AppLanguageSelector.createWithStorage(), }); - factoryRegistry.register('default', { + factoryRegistry.register('static', { api: translationApiRef, deps: { languageApi: appLanguageApiRef }, factory: ({ languageApi }) => I18nextTranslationApi.create({ languageApi, + resources: translationResources, }), }); diff --git a/packages/frontend-app-api/src/wiring/index.ts b/packages/frontend-app-api/src/wiring/index.ts index dc1ba3bc13..412e643523 100644 --- a/packages/frontend-app-api/src/wiring/index.ts +++ b/packages/frontend-app-api/src/wiring/index.ts @@ -16,6 +16,7 @@ export { createApp, + createSpecializedApp, createExtensionTree, type ExtensionTreeNode, type ExtensionTree, diff --git a/packages/frontend-plugin-api/CHANGELOG.md b/packages/frontend-plugin-api/CHANGELOG.md index 96407a7b37..2187b17aab 100644 --- a/packages/frontend-plugin-api/CHANGELOG.md +++ b/packages/frontend-plugin-api/CHANGELOG.md @@ -1,5 +1,57 @@ # @backstage/frontend-plugin-api +## 0.4.0-next.2 + +### Minor Changes + +- 8f5d6c1: Extension inputs are now wrapped into an additional object when passed to the extension factory, with the previous values being available at the `output` property. The `ExtensionInputValues` type has also been replaced by `ResolvedExtensionInputs`. +- 8837a96: **BREAKING**: This version changes how extensions are created and how their IDs are determined. The `createExtension` function now accepts `kind`, `namespace` and `name` instead of `id`. All of the new options are optional, and are used to construct the final extension ID. By convention extension creators should set the `kind` to match their own name, for example `createNavItemExtension` sets the kind `nav-item`. + + The `createExtension` function as well as all extension creators now also return an `ExtensionDefinition` rather than an `Extension`, which in turn needs to be passed to `createPlugin` or `createExtensionOverrides` to be used. + +### Patch Changes + +- b7adf24: Update alpha component ref type to be more specific than any, delete boot page component and use new plugin type for error boundary component extensions. +- 73246ec: Added translation APIs as well as `createTranslationExtension`. +- cb4197a: Forward ` node`` instead of `extensionId` to resolved extension inputs. +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## 0.4.0-next.1 + +### Minor Changes + +- a5a04739e1: The extension `factory` function now longer receives `id` or `source`, but instead now provides the extension's `AppNode` as `node`. The `ExtensionBoundary` component has also been updated to receive a `node` prop rather than `id` and `source`. + +### Patch Changes + +- 5eb6b8a7bc: Added the nav logo extension for customization of sidebar logo +- 1f12fb762c: Create factories for overriding default core components extensions. +- 59709286b3: Add feature flags to plugins and extension overrides. +- e539735435: Added `createSignInPageExtension`. +- f27ee7d937: Migrate analytics api and context files. +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + +## 0.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + ## 0.3.0 ### Minor Changes diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index 794da9617b..6bd3000867 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -5,19 +5,146 @@ ```ts /// +import { AlertApi } from '@backstage/core-plugin-api'; +import { alertApiRef } from '@backstage/core-plugin-api'; +import { AlertMessage } from '@backstage/core-plugin-api'; import { AnyApiFactory } from '@backstage/core-plugin-api'; import { AnyApiRef } from '@backstage/core-plugin-api'; +import { ApiFactory } from '@backstage/core-plugin-api'; +import { ApiHolder } from '@backstage/core-plugin-api'; import { ApiRef } from '@backstage/core-plugin-api'; +import { ApiRefConfig } from '@backstage/core-plugin-api'; import { AppTheme } from '@backstage/core-plugin-api'; -import { IconComponent } from '@backstage/core-plugin-api'; +import { AppThemeApi } from '@backstage/core-plugin-api'; +import { appThemeApiRef } from '@backstage/core-plugin-api'; +import { atlassianAuthApiRef } from '@backstage/core-plugin-api'; +import { AuthProviderInfo } from '@backstage/core-plugin-api'; +import { AuthRequestOptions } from '@backstage/core-plugin-api'; +import { BackstageIdentityApi } from '@backstage/core-plugin-api'; +import { BackstageIdentityResponse } from '@backstage/core-plugin-api'; +import { BackstageUserIdentity } from '@backstage/core-plugin-api'; +import { bitbucketAuthApiRef } from '@backstage/core-plugin-api'; +import { bitbucketServerAuthApiRef } from '@backstage/core-plugin-api'; +import { ComponentType } from 'react'; +import { ConfigApi } from '@backstage/core-plugin-api'; +import { configApiRef } from '@backstage/core-plugin-api'; +import { createApiFactory } from '@backstage/core-plugin-api'; +import { createApiRef } from '@backstage/core-plugin-api'; +import { createTranslationMessages } from '@backstage/core-plugin-api/alpha'; +import { createTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { createTranslationResource } from '@backstage/core-plugin-api/alpha'; +import { DiscoveryApi } from '@backstage/core-plugin-api'; +import { discoveryApiRef } from '@backstage/core-plugin-api'; +import { ErrorApi } from '@backstage/core-plugin-api'; +import { ErrorApiError } from '@backstage/core-plugin-api'; +import { ErrorApiErrorContext } from '@backstage/core-plugin-api'; +import { errorApiRef } from '@backstage/core-plugin-api'; +import { FeatureFlag } from '@backstage/core-plugin-api'; +import { FeatureFlagsApi } from '@backstage/core-plugin-api'; +import { featureFlagsApiRef } from '@backstage/core-plugin-api'; +import { FeatureFlagsSaveOptions } from '@backstage/core-plugin-api'; +import { FeatureFlagState } from '@backstage/core-plugin-api'; +import { FetchApi } from '@backstage/core-plugin-api'; +import { fetchApiRef } from '@backstage/core-plugin-api'; +import { githubAuthApiRef } from '@backstage/core-plugin-api'; +import { gitlabAuthApiRef } from '@backstage/core-plugin-api'; +import { googleAuthApiRef } from '@backstage/core-plugin-api'; +import { IconComponent as IconComponent_2 } from '@backstage/core-plugin-api'; +import { IdentityApi } from '@backstage/core-plugin-api'; +import { identityApiRef } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; import { JSX as JSX_2 } from 'react'; +import { microsoftAuthApiRef } from '@backstage/core-plugin-api'; +import { OAuthApi } from '@backstage/core-plugin-api'; +import { OAuthRequestApi } from '@backstage/core-plugin-api'; +import { oauthRequestApiRef } from '@backstage/core-plugin-api'; +import { OAuthRequester } from '@backstage/core-plugin-api'; +import { OAuthRequesterOptions } from '@backstage/core-plugin-api'; +import { OAuthScope } from '@backstage/core-plugin-api'; +import { oktaAuthApiRef } from '@backstage/core-plugin-api'; +import { oneloginAuthApiRef } from '@backstage/core-plugin-api'; +import { OpenIdConnectApi } from '@backstage/core-plugin-api'; +import { PendingOAuthRequest } from '@backstage/core-plugin-api'; +import { ProfileInfo } from '@backstage/core-plugin-api'; +import { ProfileInfoApi } from '@backstage/core-plugin-api'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; +import { SessionApi } from '@backstage/core-plugin-api'; +import { SessionState } from '@backstage/core-plugin-api'; +import { SignInPageProps } from '@backstage/core-plugin-api'; +import { StorageApi } from '@backstage/core-plugin-api'; +import { storageApiRef } from '@backstage/core-plugin-api'; +import { StorageValueSnapshot } from '@backstage/core-plugin-api'; +import { TranslationMessages } from '@backstage/core-plugin-api/alpha'; +import { TranslationMessagesOptions } from '@backstage/core-plugin-api/alpha'; +import { TranslationRef } from '@backstage/core-plugin-api/alpha'; +import { TranslationRefOptions } from '@backstage/core-plugin-api/alpha'; +import { TranslationResource } from '@backstage/core-plugin-api/alpha'; +import { TranslationResourceOptions } from '@backstage/core-plugin-api/alpha'; +import { TypesToApiRefs } from '@backstage/core-plugin-api'; +import { useApi } from '@backstage/core-plugin-api'; +import { useApiHolder } from '@backstage/core-plugin-api'; +import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { withApis } from '@backstage/core-plugin-api'; import { z } from 'zod'; import { ZodSchema } from 'zod'; import { ZodTypeDef } from 'zod'; +export { AlertApi }; + +export { alertApiRef }; + +export { AlertMessage }; + +// @public +export type AnalyticsApi = { + captureEvent(event: AnalyticsEvent): void; +}; + +// @public +export const analyticsApiRef: ApiRef; + +// @public +export const AnalyticsContext: (options: { + attributes: Partial; + children: ReactNode; +}) => React_2.JSX.Element; + +// @public +export type AnalyticsContextValue = CommonAnalyticsContext & { + [param in string]: string | boolean | number | undefined; +}; + +// @public +export type AnalyticsEvent = { + action: string; + subject: string; + value?: number; + attributes?: AnalyticsEventAttributes; + context: AnalyticsContextValue; +}; + +// @public +export type AnalyticsEventAttributes = { + [attribute in string]: string | boolean | number; +}; + +// @public +export type AnalyticsTracker = { + captureEvent: ( + action: string, + subject: string, + options?: { + value?: number; + attributes?: AnalyticsEventAttributes; + }, + ) => void; +}; + +export { AnyApiFactory }; + +export { AnyApiRef }; + // @public (undocumented) export type AnyExtensionDataMap = { [name in string]: ExtensionDataRef< @@ -56,6 +183,14 @@ export type AnyRoutes = { [name in string]: RouteRef; }; +export { ApiFactory }; + +export { ApiHolder }; + +export { ApiRef }; + +export { ApiRefConfig }; + // @public export interface AppNode { readonly edges: AppNodeEdges; @@ -99,6 +234,12 @@ export interface AppNodeSpec { readonly source?: BackstagePlugin; } +export { AppTheme }; + +export { AppThemeApi }; + +export { appThemeApiRef }; + // @public export interface AppTree { readonly nodes: ReadonlyMap; @@ -116,23 +257,62 @@ export interface AppTreeApi { // @public export const appTreeApiRef: ApiRef; +export { atlassianAuthApiRef }; + +export { AuthProviderInfo }; + +export { AuthRequestOptions }; + +export { BackstageIdentityApi }; + +export { BackstageIdentityResponse }; + // @public (undocumented) export interface BackstagePlugin< Routes extends AnyRoutes = AnyRoutes, ExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, > { // (undocumented) - $$type: '@backstage/BackstagePlugin'; + readonly $$type: '@backstage/BackstagePlugin'; // (undocumented) - extensions: Extension[]; + readonly externalRoutes: ExternalRoutes; // (undocumented) - externalRoutes: ExternalRoutes; + readonly id: string; // (undocumented) - id: string; - // (undocumented) - routes: Routes; + readonly routes: Routes; } +export { BackstageUserIdentity }; + +export { bitbucketAuthApiRef }; + +export { bitbucketServerAuthApiRef }; + +// @public +export type CommonAnalyticsContext = { + pluginId: string; + extensionId: string; +}; + +// @public (undocumented) +export type ComponentRef = { + id: string; + T: T; +}; + +// @public +export interface ComponentsApi { + // (undocumented) + getComponent(ref: ComponentRef): ComponentType; +} + +// @public +export const componentsApiRef: ApiRef; + +export { ConfigApi }; + +export { configApiRef }; + // @public (undocumented) export interface ConfigurableExtensionDataRef< TData, @@ -149,6 +329,20 @@ export interface ConfigurableExtensionDataRef< >; } +// @public (undocumented) +export const coreComponentRefs: { + progress: ComponentRef; + notFoundErrorPage: ComponentRef; + errorBoundaryFallback: ComponentRef; +}; + +// @public (undocumented) +export type CoreErrorBoundaryFallbackProps = { + plugin?: BackstagePlugin; + error: Error; + resetError: () => void; +}; + // @public (undocumented) export const coreExtensionData: { reactElement: ConfigurableExtensionDataRef; @@ -157,8 +351,24 @@ export const coreExtensionData: { routeRef: ConfigurableExtensionDataRef, {}>; navTarget: ConfigurableExtensionDataRef; theme: ConfigurableExtensionDataRef; + logoElements: ConfigurableExtensionDataRef; + component: ConfigurableExtensionDataRef< + { + ref: ComponentRef; + impl: ComponentType; + }, + {} + >; }; +// @public (undocumented) +export type CoreNotFoundErrorPageProps = { + children?: ReactNode; +}; + +// @public (undocumented) +export type CoreProgressProps = {}; + // @public (undocumented) export function createApiExtension< TConfig extends {}, @@ -169,7 +379,7 @@ export function createApiExtension< api: AnyApiRef; factory: (options: { config: TConfig; - inputs: Expand>; + inputs: Expand>; }) => AnyApiFactory; } | { @@ -179,7 +389,37 @@ export function createApiExtension< configSchema?: PortableSchema; inputs?: TInputs; }, -): Extension; +): ExtensionDefinition; + +export { createApiFactory }; + +export { createApiRef }; + +// @public (undocumented) +export function createComponentExtension< + TProps extends {}, + TConfig extends {}, + TInputs extends AnyExtensionInputMap, +>(options: { + ref: ComponentRef; + name?: string; + disabled?: boolean; + inputs?: TInputs; + configSchema?: PortableSchema; + component: + | { + lazy: (values: { + config: TConfig; + inputs: Expand>; + }) => Promise>; + } + | { + sync: (values: { + config: TConfig; + inputs: Expand>; + }) => ComponentType; + }; +}): ExtensionDefinition; // @public (undocumented) export function createExtension< @@ -188,7 +428,7 @@ export function createExtension< TConfig = never, >( options: CreateExtensionOptions, -): Extension; +): ExtensionDefinition; // @public (undocumented) export function createExtensionDataRef( @@ -230,15 +470,19 @@ export interface CreateExtensionOptions< disabled?: boolean; // (undocumented) factory(options: { - source?: BackstagePlugin; + node: AppNode; config: TConfig; - inputs: Expand>; + inputs: Expand>; }): Expand>; // (undocumented) - id: string; - // (undocumented) inputs?: TInputs; // (undocumented) + kind?: string; + // (undocumented) + name?: string; + // (undocumented) + namespace?: string; + // (undocumented) output: TOutput; } @@ -274,11 +518,12 @@ export function createExternalRouteRef< // @public export function createNavItemExtension(options: { - id: string; + namespace?: string; + name?: string; routeRef: RouteRef; title: string; - icon: IconComponent; -}): Extension<{ + icon: IconComponent_2; +}): ExtensionDefinition<{ title: string; }>; @@ -297,7 +542,8 @@ export function createPageExtension< configSchema: PortableSchema; } ) & { - id: string; + namespace?: string; + name?: string; attachTo?: { id: string; input: string; @@ -307,10 +553,10 @@ export function createPageExtension< routeRef?: RouteRef; loader: (options: { config: TConfig; - inputs: Expand>; + inputs: Expand>; }) => Promise; }, -): Extension; +): ExtensionDefinition; // @public (undocumented) export function createPlugin< @@ -345,6 +591,26 @@ export function createSchemaFromZod( schemaCreator: (zImpl: typeof z) => ZodSchema, ): PortableSchema; +// @public (undocumented) +export function createSignInPageExtension< + TConfig extends {}, + TInputs extends AnyExtensionInputMap, +>(options: { + namespace?: string; + name?: string; + attachTo?: { + id: string; + input: string; + }; + configSchema?: PortableSchema; + disabled?: boolean; + inputs?: TInputs; + loader: (options: { + config: TConfig; + inputs: Expand>; + }) => Promise>; +}): ExtensionDefinition; + // @public export function createSubRouteRef< Path extends string, @@ -355,7 +621,49 @@ export function createSubRouteRef< }): MakeSubRouteRef, ParentParams>; // @public (undocumented) -export function createThemeExtension(theme: AppTheme): Extension; +export function createThemeExtension( + theme: AppTheme, +): ExtensionDefinition; + +// @public (undocumented) +export function createTranslationExtension(options: { + name?: string; + resource: TranslationResource | TranslationMessages; +}): ExtensionDefinition; + +// @public (undocumented) +export namespace createTranslationExtension { + const // (undocumented) + translationDataRef: ConfigurableExtensionDataRef< + | TranslationResource + | TranslationMessages< + string, + { + [x: string]: string; + }, + boolean + >, + {} + >; +} + +export { createTranslationMessages }; + +export { createTranslationRef }; + +export { createTranslationResource }; + +export { DiscoveryApi }; + +export { discoveryApiRef }; + +export { ErrorApi }; + +export { ErrorApiError }; + +export { ErrorApiErrorContext }; + +export { errorApiRef }; // @public (undocumented) export interface Extension { @@ -372,12 +680,9 @@ export interface Extension { disabled: boolean; // (undocumented) factory(options: { - source?: BackstagePlugin; + node: AppNode; config: TConfig; - inputs: Record< - string, - undefined | Record | Array> - >; + inputs: ResolvedExtensionInputs; }): ExtensionDataValues; // (undocumented) id: string; @@ -397,11 +702,9 @@ export interface ExtensionBoundaryProps { // (undocumented) children: ReactNode; // (undocumented) - id: string; + node: AppNode; // (undocumented) routable?: boolean; - // (undocumented) - source?: BackstagePlugin; } // @public (undocumented) @@ -432,6 +735,37 @@ export type ExtensionDataValues = { : never]?: TExtensionData[DataName]['T']; }; +// @public (undocumented) +export interface ExtensionDefinition { + // (undocumented) + $$type: '@backstage/ExtensionDefinition'; + // (undocumented) + attachTo: { + id: string; + input: string; + }; + // (undocumented) + configSchema?: PortableSchema; + // (undocumented) + disabled: boolean; + // (undocumented) + factory(options: { + node: AppNode; + config: TConfig; + inputs: ResolvedExtensionInputs; + }): ExtensionDataValues; + // (undocumented) + inputs: AnyExtensionInputMap; + // (undocumented) + kind?: string; + // (undocumented) + name?: string; + // (undocumented) + namespace?: string; + // (undocumented) + output: AnyExtensionDataMap; +} + // @public (undocumented) export interface ExtensionInput< TExtensionData extends AnyExtensionDataMap, @@ -448,31 +782,18 @@ export interface ExtensionInput< extensionData: TExtensionData; } -// @public -export type ExtensionInputValues< - TInputs extends { - [name in string]: ExtensionInput; - }, -> = { - [InputName in keyof TInputs]: false extends TInputs[InputName]['config']['singleton'] - ? Array>> - : false extends TInputs[InputName]['config']['optional'] - ? Expand> - : Expand< - ExtensionDataValues | undefined - >; -}; - // @public (undocumented) export interface ExtensionOverrides { // (undocumented) - $$type: '@backstage/ExtensionOverrides'; + readonly $$type: '@backstage/ExtensionOverrides'; } // @public (undocumented) export interface ExtensionOverridesOptions { // (undocumented) - extensions: Extension[]; + extensions: ExtensionDefinition[]; + // (undocumented) + featureFlags?: FeatureFlagConfig[]; } // @public @@ -488,23 +809,92 @@ export interface ExternalRouteRef< readonly T: TParams; } +export { FeatureFlag }; + +// @public +export type FeatureFlagConfig = { + name: string; +}; + +export { FeatureFlagsApi }; + +export { featureFlagsApiRef }; + +export { FeatureFlagsSaveOptions }; + +export { FeatureFlagState }; + +export { FetchApi }; + +export { fetchApiRef }; + +export { githubAuthApiRef }; + +export { gitlabAuthApiRef }; + +export { googleAuthApiRef }; + +// @public +export type IconComponent = ComponentType< + | { + fontSize?: 'large' | 'small' | 'default' | 'inherit'; + } + | { + fontSize?: 'medium' | 'large' | 'small' | 'inherit'; + } +>; + +export { IdentityApi }; + +export { identityApiRef }; + +// @public (undocumented) +export type LogoElements = { + logoIcon?: JSX_2.Element; + logoFull?: JSX_2.Element; +}; + +export { microsoftAuthApiRef }; + // @public (undocumented) export type NavTarget = { title: string; - icon: IconComponent; + icon: IconComponent_2; routeRef: RouteRef; }; +export { OAuthApi }; + +export { OAuthRequestApi }; + +export { oauthRequestApiRef }; + +export { OAuthRequester }; + +export { OAuthRequesterOptions }; + +export { OAuthScope }; + +export { oktaAuthApiRef }; + +export { oneloginAuthApiRef }; + +export { OpenIdConnectApi }; + +export { PendingOAuthRequest }; + // @public (undocumented) export interface PluginOptions< Routes extends AnyRoutes, ExternalRoutes extends AnyExternalRoutes, > { // (undocumented) - extensions?: Extension[]; + extensions?: ExtensionDefinition[]; // (undocumented) externalRoutes?: ExternalRoutes; // (undocumented) + featureFlags?: FeatureFlagConfig[]; + // (undocumented) id: string; // (undocumented) routes?: Routes; @@ -516,6 +906,32 @@ export type PortableSchema = { schema: JsonObject; }; +export { ProfileInfo }; + +export { ProfileInfoApi }; + +// @public +export type ResolvedExtensionInput = + { + node: AppNode; + output: ExtensionDataValues; + }; + +// @public +export type ResolvedExtensionInputs< + TInputs extends { + [name in string]: ExtensionInput; + }, +> = { + [InputName in keyof TInputs]: false extends TInputs[InputName]['config']['singleton'] + ? Array>> + : false extends TInputs[InputName]['config']['optional'] + ? Expand> + : Expand< + ResolvedExtensionInput | undefined + >; +}; + // @public export type RouteFunc = ( ...[params]: TParams extends undefined @@ -533,6 +949,16 @@ export interface RouteRef< readonly T: TParams; } +export { SessionApi }; + +export { SessionState }; + +export { StorageApi }; + +export { storageApiRef }; + +export { StorageValueSnapshot }; + // @public export interface SubRouteRef< TParams extends AnyRouteRefParams = AnyRouteRefParams, @@ -545,6 +971,32 @@ export interface SubRouteRef< readonly T: TParams; } +export { TranslationMessages }; + +export { TranslationMessagesOptions }; + +export { TranslationRef }; + +export { TranslationRefOptions }; + +export { TranslationResource }; + +export { TranslationResourceOptions }; + +export { TypesToApiRefs }; + +// @public +export function useAnalytics(): AnalyticsTracker; + +export { useApi }; + +export { useApiHolder }; + +// @public +export function useComponentRef( + ref: ComponentRef, +): ComponentType; + // @public export function useRouteRef< TOptional extends boolean, @@ -562,4 +1014,8 @@ export function useRouteRef( export function useRouteRefParams( _routeRef: RouteRef | SubRouteRef, ): Params; + +export { useTranslationRef }; + +export { withApis }; ``` diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index d739cb8fdd..813351a6a0 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-plugin-api", - "version": "0.3.0", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,6 +25,7 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/frontend-app-api": "workspace:^", + "@backstage/frontend-test-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^14.0.0", @@ -38,6 +39,7 @@ "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "dependencies": { + "@backstage/config": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/types": "workspace:^", diff --git a/packages/frontend-plugin-api/src/analytics/AnalyticsContext.test.tsx b/packages/frontend-plugin-api/src/analytics/AnalyticsContext.test.tsx new file mode 100644 index 0000000000..8e78bdc8c4 --- /dev/null +++ b/packages/frontend-plugin-api/src/analytics/AnalyticsContext.test.tsx @@ -0,0 +1,82 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { renderHook } from '@testing-library/react'; +import { AnalyticsContext, useAnalyticsContext } from './AnalyticsContext'; + +const AnalyticsSpy = () => { + const context = useAnalyticsContext(); + return ( + <> +
{context.pluginId}
+
{context.extensionId}
+
{context.custom}
+ + ); +}; + +describe('AnalyticsContext', () => { + describe('useAnalyticsContext', () => { + it('returns default values', () => { + const { result } = renderHook(() => useAnalyticsContext()); + expect(result.current).toEqual({ + extensionId: 'App', + pluginId: 'root', + }); + }); + }); + + describe('AnalyticsContext', () => { + it('uses default analytics context', () => { + const result = render( + + + , + ); + + expect(result.getByTestId('extension-id')).toHaveTextContent('App'); + expect(result.getByTestId('plugin-id')).toHaveTextContent('root'); + }); + + it('uses provided analytics context', () => { + const result = render( + + + , + ); + + expect(result.getByTestId('extension-id')).toHaveTextContent('App'); + expect(result.getByTestId('plugin-id')).toHaveTextContent('custom'); + }); + + it('uses nested analytics context', () => { + const result = render( + + + + + , + ); + + expect(result.getByTestId('extension-id')).toHaveTextContent( + 'AnalyticsSpy', + ); + expect(result.getByTestId('plugin-id')).toHaveTextContent('custom'); + }); + }); +}); diff --git a/packages/frontend-plugin-api/src/analytics/AnalyticsContext.tsx b/packages/frontend-plugin-api/src/analytics/AnalyticsContext.tsx new file mode 100644 index 0000000000..10ef475803 --- /dev/null +++ b/packages/frontend-plugin-api/src/analytics/AnalyticsContext.tsx @@ -0,0 +1,108 @@ +/* + * 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 { + createVersionedContext, + createVersionedValueMap, +} from '@backstage/version-bridge'; +import React, { ReactNode, useContext } from 'react'; +import { AnalyticsContextValue } from './types'; + +const AnalyticsReactContext = createVersionedContext<{ + 1: AnalyticsContextValue; +}>('analytics-context'); + +/** + * A "private" (to this package) hook that enables context inheritance and a + * way to read Analytics Context values at event capture-time. + * + * @internal + */ +export const useAnalyticsContext = (): AnalyticsContextValue => { + const theContext = useContext(AnalyticsReactContext); + + // Provide a default value if no value exists. + if (theContext === undefined) { + return { + pluginId: 'root', + extensionId: 'App', + }; + } + + // This should probably never happen, but check for it. + const theValue = theContext.atVersion(1); + if (theValue === undefined) { + throw new Error('No context found for version 1.'); + } + + return theValue; +}; + +/** + * Provides components in the child react tree an Analytics Context, ensuring + * all analytics events captured within the context have relevant attributes. + * + * @remarks + * + * Analytics contexts are additive, meaning the context ultimately emitted with + * an event is the combination of all contexts in the parent tree. + * + * @public + */ +export const AnalyticsContext = (options: { + attributes: Partial; + children: ReactNode; +}) => { + const { attributes, children } = options; + + const parentValues = useAnalyticsContext(); + const combinedValue = { + ...parentValues, + ...attributes, + }; + + const versionedCombinedValue = createVersionedValueMap({ 1: combinedValue }); + return ( + + {children} + + ); +}; + +/** + * Returns an HOC wrapping the provided component in an Analytics context with + * the given values. + * + * @param Component - Component to be wrapped with analytics context attributes + * @param values - Analytics context key/value pairs. + * @internal + */ +export function withAnalyticsContext( + Component: React.ComponentType, + values: AnalyticsContextValue, +) { + const ComponentWithAnalyticsContext = (props: TProps) => { + return ( + + + + ); + }; + ComponentWithAnalyticsContext.displayName = `WithAnalyticsContext(${ + Component.displayName || Component.name || 'Component' + })`; + return ComponentWithAnalyticsContext; +} diff --git a/packages/frontend-plugin-api/src/analytics/Tracker.test.ts b/packages/frontend-plugin-api/src/analytics/Tracker.test.ts new file mode 100644 index 0000000000..f1670cf9c4 --- /dev/null +++ b/packages/frontend-plugin-api/src/analytics/Tracker.test.ts @@ -0,0 +1,285 @@ +/* + * 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. + */ + +import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; +import { Tracker, routableExtensionRenderedEvent } from './Tracker'; + +describe('Tracker', () => { + const defaultContext = { + pluginId: 'root', + extensionId: 'App', + }; + const globalEvents = getOrCreateGlobalSingleton( + 'core-plugin-api:analytics-tracker-events', + () => ({}), + ); + const analyticsApiSpy = { + captureEvent: jest.fn(), + }; + let trackerUnderTest: Tracker; + + beforeEach(() => { + // Reset mocks and global state + jest.resetAllMocks(); + globalEvents.mostRecentGatheredNavigation = undefined; + globalEvents.mostRecentRoutableExtensionRender = undefined; + + // Set up a new tracker to test. + trackerUnderTest = new Tracker(analyticsApiSpy); + }); + + it('captures simple event with default context', () => { + trackerUnderTest.captureEvent('click', 'test 1'); + + expect(analyticsApiSpy.captureEvent).toHaveBeenCalledWith( + expect.objectContaining({ + action: 'click', + subject: 'test 1', + context: defaultContext, + }), + ); + }); + + it('captures simple event with set context', () => { + trackerUnderTest.setContext({ + pluginId: 'catalog', + extensionId: 'App', + }); + trackerUnderTest.captureEvent('click', 'test 2', { + value: 2, + attributes: { to: '/page-2' }, + }); + + expect(analyticsApiSpy.captureEvent).toHaveBeenCalledWith( + expect.objectContaining({ + action: 'click', + subject: 'test 2', + value: 2, + attributes: { to: '/page-2' }, + context: { + pluginId: 'catalog', + extensionId: 'App', + }, + }), + ); + }); + + describe('accurate navigate events', () => { + it('never captures _routeNodeType context key on navigate event', () => { + trackerUnderTest.setContext({ + pluginId: 'catalog', + extensionId: 'App', + }); + trackerUnderTest.captureEvent('navigate', '/page-3'); + + const receivedContext = + analyticsApiSpy.captureEvent.mock.calls[0][0].context; + expect(receivedContext.pluginId).toBe('catalog'); + expect(receivedContext._routeNodeType).toBe(undefined); + }); + + it('never immediately captures navigate event with _routeNodeType "gathered"', () => { + trackerUnderTest.setContext({ + ...defaultContext, + }); + trackerUnderTest.captureEvent('navigate', '/page-4'); + + expect(analyticsApiSpy.captureEvent).not.toHaveBeenCalled(); + }); + + it('never captures "routable-extension-rendered" events', () => { + trackerUnderTest.captureEvent(routableExtensionRenderedEvent, ''); + + expect(analyticsApiSpy.captureEvent).not.toHaveBeenCalled(); + }); + + it('captures deferred navigate event with expected context', () => { + // User navigates to a gathered mountpoint with multiple plugins + trackerUnderTest.setContext({ + ...defaultContext, + }); + trackerUnderTest.captureEvent('navigate', '/page-5'); + + // A routable extension is rendered with specific plugin context + trackerUnderTest.setContext({ + pluginId: 'some-plugin', + extensionId: 'App', + }); + trackerUnderTest.captureEvent(routableExtensionRenderedEvent, ''); + + // A non-navigate event + trackerUnderTest.captureEvent('click', 'test 5'); + + expect(analyticsApiSpy.captureEvent).toHaveBeenCalledTimes(2); + expect(analyticsApiSpy.captureEvent).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ + action: 'navigate', + subject: '/page-5', + context: { + pluginId: 'some-plugin', + extensionId: 'App', + }, + }), + ); + expect(analyticsApiSpy.captureEvent).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + action: 'click', + subject: 'test 5', + context: { + pluginId: 'some-plugin', + extensionId: 'App', + }, + }), + ); + }); + + it('captures deferred navigate event with expected context when second event is also deferrable', () => { + // User navigates to a gathered mountpoint with multiple plugins + trackerUnderTest.setContext({ + ...defaultContext, + }); + trackerUnderTest.captureEvent('navigate', '/page-6'); + + // A routable extension is rendered with specific plugin context + trackerUnderTest.setContext({ + pluginId: 'another-plugin', + extensionId: 'App', + }); + trackerUnderTest.captureEvent(routableExtensionRenderedEvent, ''); + + // User navigates to another gathered mountpoint with multiple plugins + trackerUnderTest.setContext({ + ...defaultContext, + }); + trackerUnderTest.captureEvent('navigate', '/page-6-2'); + + expect(analyticsApiSpy.captureEvent).toHaveBeenCalledTimes(1); + expect(analyticsApiSpy.captureEvent).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ + action: 'navigate', + subject: '/page-6', + context: { + pluginId: 'another-plugin', + extensionId: 'App', + }, + }), + ); + }); + + it('captures deferred navigate event with default context when no extension is rendered in between', () => { + // User navigates to a gathered mountpoint with multiple plugins + trackerUnderTest.setContext({ + ...defaultContext, + }); + trackerUnderTest.captureEvent('navigate', '/page-7'); + + // A non-navigate event with no routable extension render in between + trackerUnderTest.captureEvent('click', 'test 7'); + + expect(analyticsApiSpy.captureEvent).toHaveBeenCalledTimes(2); + expect(analyticsApiSpy.captureEvent).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ + action: 'navigate', + subject: '/page-7', + context: defaultContext, + }), + ); + expect(analyticsApiSpy.captureEvent).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + action: 'click', + subject: 'test 7', + context: defaultContext, + }), + ); + }); + + it('captures deferred navigate event with expected context across separate trackers', () => { + // User navigates to a gathered mountpoint with multiple plugins + trackerUnderTest.setContext({ + ...defaultContext, + }); + trackerUnderTest.captureEvent('navigate', '/page-8'); + + // A routable extension is rendered with specific plugin context and + // captured via a separate tracker instance. + const anotherTracker = new Tracker(analyticsApiSpy, { + pluginId: 'the-plugin', + extensionId: 'App', + }); + anotherTracker.captureEvent(routableExtensionRenderedEvent, ''); + + // A non-navigate event is captured + const aThirdTracker = new Tracker(analyticsApiSpy); + aThirdTracker.captureEvent('click', 'test 8'); + + expect(analyticsApiSpy.captureEvent).toHaveBeenCalledTimes(2); + expect(analyticsApiSpy.captureEvent).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ + action: 'navigate', + subject: '/page-8', + context: { + pluginId: 'the-plugin', + extensionId: 'App', + }, + }), + ); + expect(analyticsApiSpy.captureEvent).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + action: 'click', + subject: 'test 8', + }), + ); + }); + + it('replaces extension context with "App" when capturing deferred events', () => { + // User navigates to a gathered mountpoint with multiple plugins + trackerUnderTest.setContext({ + ...defaultContext, + }); + trackerUnderTest.captureEvent('navigate', '/page-9'); + + // A routable extension is rendered with specific plugin context + trackerUnderTest.setContext({ + pluginId: 'very-plugin', + extensionId: 'ShouldBeReplaced', + }); + trackerUnderTest.captureEvent(routableExtensionRenderedEvent, ''); + + // A non-navigate event + trackerUnderTest.captureEvent('click', 'test 9'); + + // Extension context should have been replaced with just "App" + expect(analyticsApiSpy.captureEvent).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ + action: 'navigate', + subject: '/page-9', + context: { + pluginId: 'very-plugin', + extensionId: 'App', + }, + }), + ); + }); + }); +}); diff --git a/packages/frontend-plugin-api/src/analytics/Tracker.ts b/packages/frontend-plugin-api/src/analytics/Tracker.ts new file mode 100644 index 0000000000..dd0d770354 --- /dev/null +++ b/packages/frontend-plugin-api/src/analytics/Tracker.ts @@ -0,0 +1,175 @@ +/* + * 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 { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; +import { + AnalyticsApi, + AnalyticsEventAttributes, + AnalyticsTracker, +} from '../apis'; +import { AnalyticsContextValue } from './'; + +type TempGlobalEvents = { + /** + * Stores the most recent "gathered" mountpoint navigation. + */ + mostRecentGatheredNavigation?: { + action: string; + subject: string; + value?: number; + attributes?: AnalyticsEventAttributes; + context: AnalyticsContextValue; + }; + /** + * Stores the most recent routable extension render. + */ + mostRecentRoutableExtensionRender?: { + context: AnalyticsContextValue; + }; + /** + * Tracks whether or not a beforeunload event listener has already been + * registered. + */ + beforeUnloadRegistered: boolean; +}; + +/** + * Temporary global store for select event data. Used to make `navigate` events + * more accurate when gathered mountpoints are used. + */ +const globalEvents = getOrCreateGlobalSingleton( + 'core-plugin-api:analytics-tracker-events', + () => ({ + mostRecentGatheredNavigation: undefined, + mostRecentRoutableExtensionRender: undefined, + beforeUnloadRegistered: false, + }), +); + +/** + * Internal-only event representing when a routable extension is rendered. + */ +export const routableExtensionRenderedEvent = '_ROUTABLE-EXTENSION-RENDERED'; + +export class Tracker implements AnalyticsTracker { + constructor( + private readonly analyticsApi: AnalyticsApi, + private context: AnalyticsContextValue = { + pluginId: 'root', + extensionId: 'App', + }, + ) { + // Only register a single beforeunload event across all trackers. + if (!globalEvents.beforeUnloadRegistered) { + // Before the page unloads, attempt to capture any deferred navigation + // events that haven't yet been captured. + addEventListener( + 'beforeunload', + () => { + if (globalEvents.mostRecentGatheredNavigation) { + this.analyticsApi.captureEvent({ + ...globalEvents.mostRecentGatheredNavigation, + ...globalEvents.mostRecentRoutableExtensionRender, + }); + globalEvents.mostRecentGatheredNavigation = undefined; + globalEvents.mostRecentRoutableExtensionRender = undefined; + } + }, + { once: true, passive: true }, + ); + + // Prevent duplicate handlers from being registered. + globalEvents.beforeUnloadRegistered = true; + } + } + + setContext(context: AnalyticsContextValue) { + this.context = context; + } + + captureEvent( + action: string, + subject: string, + { + value, + attributes, + }: { value?: number; attributes?: AnalyticsEventAttributes } = {}, + ) { + // Never pass internal "_routeNodeType" context value. + const context = this.context; + + // Never fire the special "_routable-extension-rendered" internal event. + if (action === routableExtensionRenderedEvent) { + // But keep track of it if we're delaying a `navigate` event for a + // a gathered route node type. + if (globalEvents.mostRecentGatheredNavigation) { + globalEvents.mostRecentRoutableExtensionRender = { + context: { + ...context, + extensionId: 'App', + }, + }; + } + return; + } + + // If we are about to fire a real event, and we have an un-fired gathered + // mountpoint navigation on the global store, we need to fire the navigate + // event first, so this real event happens accurately after the navigation. + if (globalEvents.mostRecentGatheredNavigation) { + try { + this.analyticsApi.captureEvent({ + ...globalEvents.mostRecentGatheredNavigation, + ...globalEvents.mostRecentRoutableExtensionRender, + }); + } catch (e) { + // eslint-disable-next-line no-console + console.warn('Error during analytics event capture. %o', e); + } + + // Clear the global stores. + globalEvents.mostRecentGatheredNavigation = undefined; + globalEvents.mostRecentRoutableExtensionRender = undefined; + } + + // Never directly fire a navigation event on a gathered route with default + // contextual details. + if (action === 'navigate' && context.pluginId === 'root') { + // Instead, set it on the global store. + globalEvents.mostRecentGatheredNavigation = { + action, + subject, + value, + attributes, + context, + }; + return; + } + + try { + this.analyticsApi.captureEvent({ + action, + subject, + value, + attributes, + context, + }); + } catch (e) { + // eslint-disable-next-line no-console + console.warn('Error during analytics event capture. %o', e); + } + } +} diff --git a/packages/frontend-plugin-api/src/analytics/index.ts b/packages/frontend-plugin-api/src/analytics/index.ts new file mode 100644 index 0000000000..651e8e105e --- /dev/null +++ b/packages/frontend-plugin-api/src/analytics/index.ts @@ -0,0 +1,19 @@ +/* + * 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. + */ + +export { AnalyticsContext } from './AnalyticsContext'; +export type { AnalyticsContextValue, CommonAnalyticsContext } from './types'; +export { useAnalytics } from './useAnalytics'; diff --git a/packages/frontend-plugin-api/src/analytics/types.ts b/packages/frontend-plugin-api/src/analytics/types.ts new file mode 100644 index 0000000000..21347e2fc7 --- /dev/null +++ b/packages/frontend-plugin-api/src/analytics/types.ts @@ -0,0 +1,44 @@ +/* + * 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. + */ + +/** + * Common analytics context attributes. + * + * @public + */ +export type CommonAnalyticsContext = { + /** + * The nearest known parent plugin where the event was captured. + */ + pluginId: string; + + /** + * The nearest known parent extension where the event was captured. + */ + /** + * The nearest known parent extension where the event was captured. + */ + extensionId: string; +}; + +/** + * Analytics context envelope. + * + * @public + */ +export type AnalyticsContextValue = CommonAnalyticsContext & { + [param in string]: string | boolean | number | undefined; +}; diff --git a/packages/frontend-plugin-api/src/analytics/useAnalytics.test.tsx b/packages/frontend-plugin-api/src/analytics/useAnalytics.test.tsx new file mode 100644 index 0000000000..beb16b1fbb --- /dev/null +++ b/packages/frontend-plugin-api/src/analytics/useAnalytics.test.tsx @@ -0,0 +1,61 @@ +/* + * 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 { renderHook } from '@testing-library/react'; +import { useAnalytics } from './useAnalytics'; +import { analyticsApiRef } from '@backstage/core-plugin-api'; +import { TestApiProvider } from '@backstage/test-utils'; +import React from 'react'; + +describe('useAnalytics', () => { + it('returns tracker with no implementation defined', () => { + // useApi throws an error because the Analytics API is not implemented + // But the result should still have a captureEvent method. + const { result } = renderHook(() => useAnalytics(), {}); + expect(result.current.captureEvent).toBeDefined(); + }); + + it('returns tracker from defined analytics api', () => { + const captureEvent = jest.fn(); + + // Calling the captureEvent method of the underlying implementation should + // pass along the given event as well as the default context. + const { result } = renderHook(() => useAnalytics(), { + wrapper: ({ children }) => ( + // Simulate useApi returning a valid tracker. + + {children} + + ), + }); + result.current.captureEvent('an action', 'a subject', { + value: 42, + attributes: { some: 'value' }, + }); + expect(captureEvent).toHaveBeenCalledWith({ + action: 'an action', + subject: 'a subject', + value: 42, + attributes: { + some: 'value', + }, + context: { + extensionId: 'App', + pluginId: 'root', + }, + }); + }); +}); diff --git a/packages/frontend-plugin-api/src/analytics/useAnalytics.tsx b/packages/frontend-plugin-api/src/analytics/useAnalytics.tsx new file mode 100644 index 0000000000..f3b5998de4 --- /dev/null +++ b/packages/frontend-plugin-api/src/analytics/useAnalytics.tsx @@ -0,0 +1,57 @@ +/* + * 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 { useApi } from '@backstage/core-plugin-api'; +import { useAnalyticsContext } from './AnalyticsContext'; +import { analyticsApiRef, AnalyticsTracker, AnalyticsApi } from '../apis'; +import { useRef } from 'react'; +import { Tracker } from './Tracker'; + +function useAnalyticsApi(): AnalyticsApi { + try { + return useApi(analyticsApiRef); + } catch { + return { captureEvent: () => {} }; + } +} + +/** + * Gets a pre-configured analytics tracker. + * + * @public + */ +export function useAnalytics(): AnalyticsTracker { + const trackerRef = useRef(null); + const context = useAnalyticsContext(); + // Our goal is to make this API truly optional for any/all consuming code + // (including tests). This hook runs last to ensure hook order is, as much as + // possible, maintained. + const analyticsApi = useAnalyticsApi(); + + function getTracker(): Tracker { + if (trackerRef.current === null) { + trackerRef.current = new Tracker(analyticsApi); + } + return trackerRef.current; + } + + const tracker = getTracker(); + // this is not ideal, but it allows to memoize the tracker + // without explicitly set the context as dependency. + tracker.setContext(context); + + return tracker; +} diff --git a/packages/frontend-plugin-api/src/apis/definitions/AlertApi.ts b/packages/frontend-plugin-api/src/apis/definitions/AlertApi.ts new file mode 100644 index 0000000000..649a930b50 --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/definitions/AlertApi.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { + type AlertApi, + type AlertMessage, + alertApiRef, +} from '@backstage/core-plugin-api'; diff --git a/packages/frontend-plugin-api/src/apis/definitions/AnalyticsApi.ts b/packages/frontend-plugin-api/src/apis/definitions/AnalyticsApi.ts new file mode 100644 index 0000000000..15b09482b7 --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/definitions/AnalyticsApi.ts @@ -0,0 +1,131 @@ +/* + * 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 { ApiRef, createApiRef } from '@backstage/core-plugin-api'; +import { AnalyticsContextValue } from '../../analytics/types'; + +/** + * Represents an event worth tracking in an analytics system that could inform + * how users of a Backstage instance are using its features. + * + * @public + */ +export type AnalyticsEvent = { + /** + * A string that identifies the event being tracked by the type of action the + * event represents. Be careful not to encode extra metadata in this string + * that should instead be placed in the Analytics Context or attributes. + * Examples include: + * + * - view + * - click + * - filter + * - search + * - hover + * - scroll + */ + action: string; + + /** + * A string that uniquely identifies the object that the action is being + * taken on. Examples include: + * + * - The path of the page viewed + * - The url of the link clicked + * - The value that was filtered by + * - The text that was searched for + */ + subject: string; + + /** + * An optional numeric value relevant to the event that could be aggregated + * by analytics tools. Examples include: + * + * - The index or position of the clicked element in an ordered list + * - The percentage of an element that has been scrolled through + * - The amount of time that has elapsed since a fixed point + * - A satisfaction score on a fixed scale + */ + value?: number; + + /** + * Optional, additional attributes (representing dimensions or metrics) + * specific to the event that could be forwarded on to analytics systems. + */ + attributes?: AnalyticsEventAttributes; + + /** + * Contextual metadata relating to where the event was captured and by whom. + * This could include information about the route, plugin, or extension in + * which an event was captured. + */ + context: AnalyticsContextValue; +}; + +/** + * A structure allowing other arbitrary metadata to be provided by analytics + * event emitters. + * + * @public + */ +export type AnalyticsEventAttributes = { + [attribute in string]: string | boolean | number; +}; + +/** + * Represents a tracker with methods that can be called to track events in a + * configured analytics service. + * + * @public + */ +export type AnalyticsTracker = { + captureEvent: ( + action: string, + subject: string, + options?: { + value?: number; + attributes?: AnalyticsEventAttributes; + }, + ) => void; +}; + +/** + * The Analytics API is used to track user behavior in a Backstage instance. + * + * @remarks + * + * To instrument your App or Plugin, retrieve an analytics tracker using the + * useAnalytics() hook. This will return a pre-configured AnalyticsTracker + * with relevant methods for instrumentation. + * + * @public + */ +export type AnalyticsApi = { + /** + * Primary event handler responsible for compiling and forwarding events to + * an analytics system. + */ + captureEvent(event: AnalyticsEvent): void; +}; + +/** + * The API reference of {@link AnalyticsApi}. + * + * @public + */ +export const analyticsApiRef: ApiRef = createApiRef({ + id: 'core.analytics', +}); diff --git a/packages/frontend-plugin-api/src/apis/definitions/AppLanguageApi.ts b/packages/frontend-plugin-api/src/apis/definitions/AppLanguageApi.ts new file mode 100644 index 0000000000..37ffcfa820 --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/definitions/AppLanguageApi.ts @@ -0,0 +1,20 @@ +/* + * 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 { + type AppLanguageApi, + appLanguageApiRef, +} from '@backstage/core-plugin-api/alpha'; diff --git a/packages/frontend-plugin-api/src/apis/definitions/AppThemeApi.ts b/packages/frontend-plugin-api/src/apis/definitions/AppThemeApi.ts new file mode 100644 index 0000000000..ce62cd72c3 --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/definitions/AppThemeApi.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { + type AppTheme, + type AppThemeApi, + appThemeApiRef, +} from '@backstage/core-plugin-api'; diff --git a/packages/frontend-plugin-api/src/apis/definitions/ComponentsApi.ts b/packages/frontend-plugin-api/src/apis/definitions/ComponentsApi.ts new file mode 100644 index 0000000000..c5e9d2c44f --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/definitions/ComponentsApi.ts @@ -0,0 +1,49 @@ +/* + * 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. + */ + +import { ComponentType } from 'react'; +import { createApiRef, useApi } from '@backstage/core-plugin-api'; +import { ComponentRef } from '../../components'; + +/** + * API for looking up components based on component refs. + * + * @public + */ +export interface ComponentsApi { + // TODO: Should component refs also provide the default implementation so that we're guaranteed to get a component? + getComponent(ref: ComponentRef): ComponentType; +} + +/** + * The `ApiRef` of {@link ComponentsApi}. + * + * @public + */ +export const componentsApiRef = createApiRef({ + id: 'core.components', +}); + +/** + * @public + * Returns the component associated with the given ref. + */ +export function useComponentRef( + ref: ComponentRef, +): ComponentType { + const componentsApi = useApi(componentsApiRef); + return componentsApi.getComponent(ref); +} diff --git a/plugins/catalog-backend/src/catalog/index.ts b/packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts similarity index 88% rename from plugins/catalog-backend/src/catalog/index.ts rename to packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts index ba34673bba..968a2843ba 100644 --- a/plugins/catalog-backend/src/catalog/index.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/ConfigApi.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export type { EntitiesSearchFilter, EntityFilter } from './types'; +export { type ConfigApi, configApiRef } from '@backstage/core-plugin-api'; diff --git a/packages/frontend-plugin-api/src/apis/definitions/DiscoveryApi.ts b/packages/frontend-plugin-api/src/apis/definitions/DiscoveryApi.ts new file mode 100644 index 0000000000..98b3f0bbf0 --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/definitions/DiscoveryApi.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { type DiscoveryApi, discoveryApiRef } from '@backstage/core-plugin-api'; diff --git a/plugins/graphql-backend/src/index.ts b/packages/frontend-plugin-api/src/apis/definitions/ErrorApi.ts similarity index 82% rename from plugins/graphql-backend/src/index.ts rename to packages/frontend-plugin-api/src/apis/definitions/ErrorApi.ts index a9f7f92ad9..57782a05dc 100644 --- a/plugins/graphql-backend/src/index.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/ErrorApi.ts @@ -14,10 +14,9 @@ * limitations under the License. */ -/** - * An experimental Backstage backend plugin for GraphQL - * - * @packageDocumentation - */ - -export * from './service/router'; +export { + type ErrorApiError, + type ErrorApiErrorContext, + type ErrorApi, + errorApiRef, +} from '@backstage/core-plugin-api'; diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/index.ts b/packages/frontend-plugin-api/src/apis/definitions/FeatureFlagsApi.ts similarity index 79% rename from plugins/kubernetes-react/src/utils/clusterLinks/index.ts rename to packages/frontend-plugin-api/src/apis/definitions/FeatureFlagsApi.ts index 90a30e8277..820efc0a25 100644 --- a/plugins/kubernetes-react/src/utils/clusterLinks/index.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/FeatureFlagsApi.ts @@ -15,7 +15,9 @@ */ export { - formatClusterLink, - type FormatClusterLinkOptions, -} from './formatClusterLink'; -export { clusterLinksFormatters } from './formatters'; + type FeatureFlag, + type FeatureFlagState, + type FeatureFlagsSaveOptions, + type FeatureFlagsApi, + featureFlagsApiRef, +} from '@backstage/core-plugin-api'; diff --git a/packages/frontend-plugin-api/src/apis/definitions/FetchApi.ts b/packages/frontend-plugin-api/src/apis/definitions/FetchApi.ts new file mode 100644 index 0000000000..bcc9bc6a91 --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/definitions/FetchApi.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +export { type FetchApi, fetchApiRef } from '@backstage/core-plugin-api'; diff --git a/packages/frontend-plugin-api/src/apis/definitions/IdentityApi.ts b/packages/frontend-plugin-api/src/apis/definitions/IdentityApi.ts new file mode 100644 index 0000000000..03503a8fba --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/definitions/IdentityApi.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { type IdentityApi, identityApiRef } from '@backstage/core-plugin-api'; diff --git a/packages/frontend-plugin-api/src/apis/definitions/OAuthRequestApi.ts b/packages/frontend-plugin-api/src/apis/definitions/OAuthRequestApi.ts new file mode 100644 index 0000000000..ff7a0f2852 --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/definitions/OAuthRequestApi.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { + type OAuthRequesterOptions, + type OAuthRequester, + type PendingOAuthRequest, + type OAuthRequestApi, + oauthRequestApiRef, +} from '@backstage/core-plugin-api'; diff --git a/packages/frontend-plugin-api/src/apis/definitions/StorageApi.ts b/packages/frontend-plugin-api/src/apis/definitions/StorageApi.ts new file mode 100644 index 0000000000..2309d2414c --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/definitions/StorageApi.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { + type StorageValueSnapshot, + type StorageApi, + storageApiRef, +} from '@backstage/core-plugin-api'; diff --git a/packages/frontend-plugin-api/src/apis/definitions/alpha.ts b/packages/frontend-plugin-api/src/apis/definitions/alpha.ts new file mode 100644 index 0000000000..a4ccde1170 --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/definitions/alpha.ts @@ -0,0 +1,17 @@ +/* + * 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 { appLanguageApiRef, type AppLanguageApi } from './AppLanguageApi'; diff --git a/packages/frontend-plugin-api/src/apis/definitions/auth.ts b/packages/frontend-plugin-api/src/apis/definitions/auth.ts new file mode 100644 index 0000000000..d27aebbf47 --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/definitions/auth.ts @@ -0,0 +1,39 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { + type BackstageIdentityApi, + type BackstageIdentityResponse, + type BackstageUserIdentity, + type AuthProviderInfo, + type AuthRequestOptions, + type OAuthScope, + type OAuthApi, + type OpenIdConnectApi, + type ProfileInfoApi, + type ProfileInfo, + type SessionApi, + SessionState, + atlassianAuthApiRef, + bitbucketAuthApiRef, + bitbucketServerAuthApiRef, + githubAuthApiRef, + gitlabAuthApiRef, + googleAuthApiRef, + oktaAuthApiRef, + microsoftAuthApiRef, + oneloginAuthApiRef, +} from '@backstage/core-plugin-api'; diff --git a/packages/frontend-plugin-api/src/apis/definitions/index.ts b/packages/frontend-plugin-api/src/apis/definitions/index.ts index 8facdca2ca..f2496ee61a 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/index.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/index.ts @@ -23,3 +23,24 @@ export { type AppTree, type AppTreeApi, } from './AppTreeApi'; + +// This folder contains definitions for all core APIs. +// +// Plugins should rely on these APIs for functionality as much as possible. +// +// If you think some API definition is missing, please open an Issue or send a PR! + +export * from './auth'; + +export * from './AlertApi'; +export * from './AppThemeApi'; +export * from './ComponentsApi'; +export * from './ConfigApi'; +export * from './DiscoveryApi'; +export * from './ErrorApi'; +export * from './FeatureFlagsApi'; +export * from './FetchApi'; +export * from './IdentityApi'; +export * from './OAuthRequestApi'; +export * from './StorageApi'; +export * from './AnalyticsApi'; diff --git a/packages/frontend-plugin-api/src/apis/index.ts b/packages/frontend-plugin-api/src/apis/index.ts index 5a012c0553..5def6cb0f9 100644 --- a/packages/frontend-plugin-api/src/apis/index.ts +++ b/packages/frontend-plugin-api/src/apis/index.ts @@ -15,3 +15,4 @@ */ export * from './definitions'; +export * from './system'; diff --git a/packages/frontend-plugin-api/src/apis/system/ApiRef.ts b/packages/frontend-plugin-api/src/apis/system/ApiRef.ts new file mode 100644 index 0000000000..0d1f8312cb --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/system/ApiRef.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { + type ApiRef, + type ApiRefConfig, + createApiRef, +} from '@backstage/core-plugin-api'; diff --git a/packages/frontend-plugin-api/src/apis/system/helpers.ts b/packages/frontend-plugin-api/src/apis/system/helpers.ts new file mode 100644 index 0000000000..5de265be99 --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/system/helpers.ts @@ -0,0 +1,17 @@ +/* + * 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 { createApiFactory } from '@backstage/core-plugin-api'; diff --git a/packages/frontend-plugin-api/src/apis/system/index.ts b/packages/frontend-plugin-api/src/apis/system/index.ts new file mode 100644 index 0000000000..b1bd3ac2b3 --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/system/index.ts @@ -0,0 +1,21 @@ +/* + * 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 { useApi, useApiHolder, withApis } from './useApi'; +export { createApiRef } from './ApiRef'; +export type { ApiRefConfig } from './ApiRef'; +export * from './types'; +export * from './helpers'; diff --git a/packages/frontend-plugin-api/src/apis/system/types.ts b/packages/frontend-plugin-api/src/apis/system/types.ts new file mode 100644 index 0000000000..cc44e19e3f --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/system/types.ts @@ -0,0 +1,24 @@ +/* + * 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 type { + ApiRef, + AnyApiRef, + TypesToApiRefs, + ApiHolder, + ApiFactory, + AnyApiFactory, +} from '@backstage/core-plugin-api'; diff --git a/packages/frontend-plugin-api/src/apis/system/useApi.tsx b/packages/frontend-plugin-api/src/apis/system/useApi.tsx new file mode 100644 index 0000000000..d2efa49fa1 --- /dev/null +++ b/packages/frontend-plugin-api/src/apis/system/useApi.tsx @@ -0,0 +1,17 @@ +/* + * 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 { useApiHolder, useApi, withApis } from '@backstage/core-plugin-api'; diff --git a/packages/frontend-plugin-api/src/components/ComponentRef.tsx b/packages/frontend-plugin-api/src/components/ComponentRef.tsx new file mode 100644 index 0000000000..50df9552ec --- /dev/null +++ b/packages/frontend-plugin-api/src/components/ComponentRef.tsx @@ -0,0 +1,58 @@ +/* + * 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. + */ + +import { + CoreErrorBoundaryFallbackProps, + CoreNotFoundErrorPageProps, + CoreProgressProps, +} from '../types'; + +/** @public */ +export type ComponentRef = { + id: string; + T: T; +}; + +/** @public */ +export function createComponentRef(options: { + id: string; +}): ComponentRef { + const { id } = options; + return { + id, + } as ComponentRef; +} + +const coreProgressComponentRef = createComponentRef({ + id: 'core.components.progress', +}); + +const coreNotFoundErrorPageComponentRef = + createComponentRef({ + id: 'core.components.notFoundErrorPage', + }); + +const coreErrorBoundaryFallbackComponentRef = + createComponentRef({ + id: 'core.components.errorBoundaryFallback', + }); + +/** @public */ +export const coreComponentRefs = { + progress: coreProgressComponentRef, + notFoundErrorPage: coreNotFoundErrorPageComponentRef, + errorBoundaryFallback: coreErrorBoundaryFallbackComponentRef, +}; diff --git a/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx b/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx index 1191b75a1d..6b457fadc9 100644 --- a/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx +++ b/packages/frontend-plugin-api/src/components/ErrorBoundary.tsx @@ -14,35 +14,14 @@ * limitations under the License. */ -import React, { Component, PropsWithChildren } from 'react'; -// TODO: Dependency on MUI should be removed from core packages -import { Button } from '@material-ui/core'; -import { ErrorPanel } from '@backstage/core-components'; +import React, { Component, ComponentType, PropsWithChildren } from 'react'; import { BackstagePlugin } from '../wiring'; +import { CoreErrorBoundaryFallbackProps } from '../types'; -type DefaultErrorBoundaryFallbackProps = PropsWithChildren<{ +type ErrorBoundaryProps = PropsWithChildren<{ plugin?: BackstagePlugin; - error: Error; - resetError: () => void; + Fallback: ComponentType; }>; - -const DefaultErrorBoundaryFallback = ({ - plugin, - error, - resetError, -}: DefaultErrorBoundaryFallbackProps) => { - const title = `Error in ${plugin?.id}`; - - return ( - - - - ); -}; - -type ErrorBoundaryProps = PropsWithChildren<{ plugin?: BackstagePlugin }>; type ErrorBoundaryState = { error?: Error }; /** @internal */ @@ -62,12 +41,11 @@ export class ErrorBoundary extends Component< render() { const { error } = this.state; - const { plugin, children } = this.props; + const { plugin, children, Fallback } = this.props; if (error) { - // TODO: use a configurable error boundary fallback return ( - , - options?: { - config?: JsonObject; - }, -) { - const { config = {} } = options ?? {}; - - const app = createApp({ - features: [ - createPlugin({ - id: 'plugin', - extensions: [extension], - }), - ], - configLoader: async () => new MockConfigApi(config), - }); - - return renderWithEffects(app.createRoot()); -} +import { createExtensionTester } from '@backstage/frontend-test-utils'; const wrapInBoundaryExtension = (element: JSX.Element) => { - const id = 'plugin.extension'; const routeRef = createRouteRef(); return createExtension({ - id, - attachTo: { id: 'core.routes', input: 'routes' }, + name: 'test', + attachTo: { id: 'core/routes', input: 'routes' }, output: { element: coreExtensionData.reactElement, path: coreExtensionData.routePath, routeRef: coreExtensionData.routeRef.optional(), }, - factory({ source }) { + factory({ node }) { return { routeRef, path: '/', - element: ( - - {element} - - ), + element: {element}, }; }, }); @@ -86,7 +49,7 @@ describe('ExtensionBoundary', () => { const TextComponent = () => { return

{text}

; }; - await renderExtensionInTestApp(wrapInBoundaryExtension()); + createExtensionTester(wrapInBoundaryExtension()).render(); await waitFor(() => expect(screen.getByText(text)).toBeInTheDocument()); }); @@ -95,7 +58,7 @@ describe('ExtensionBoundary', () => { const ErrorComponent = () => { throw new Error(error); }; - await renderExtensionInTestApp(wrapInBoundaryExtension()); + createExtensionTester(wrapInBoundaryExtension()).render(); await waitFor(() => expect(screen.getByText(error)).toBeInTheDocument()); }); @@ -112,23 +75,26 @@ describe('ExtensionBoundary', () => { return null; }; - await renderExtensionInTestApp( + createExtensionTester( wrapInBoundaryExtension( , ), - ); + ).render(); - await waitFor(() => - expect(analyticsApiMock.getEvents()[0]).toMatchObject({ + await waitFor(() => { + const event = analyticsApiMock + .getEvents() + .find(e => e.subject === subject); + + expect(event).toMatchObject({ action, subject, context: { - extension: 'plugin.extension', - routeRef: 'unknown', + extensionId: 'test', }, - }), - ); + }); + }); }); }); diff --git a/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx b/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx index a9ea297216..d9bd41f2a9 100644 --- a/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx +++ b/packages/frontend-plugin-api/src/components/ExtensionBoundary.tsx @@ -14,13 +14,18 @@ * limitations under the License. */ -import React, { PropsWithChildren, ReactNode, useEffect } from 'react'; +import React, { + PropsWithChildren, + ReactNode, + Suspense, + useEffect, +} from 'react'; import { AnalyticsContext, useAnalytics } from '@backstage/core-plugin-api'; -import { BackstagePlugin } from '../wiring'; import { ErrorBoundary } from './ErrorBoundary'; -import { ExtensionSuspense } from './ExtensionSuspense'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { routableExtensionRenderedEvent } from '../../../core-plugin-api/src/analytics/Tracker'; +import { AppNode, useComponentRef } from '../apis'; +import { coreComponentRefs } from './ComponentRef'; type RouteTrackerProps = PropsWithChildren<{ disableTracking?: boolean; @@ -44,29 +49,32 @@ const RouteTracker = (props: RouteTrackerProps) => { /** @public */ export interface ExtensionBoundaryProps { - id: string; - source?: BackstagePlugin; + node: AppNode; routable?: boolean; children: ReactNode; } /** @public */ export function ExtensionBoundary(props: ExtensionBoundaryProps) { - const { id, source, routable, children } = props; + const { node, routable, children } = props; + + const plugin = node.spec.source; + const Progress = useComponentRef(coreComponentRefs.progress); + const fallback = useComponentRef(coreComponentRefs.errorBoundaryFallback); // Skipping "routeRef" attribute in the new system, the extension "id" should provide more insight const attributes = { - extension: id, - pluginId: source?.id, + extensionId: node.spec.id, + pluginId: node.spec.source?.id, }; return ( - - + }> + {children} - + ); } diff --git a/packages/frontend-plugin-api/src/components/index.ts b/packages/frontend-plugin-api/src/components/index.ts index 7056a59271..893918059b 100644 --- a/packages/frontend-plugin-api/src/components/index.ts +++ b/packages/frontend-plugin-api/src/components/index.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +export { coreComponentRefs, type ComponentRef } from './ComponentRef'; + export { ExtensionBoundary, type ExtensionBoundaryProps, diff --git a/packages/frontend-plugin-api/src/extensions/createApiExtension.test.ts b/packages/frontend-plugin-api/src/extensions/createApiExtension.test.ts index e90c0b6b85..2585b0d694 100644 --- a/packages/frontend-plugin-api/src/extensions/createApiExtension.test.ts +++ b/packages/frontend-plugin-api/src/extensions/createApiExtension.test.ts @@ -26,13 +26,14 @@ describe('createApiExtension', () => { factory: () => ({ foo: 'bar' }), }); - const extension = createApiExtension({ - factory, - }); - - expect(extension).toEqual({ - $$type: '@backstage/Extension', - id: 'apis.test', + expect( + createApiExtension({ + factory, + }), + ).toEqual({ + $$type: '@backstage/ExtensionDefinition', + kind: 'api', + namespace: 'test', attachTo: { id: 'core', input: 'apis' }, disabled: false, configSchema: undefined, @@ -65,8 +66,9 @@ describe('createApiExtension', () => { }); // boo expect(extension).toEqual({ - $$type: '@backstage/Extension', - id: 'apis.test', + $$type: '@backstage/ExtensionDefinition', + kind: 'api', + namespace: 'test', attachTo: { id: 'core', input: 'apis' }, disabled: false, configSchema: undefined, diff --git a/packages/frontend-plugin-api/src/extensions/createApiExtension.ts b/packages/frontend-plugin-api/src/extensions/createApiExtension.ts index 7b6dded022..bbaef3c849 100644 --- a/packages/frontend-plugin-api/src/extensions/createApiExtension.ts +++ b/packages/frontend-plugin-api/src/extensions/createApiExtension.ts @@ -17,7 +17,7 @@ import { AnyApiFactory, AnyApiRef } from '@backstage/core-plugin-api'; import { PortableSchema } from '../schema'; import { - ExtensionInputValues, + ResolvedExtensionInputs, createExtension, coreExtensionData, } from '../wiring'; @@ -34,7 +34,7 @@ export function createApiExtension< api: AnyApiRef; factory: (options: { config: TConfig; - inputs: Expand>; + inputs: Expand>; }) => AnyApiFactory; } | { @@ -51,7 +51,10 @@ export function createApiExtension< 'api' in options ? options.api : (factory as { api: AnyApiRef }).api; return createExtension({ - id: `apis.${apiRef.id}`, + kind: 'api', + // Since ApiRef IDs use a global namespace we use the namespace here in order to override + // potential plugin IDs and always end up with the format `api:` + namespace: apiRef.id, attachTo: { id: 'core', input: 'apis' }, inputs: extensionInputs, configSchema, diff --git a/packages/frontend-plugin-api/src/extensions/createComponentExtension.tsx b/packages/frontend-plugin-api/src/extensions/createComponentExtension.tsx new file mode 100644 index 0000000000..816dee6054 --- /dev/null +++ b/packages/frontend-plugin-api/src/extensions/createComponentExtension.tsx @@ -0,0 +1,90 @@ +/* + * 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. + */ + +import React, { lazy, ComponentType } from 'react'; +import { + AnyExtensionInputMap, + ResolvedExtensionInputs, + coreExtensionData, + createExtension, +} from '../wiring'; +import { Expand } from '../types'; +import { PortableSchema } from '../schema'; +import { ExtensionBoundary, ComponentRef } from '../components'; + +/** @public */ +export function createComponentExtension< + TProps extends {}, + TConfig extends {}, + TInputs extends AnyExtensionInputMap, +>(options: { + ref: ComponentRef; + name?: string; + disabled?: boolean; + inputs?: TInputs; + configSchema?: PortableSchema; + component: + | { + lazy: (values: { + config: TConfig; + inputs: Expand>; + }) => Promise>; + } + | { + sync: (values: { + config: TConfig; + inputs: Expand>; + }) => ComponentType; + }; +}) { + return createExtension({ + kind: 'component', + namespace: options.ref.id, + name: options.name, + attachTo: { id: 'core', input: 'components' }, + inputs: options.inputs, + disabled: options.disabled, + configSchema: options.configSchema, + output: { + component: coreExtensionData.component, + }, + factory({ config, inputs, node }) { + let ExtensionComponent: ComponentType; + + if ('sync' in options.component) { + ExtensionComponent = options.component.sync({ config, inputs }); + } else { + const lazyLoader = options.component.lazy; + ExtensionComponent = lazy(() => + lazyLoader({ config, inputs }).then(component => ({ + default: component, + })), + ) as unknown as ComponentType; + } + + return { + component: { + ref: options.ref, + impl: props => ( + + + + ), + }, + }; + }, + }); +} diff --git a/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx b/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx index 84fbe5ffee..207778fbd7 100644 --- a/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx +++ b/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx @@ -24,15 +24,18 @@ import { RouteRef } from '../routing'; * @public */ export function createNavItemExtension(options: { - id: string; + namespace?: string; + name?: string; routeRef: RouteRef; title: string; icon: IconComponent; }) { - const { id, routeRef, title, icon } = options; + const { routeRef, title, icon, namespace, name } = options; return createExtension({ - id, - attachTo: { id: 'core.nav', input: 'items' }, + namespace, + name, + kind: 'nav-item', + attachTo: { id: 'core/nav', input: 'items' }, configSchema: createSchemaFromZod(z => z.object({ title: z.string().default(title), diff --git a/packages/frontend-plugin-api/src/extensions/createNavLogoExtension.test.tsx b/packages/frontend-plugin-api/src/extensions/createNavLogoExtension.test.tsx new file mode 100644 index 0000000000..ca95fad7bc --- /dev/null +++ b/packages/frontend-plugin-api/src/extensions/createNavLogoExtension.test.tsx @@ -0,0 +1,45 @@ +/* + * 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. + */ + +import React from 'react'; +import { createNavLogoExtension } from './createNavLogoExtension'; + +jest.mock('@backstage/core-plugin-api', () => ({ + ...jest.requireActual('@backstage/core-plugin-api'), +})); + +describe('createNavLogoExtension', () => { + it('creates the extension properly', () => { + expect( + createNavLogoExtension({ + name: 'test', + logoFull:
Logo Full
, + logoIcon:
Logo Icon
, + }), + ).toEqual({ + $$type: '@backstage/ExtensionDefinition', + kind: 'nav-logo', + name: 'test', + attachTo: { id: 'core/nav', input: 'logos' }, + disabled: false, + inputs: {}, + output: { + logos: expect.anything(), + }, + factory: expect.any(Function), + }); + }); +}); diff --git a/packages/frontend-plugin-api/src/extensions/createNavLogoExtension.tsx b/packages/frontend-plugin-api/src/extensions/createNavLogoExtension.tsx new file mode 100644 index 0000000000..878764bad7 --- /dev/null +++ b/packages/frontend-plugin-api/src/extensions/createNavLogoExtension.tsx @@ -0,0 +1,47 @@ +/* + * 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. + */ + +import { coreExtensionData, createExtension } from '../wiring'; + +/** + * Helper for creating extensions for a nav logos. + * @public + */ +export function createNavLogoExtension(options: { + name?: string; + namespace?: string; + logoIcon: JSX.Element; + logoFull: JSX.Element; +}) { + const { logoIcon, logoFull } = options; + return createExtension({ + kind: 'nav-logo', + name: options?.name, + namespace: options?.namespace, + attachTo: { id: 'core/nav', input: 'logos' }, + output: { + logos: coreExtensionData.logoElements, + }, + factory: () => { + return { + logos: { + logoIcon, + logoFull, + }, + }; + }, + }); +} diff --git a/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx b/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx index 81843558da..525f10ee61 100644 --- a/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx +++ b/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx @@ -15,16 +15,12 @@ */ import React from 'react'; -import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils'; import { useAnalytics } from '@backstage/core-plugin-api'; import { waitFor } from '@testing-library/react'; import { PortableSchema } from '../schema'; -import { - coreExtensionData, - createExtensionInput, - createPlugin, -} from '../wiring'; +import { coreExtensionData, createExtensionInput } from '../wiring'; import { createPageExtension } from './createPageExtension'; +import { createExtensionTester } from '@backstage/frontend-test-utils'; jest.mock('@backstage/core-plugin-api', () => ({ ...jest.requireActual('@backstage/core-plugin-api'), @@ -40,14 +36,15 @@ describe('createPageExtension', () => { expect( createPageExtension({ - id: 'test', + name: 'test', configSchema, loader: async () =>
, }), ).toEqual({ - $$type: '@backstage/Extension', - id: 'test', - attachTo: { id: 'core.routes', input: 'routes' }, + $$type: '@backstage/ExtensionDefinition', + name: 'test', + kind: 'page', + attachTo: { id: 'core/routes', input: 'routes' }, configSchema: expect.anything(), disabled: false, inputs: {}, @@ -61,7 +58,7 @@ describe('createPageExtension', () => { expect( createPageExtension({ - id: 'test', + name: 'test', attachTo: { id: 'other', input: 'place' }, disabled: true, configSchema, @@ -73,8 +70,9 @@ describe('createPageExtension', () => { loader: async () =>
, }), ).toEqual({ - $$type: '@backstage/Extension', - id: 'test', + $$type: '@backstage/ExtensionDefinition', + name: 'test', + kind: 'page', attachTo: { id: 'other', input: 'place' }, configSchema: expect.anything(), disabled: true, @@ -93,14 +91,15 @@ describe('createPageExtension', () => { expect( createPageExtension({ - id: 'test', + name: 'test', defaultPath: '/here', loader: async () =>
, }), ).toEqual({ - $$type: '@backstage/Extension', - id: 'test', - attachTo: { id: 'core.routes', input: 'routes' }, + $$type: '@backstage/ExtensionDefinition', + name: 'test', + kind: 'page', + attachTo: { id: 'core/routes', input: 'routes' }, configSchema: expect.anything(), disabled: false, inputs: {}, @@ -120,19 +119,12 @@ describe('createPageExtension', () => { captureEvent, }); - const extension = createPageExtension({ - id: 'plugin.page', - defaultPath: '/', - loader: async () =>
Component
, - }); - - const output = extension.factory({ - source: createPlugin({ id: 'plugin ' }), - config: { path: '/' }, - inputs: {}, - }); - - renderWithEffects(wrapInTestApp(output.element as unknown as JSX.Element)); + createExtensionTester( + createPageExtension({ + defaultPath: '/', + loader: async () =>
Component
, + }), + ).render(); await waitFor(() => expect(captureEvent).toHaveBeenCalledWith( diff --git a/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx b/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx index f5e258a1e4..3b936ef210 100644 --- a/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx +++ b/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx @@ -20,12 +20,12 @@ import { createSchemaFromZod, PortableSchema } from '../schema'; import { coreExtensionData, createExtension, - Extension, - ExtensionInputValues, + ResolvedExtensionInputs, AnyExtensionInputMap, } from '../wiring'; import { RouteRef } from '../routing'; import { Expand } from '../types'; +import { ExtensionDefinition } from '../wiring/createExtension'; /** * Helper for creating extensions for a routable React page component. @@ -44,19 +44,18 @@ export function createPageExtension< configSchema: PortableSchema; } ) & { - id: string; + namespace?: string; + name?: string; attachTo?: { id: string; input: string }; disabled?: boolean; inputs?: TInputs; routeRef?: RouteRef; loader: (options: { config: TConfig; - inputs: Expand>; + inputs: Expand>; }) => Promise; }, -): Extension { - const { id } = options; - +): ExtensionDefinition { const configSchema = 'configSchema' in options ? options.configSchema @@ -65,8 +64,10 @@ export function createPageExtension< ) as PortableSchema); return createExtension({ - id, - attachTo: options.attachTo ?? { id: 'core.routes', input: 'routes' }, + kind: 'page', + namespace: options.namespace, + name: options.name, + attachTo: options.attachTo ?? { id: 'core/routes', input: 'routes' }, configSchema, inputs: options.inputs, disabled: options.disabled, @@ -75,7 +76,7 @@ export function createPageExtension< path: coreExtensionData.routePath, routeRef: coreExtensionData.routeRef.optional(), }, - factory({ config, inputs, source }) { + factory({ config, inputs, node }) { const ExtensionComponent = lazy(() => options .loader({ config, inputs }) @@ -86,7 +87,7 @@ export function createPageExtension< path: config.path, routeRef: options.routeRef, element: ( - + ), diff --git a/packages/frontend-plugin-api/src/extensions/createSignInPageExtension.test.tsx b/packages/frontend-plugin-api/src/extensions/createSignInPageExtension.test.tsx new file mode 100644 index 0000000000..d8835ae788 --- /dev/null +++ b/packages/frontend-plugin-api/src/extensions/createSignInPageExtension.test.tsx @@ -0,0 +1,47 @@ +/* + * 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. + */ + +import React from 'react'; +import { createExtensionTester } from '@backstage/frontend-test-utils'; +import { screen } from '@testing-library/react'; +import { createSignInPageExtension } from './createSignInPageExtension'; +import { coreExtensionData, createExtension } from '../wiring'; + +describe('createSignInPageExtension', () => { + it('renders a sign-in page', async () => { + const SignInPage = createSignInPageExtension({ + name: 'test', + loader: async () => () =>
, + }); + + createExtensionTester( + createExtension({ + name: 'dummy', + attachTo: { id: 'ignored', input: 'ignored' }, + output: { + element: coreExtensionData.reactElement, + }, + factory: () => ({ element:
}), + }), + ) + .add(SignInPage) + .render(); + + await expect( + screen.findByTestId('sign-in-page'), + ).resolves.toBeInTheDocument(); + }); +}); diff --git a/packages/frontend-plugin-api/src/extensions/createSignInPageExtension.tsx b/packages/frontend-plugin-api/src/extensions/createSignInPageExtension.tsx new file mode 100644 index 0000000000..d04c29fb9b --- /dev/null +++ b/packages/frontend-plugin-api/src/extensions/createSignInPageExtension.tsx @@ -0,0 +1,80 @@ +/* + * 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. + */ + +import React, { ComponentType, lazy } from 'react'; +import { ExtensionBoundary } from '../components'; +import { PortableSchema } from '../schema'; +import { + createExtension, + ResolvedExtensionInputs, + AnyExtensionInputMap, + createExtensionDataRef, + ExtensionDefinition, +} from '../wiring'; +import { Expand } from '../types'; +import { SignInPageProps } from '@backstage/core-plugin-api'; + +/** @internal */ +export const signInPageComponentDataRef = + createExtensionDataRef>('core.signInPage'); + +/** + * + * @public + */ +export function createSignInPageExtension< + TConfig extends {}, + TInputs extends AnyExtensionInputMap, +>(options: { + namespace?: string; + name?: string; + attachTo?: { id: string; input: string }; + configSchema?: PortableSchema; + disabled?: boolean; + inputs?: TInputs; + loader: (options: { + config: TConfig; + inputs: Expand>; + }) => Promise>; +}): ExtensionDefinition { + return createExtension({ + kind: 'sign-in-page', + namespace: options?.namespace, + name: options?.name, + attachTo: options.attachTo ?? { id: 'core/router', input: 'signInPage' }, + configSchema: options.configSchema, + inputs: options.inputs, + disabled: options.disabled, + output: { + component: signInPageComponentDataRef, + }, + factory({ config, inputs, node }) { + const ExtensionComponent = lazy(() => + options + .loader({ config, inputs }) + .then(component => ({ default: component })), + ); + + return { + component: props => ( + + + + ), + }; + }, + }); +} diff --git a/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts b/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts index d41121d51c..5554a08874 100644 --- a/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts +++ b/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts @@ -20,7 +20,9 @@ import { AppTheme } from '@backstage/core-plugin-api'; /** @public */ export function createThemeExtension(theme: AppTheme) { return createExtension({ - id: `themes.${theme.id}`, + kind: 'theme', + namespace: 'app', + name: theme.id, attachTo: { id: 'core', input: 'themes' }, output: { theme: coreExtensionData.theme, diff --git a/packages/frontend-plugin-api/src/extensions/createTranslationExtension.test.ts b/packages/frontend-plugin-api/src/extensions/createTranslationExtension.test.ts new file mode 100644 index 0000000000..3a0eee91b5 --- /dev/null +++ b/packages/frontend-plugin-api/src/extensions/createTranslationExtension.test.ts @@ -0,0 +1,128 @@ +/* + * 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. + */ + +import { + createTranslationRef, + createTranslationMessages, + createTranslationResource, +} from '@backstage/core-plugin-api/alpha'; +import { createTranslationExtension } from './createTranslationExtension'; + +const translationRef = createTranslationRef({ + id: 'test', + messages: { + a: 'a', + b: 'b', + }, +}); + +describe('createTranslationExtension', () => { + it('creates a translation message extension', () => { + const messages = createTranslationMessages({ + ref: translationRef, + messages: { + a: 'A', + }, + }); + const extension = createTranslationExtension({ resource: messages }); + + expect(extension).toEqual({ + $$type: '@backstage/ExtensionDefinition', + kind: 'translation', + namespace: 'test', + attachTo: { id: 'core', input: 'translations' }, + disabled: false, + inputs: {}, + output: { + resource: createTranslationExtension.translationDataRef, + }, + factory: expect.any(Function), + }); + + expect(extension.factory({} as any)).toEqual({ + resource: messages, + }); + }); + + it('creates a translation resource extension', () => { + const resource = createTranslationResource({ + ref: translationRef, + translations: { + sv: () => + Promise.resolve({ + default: createTranslationMessages({ + ref: translationRef, + messages: { + a: 'Ä', + b: 'Ö', + }, + }), + }), + }, + }); + const extension = createTranslationExtension({ resource }); + + expect(extension).toEqual({ + $$type: '@backstage/ExtensionDefinition', + kind: 'translation', + namespace: 'test', + attachTo: { id: 'core', input: 'translations' }, + disabled: false, + inputs: {}, + output: { + resource: createTranslationExtension.translationDataRef, + }, + factory: expect.any(Function), + }); + + expect(extension.factory({} as any)).toEqual({ resource }); + }); + + it('creates a translation resource extension with a name', () => { + expect( + createTranslationExtension({ + name: 'sv', + resource: createTranslationResource({ + ref: translationRef, + translations: { + sv: () => + Promise.resolve({ + default: createTranslationMessages({ + ref: translationRef, + messages: { + a: 'Ä', + b: 'Ö', + }, + }), + }), + }, + }), + }), + ).toEqual({ + $$type: '@backstage/ExtensionDefinition', + kind: 'translation', + namespace: 'test', + name: 'sv', + attachTo: { id: 'core', input: 'translations' }, + disabled: false, + inputs: {}, + output: { + resource: createTranslationExtension.translationDataRef, + }, + factory: expect.any(Function), + }); + }); +}); diff --git a/packages/frontend-plugin-api/src/extensions/createTranslationExtension.ts b/packages/frontend-plugin-api/src/extensions/createTranslationExtension.ts new file mode 100644 index 0000000000..59cc87948f --- /dev/null +++ b/packages/frontend-plugin-api/src/extensions/createTranslationExtension.ts @@ -0,0 +1,42 @@ +/* + * 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. + */ + +import { TranslationMessages, TranslationResource } from '../translation'; +import { createExtension, createExtensionDataRef } from '../wiring'; + +/** @public */ +export function createTranslationExtension(options: { + name?: string; + resource: TranslationResource | TranslationMessages; +}) { + return createExtension({ + kind: 'translation', + namespace: options.resource.id, + name: options.name, + attachTo: { id: 'core', input: 'translations' }, + output: { + resource: createTranslationExtension.translationDataRef, + }, + factory: () => ({ resource: options.resource }), + }); +} + +/** @public */ +export namespace createTranslationExtension { + export const translationDataRef = createExtensionDataRef< + TranslationResource | TranslationMessages + >('core.translationResource'); +} diff --git a/packages/frontend-plugin-api/src/extensions/index.ts b/packages/frontend-plugin-api/src/extensions/index.ts index 00cf4f919c..80ad0290dd 100644 --- a/packages/frontend-plugin-api/src/extensions/index.ts +++ b/packages/frontend-plugin-api/src/extensions/index.ts @@ -17,4 +17,7 @@ export { createApiExtension } from './createApiExtension'; export { createPageExtension } from './createPageExtension'; export { createNavItemExtension } from './createNavItemExtension'; +export { createSignInPageExtension } from './createSignInPageExtension'; export { createThemeExtension } from './createThemeExtension'; +export { createComponentExtension } from './createComponentExtension'; +export { createTranslationExtension } from './createTranslationExtension'; diff --git a/plugins/kubernetes-react/src/utils/index.ts b/packages/frontend-plugin-api/src/icons/index.ts similarity index 92% rename from plugins/kubernetes-react/src/utils/index.ts rename to packages/frontend-plugin-api/src/icons/index.ts index d47afaf668..9c9e45e54c 100644 --- a/plugins/kubernetes-react/src/utils/index.ts +++ b/packages/frontend-plugin-api/src/icons/index.ts @@ -13,4 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * from './clusterLinks'; + +export type { IconComponent } from './types'; diff --git a/packages/frontend-plugin-api/src/icons/types.ts b/packages/frontend-plugin-api/src/icons/types.ts new file mode 100644 index 0000000000..4d54629de2 --- /dev/null +++ b/packages/frontend-plugin-api/src/icons/types.ts @@ -0,0 +1,45 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ComponentType } from 'react'; + +/** + * IconComponent is the common icon type used throughout Backstage when + * working with and rendering generic icons, including the app system icons. + * + * @remarks + * + * The type is based on SvgIcon from Material UI, but both do not what the plugin-api + * package to have a dependency on Material UI, nor do we want the props to be as broad + * as the SvgIconProps interface. + * + * If you have the need to forward additional props from SvgIconProps, you can + * open an issue or submit a PR to the main Backstage repo. When doing so please + * also describe your use-case and reasoning of the addition. + * + * @public + */ + +export type IconComponent = ComponentType< + /* Material UI v4 */ + | { + fontSize?: 'large' | 'small' | 'default' | 'inherit'; + } + /* Material UI v5: https://mui.com/material-ui/migration/v5-component-changes/#icon */ + | { + fontSize?: 'medium' | 'large' | 'small' | 'inherit'; + } +>; diff --git a/packages/frontend-plugin-api/src/index.ts b/packages/frontend-plugin-api/src/index.ts index 498bc96a77..263380b1f8 100644 --- a/packages/frontend-plugin-api/src/index.ts +++ b/packages/frontend-plugin-api/src/index.ts @@ -20,9 +20,19 @@ * @packageDocumentation */ +export * from './analytics'; export * from './apis'; export * from './components'; export * from './extensions'; +export * from './icons'; export * from './routing'; export * from './schema'; +export * from './apis/system'; +export * from './translation'; export * from './wiring'; + +export type { + CoreProgressProps, + CoreNotFoundErrorPageProps, + CoreErrorBoundaryFallbackProps, +} from './types'; diff --git a/packages/frontend-plugin-api/src/translation/index.ts b/packages/frontend-plugin-api/src/translation/index.ts new file mode 100644 index 0000000000..ef3ccccbe3 --- /dev/null +++ b/packages/frontend-plugin-api/src/translation/index.ts @@ -0,0 +1,28 @@ +/* + * 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 { + type TranslationMessages, + type TranslationMessagesOptions, + type TranslationResource, + type TranslationResourceOptions, + type TranslationRef, + type TranslationRefOptions, + createTranslationMessages, + createTranslationResource, + createTranslationRef, + useTranslationRef, +} from '@backstage/core-plugin-api/alpha'; diff --git a/packages/frontend-plugin-api/src/types.ts b/packages/frontend-plugin-api/src/types.ts index 8b6f02a942..4d0fb1ac4b 100644 --- a/packages/frontend-plugin-api/src/types.ts +++ b/packages/frontend-plugin-api/src/types.ts @@ -14,9 +14,27 @@ * limitations under the License. */ +import { ReactNode } from 'react'; +import { BackstagePlugin } from './wiring'; + // TODO(Rugvip): This might be a quite useful utility type, maybe add to @backstage/types? /** * Utility type to expand type aliases into their equivalent type. * @ignore */ export type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; + +/** @public */ +export type CoreProgressProps = {}; + +/** @public */ +export type CoreNotFoundErrorPageProps = { + children?: ReactNode; +}; + +/** @public */ +export type CoreErrorBoundaryFallbackProps = { + plugin?: BackstagePlugin; + error: Error; + resetError: () => void; +}; diff --git a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts index 023eab57e1..d52a672679 100644 --- a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts +++ b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts @@ -14,14 +14,15 @@ * limitations under the License. */ -import { JSX } from 'react'; +import { ComponentType, JSX } from 'react'; import { AnyApiFactory, AppTheme, IconComponent, } from '@backstage/core-plugin-api'; -import { createExtensionDataRef } from './createExtensionDataRef'; import { RouteRef } from '../routing'; +import { ComponentRef } from '../components'; +import { createExtensionDataRef } from './createExtensionDataRef'; /** @public */ export type NavTarget = { @@ -30,6 +31,12 @@ export type NavTarget = { routeRef: RouteRef; }; +/** @public */ +export type LogoElements = { + logoIcon?: JSX.Element; + logoFull?: JSX.Element; +}; + /** @public */ export const coreExtensionData = { reactElement: createExtensionDataRef('core.reactElement'), @@ -38,4 +45,9 @@ export const coreExtensionData = { routeRef: createExtensionDataRef('core.routing.ref'), navTarget: createExtensionDataRef('core.nav.target'), theme: createExtensionDataRef('core.theme'), + logoElements: createExtensionDataRef('core.logos'), + component: createExtensionDataRef<{ + ref: ComponentRef; + impl: ComponentType; + }>('core.component'), }; diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.test.ts b/packages/frontend-plugin-api/src/wiring/createExtension.test.ts index 071272d58f..22db95082a 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.test.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.test.ts @@ -25,7 +25,7 @@ function unused(..._any: any[]) {} describe('createExtension', () => { it('should create an extension with a simple output', () => { const baseConfig = { - id: 'test', + namespace: 'test', attachTo: { id: 'root', input: 'default' }, output: { foo: stringData, @@ -39,7 +39,7 @@ describe('createExtension', () => { }; }, }); - expect(extension.id).toBe('test'); + expect(extension.namespace).toBe('test'); // When declared as an error function without a block the TypeScript errors // are a more specific and will point at the property that is problematic. @@ -163,7 +163,7 @@ describe('createExtension', () => { it('should create an extension with a some optional output', () => { const baseConfig = { - id: 'test', + namespace: 'test', attachTo: { id: 'root', input: 'default' }, output: { foo: stringData, @@ -176,7 +176,7 @@ describe('createExtension', () => { foo: 'bar', }), }); - expect(extension.id).toBe('test'); + expect(extension.namespace).toBe('test'); createExtension({ ...baseConfig, @@ -233,7 +233,7 @@ describe('createExtension', () => { it('should create an extension with input', () => { const extension = createExtension({ - id: 'test', + namespace: 'test', attachTo: { id: 'root', input: 'default' }, inputs: { mixed: createExtensionInput({ @@ -251,34 +251,34 @@ describe('createExtension', () => { foo: stringData, }, factory({ inputs }) { - const a1: string = inputs.mixed?.[0].required; + const a1: string = inputs.mixed?.[0].output.required; // @ts-expect-error - const a2: number = inputs.mixed?.[0].required; + const a2: number = inputs.mixed?.[0].output.required; // @ts-expect-error - const a3: any = inputs.mixed?.[0].nonExistent; + const a3: any = inputs.mixed?.[0].output.nonExistent; unused(a1, a2, a3); - const b1: string | undefined = inputs.mixed?.[0].optional; + const b1: string | undefined = inputs.mixed?.[0].output.optional; // @ts-expect-error - const b2: string = inputs.mixed?.[0].optional; + const b2: string = inputs.mixed?.[0].output.optional; // @ts-expect-error - const b3: number = inputs.mixed?.[0].optional; + const b3: number = inputs.mixed?.[0].output.optional; // @ts-expect-error - const b4: number | undefined = inputs.mixed?.[0].optional; + const b4: number | undefined = inputs.mixed?.[0].output.optional; unused(b1, b2, b3, b4); - const c1: string = inputs.onlyRequired?.[0].required; + const c1: string = inputs.onlyRequired?.[0].output.required; // @ts-expect-error - const c2: number = inputs.onlyRequired?.[0].required; + const c2: number = inputs.onlyRequired?.[0].output.required; unused(c1, c2); - const d1: string | undefined = inputs.onlyOptional?.[0].optional; + const d1: string | undefined = inputs.onlyOptional?.[0].output.optional; // @ts-expect-error - const d2: string = inputs.onlyOptional?.[0].optional; + const d2: string = inputs.onlyOptional?.[0].output.optional; // @ts-expect-error - const d3: number = inputs.onlyOptional?.[0].optional; + const d3: number = inputs.onlyOptional?.[0].output.optional; // @ts-expect-error - const d4: number | undefined = inputs.onlyOptional?.[0].optional; + const d4: number | undefined = inputs.onlyOptional?.[0].output.optional; unused(d1, d2, d3, d4); return { @@ -286,6 +286,6 @@ describe('createExtension', () => { }; }, }); - expect(extension.id).toBe('test'); + expect(extension.namespace).toBe('test'); }); }); diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.ts b/packages/frontend-plugin-api/src/wiring/createExtension.ts index ff011a5875..ccb93f44ea 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.ts @@ -14,11 +14,11 @@ * limitations under the License. */ +import { AppNode } from '../apis'; import { PortableSchema } from '../schema'; import { Expand } from '../types'; import { ExtensionDataRef } from './createExtensionDataRef'; import { ExtensionInput } from './createExtensionInput'; -import { BackstagePlugin } from './createPlugin'; /** @public */ export type AnyExtensionDataMap = { @@ -52,18 +52,28 @@ export type ExtensionDataValues = { }; /** - * Converts an extension input map into the matching concrete input values type. + * Convert a single extension input into a matching resolved input. * @public */ -export type ExtensionInputValues< +export type ResolvedExtensionInput = + { + node: AppNode; + output: ExtensionDataValues; + }; + +/** + * Converts an extension input map into a matching collection of resolved inputs. + * @public + */ +export type ResolvedExtensionInputs< TInputs extends { [name in string]: ExtensionInput }, > = { [InputName in keyof TInputs]: false extends TInputs[InputName]['config']['singleton'] - ? Array>> + ? Array>> : false extends TInputs[InputName]['config']['optional'] - ? Expand> + ? Expand> : Expand< - ExtensionDataValues | undefined + ResolvedExtensionInput | undefined >; }; @@ -73,19 +83,39 @@ export interface CreateExtensionOptions< TInputs extends AnyExtensionInputMap, TConfig, > { - id: string; + kind?: string; + namespace?: string; + name?: string; attachTo: { id: string; input: string }; disabled?: boolean; inputs?: TInputs; output: TOutput; configSchema?: PortableSchema; factory(options: { - source?: BackstagePlugin; + node: AppNode; config: TConfig; - inputs: Expand>; + inputs: Expand>; }): Expand>; } +/** @public */ +export interface ExtensionDefinition { + $$type: '@backstage/ExtensionDefinition'; + kind?: string; + namespace?: string; + name?: string; + attachTo: { id: string; input: string }; + disabled: boolean; + inputs: AnyExtensionInputMap; + output: AnyExtensionDataMap; + configSchema?: PortableSchema; + factory(options: { + node: AppNode; + config: TConfig; + inputs: ResolvedExtensionInputs; + }): ExtensionDataValues; +} + /** @public */ export interface Extension { $$type: '@backstage/Extension'; @@ -96,12 +126,9 @@ export interface Extension { output: AnyExtensionDataMap; configSchema?: PortableSchema; factory(options: { - source?: BackstagePlugin; + node: AppNode; config: TConfig; - inputs: Record< - string, - undefined | Record | Array> - >; + inputs: ResolvedExtensionInputs; }): ExtensionDataValues; } @@ -112,16 +139,21 @@ export function createExtension< TConfig = never, >( options: CreateExtensionOptions, -): Extension { +): ExtensionDefinition { return { - ...options, + $$type: '@backstage/ExtensionDefinition', + kind: options.kind, + namespace: options.namespace, + name: options.name, + attachTo: options.attachTo, disabled: options.disabled ?? false, - $$type: '@backstage/Extension', inputs: options.inputs ?? {}, + output: options.output, + configSchema: options.configSchema, factory({ inputs, ...rest }) { // TODO: Simplify this, but TS wouldn't infer the input type for some reason return options.factory({ - inputs: inputs as Expand>, + inputs: inputs as Expand>, ...rest, }); }, diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.test.ts b/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.test.ts index eb69f954e4..772a214490 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.test.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.test.ts @@ -26,6 +26,7 @@ describe('createExtensionOverrides', () => { { "$$type": "@backstage/ExtensionOverrides", "extensions": [], + "featureFlags": [], "version": "v1", } `); @@ -36,7 +37,21 @@ describe('createExtensionOverrides', () => { createExtensionOverrides({ extensions: [ createExtension({ - id: 'a', + name: 'a', + attachTo: { id: 'core', input: 'apis' }, + output: {}, + factory: () => ({}), + }), + createExtension({ + namespace: 'b', + attachTo: { id: 'core', input: 'apis' }, + output: {}, + factory: () => ({}), + }), + createExtension({ + kind: 'k', + namespace: 'c', + name: 'n', attachTo: { id: 'core', input: 'apis' }, output: {}, factory: () => ({}), @@ -53,13 +68,41 @@ describe('createExtensionOverrides', () => { "id": "core", "input": "apis", }, + "configSchema": undefined, "disabled": false, "factory": [Function], "id": "a", "inputs": {}, "output": {}, }, + { + "$$type": "@backstage/Extension", + "attachTo": { + "id": "core", + "input": "apis", + }, + "configSchema": undefined, + "disabled": false, + "factory": [Function], + "id": "b", + "inputs": {}, + "output": {}, + }, + { + "$$type": "@backstage/Extension", + "attachTo": { + "id": "core", + "input": "apis", + }, + "configSchema": undefined, + "disabled": false, + "factory": [Function], + "id": "k:c/n", + "inputs": {}, + "output": {}, + }, ], + "featureFlags": [], "version": "v1", } `); @@ -69,7 +112,7 @@ describe('createExtensionOverrides', () => { const overrides = createExtensionOverrides({ extensions: [ createExtension({ - id: 'a', + namespace: 'a', attachTo: { id: 'core', input: 'apis' }, output: {}, factory: () => ({}), diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts b/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts index 2c64229eb9..6c368a0e8b 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts @@ -14,22 +14,26 @@ * limitations under the License. */ -import { Extension } from './createExtension'; +import { Extension, ExtensionDefinition } from './createExtension'; +import { resolveExtensionDefinition } from './resolveExtensionDefinition'; +import { FeatureFlagConfig } from './types'; /** @public */ export interface ExtensionOverridesOptions { - extensions: Extension[]; + extensions: ExtensionDefinition[]; + featureFlags?: FeatureFlagConfig[]; } /** @public */ export interface ExtensionOverrides { - $$type: '@backstage/ExtensionOverrides'; + readonly $$type: '@backstage/ExtensionOverrides'; } /** @internal */ export interface InternalExtensionOverrides extends ExtensionOverrides { - version: string; - extensions: Extension[]; + readonly version: 'v1'; + readonly extensions: Extension[]; + readonly featureFlags: FeatureFlagConfig[]; } /** @public */ @@ -39,7 +43,8 @@ export function createExtensionOverrides( return { $$type: '@backstage/ExtensionOverrides', version: 'v1', - extensions: options.extensions, + extensions: options.extensions.map(def => resolveExtensionDefinition(def)), + featureFlags: options.featureFlags ?? [], } as InternalExtensionOverrides; } @@ -50,12 +55,12 @@ export function toInternalExtensionOverrides( const internal = overrides as InternalExtensionOverrides; if (internal.$$type !== '@backstage/ExtensionOverrides') { throw new Error( - `Invalid translation resource, bad type '${internal.$$type}'`, + `Invalid extension overrides instance, bad type '${internal.$$type}'`, ); } if (internal.version !== 'v1') { throw new Error( - `Invalid translation resource, bad version '${internal.version}'`, + `Invalid extension overrides instance, bad version '${internal.version}'`, ); } return internal; diff --git a/packages/frontend-plugin-api/src/wiring/createPlugin.test.ts b/packages/frontend-plugin-api/src/wiring/createPlugin.test.ts index 42648fcd96..18054a5de2 100644 --- a/packages/frontend-plugin-api/src/wiring/createPlugin.test.ts +++ b/packages/frontend-plugin-api/src/wiring/createPlugin.test.ts @@ -28,48 +28,34 @@ import { createExtensionInput } from './createExtensionInput'; const nameExtensionDataRef = createExtensionDataRef('name'); -const TechRadarPage = createExtension({ - id: 'plugin.techradar.page', - attachTo: { id: 'test.output', input: 'names' }, +const Extension1 = createExtension({ + name: '1', + attachTo: { id: 'test/output', input: 'names' }, output: { name: nameExtensionDataRef, }, factory() { - return { name: 'TechRadar' }; + return { name: 'extension-1' }; }, }); -const CatalogPage = createExtension({ - id: 'plugin.catalog.page', - attachTo: { id: 'test.output', input: 'names' }, +const Extension2 = createExtension({ + name: '2', + attachTo: { id: 'test/output', input: 'names' }, output: { name: nameExtensionDataRef, }, configSchema: createSchemaFromZod(z => - z.object({ name: z.string().default('Catalog') }), + z.object({ name: z.string().default('extension-2') }), ), factory({ config }) { return { name: config.name }; }, }); -const TechDocsAddon = createExtension({ - id: 'plugin.techdocs.addon.example', - attachTo: { id: 'plugin.techdocs.page', input: 'addons' }, - output: { - name: nameExtensionDataRef, - }, - configSchema: createSchemaFromZod(z => - z.object({ name: z.string().default('TechDocsAddon') }), - ), - factory({ config }) { - return { name: config.name }; - }, -}); - -const TechDocsPage = createExtension({ - id: 'plugin.techdocs.page', - attachTo: { id: 'test.output', input: 'names' }, +const Extension3 = createExtension({ + name: '3', + attachTo: { id: 'test/output', input: 'names' }, inputs: { addons: createExtensionInput({ name: nameExtensionDataRef, @@ -79,12 +65,42 @@ const TechDocsPage = createExtension({ name: nameExtensionDataRef, }, factory({ inputs }) { - return { name: `TechDocs-${inputs.addons.map(n => n.name).join('-')}` }; + return { + name: `extension-3:${inputs.addons.map(n => n.output.name).join('-')}`, + }; + }, +}); + +const Child = createExtension({ + name: 'child', + attachTo: { id: 'test/3', input: 'addons' }, + output: { + name: nameExtensionDataRef, + }, + configSchema: createSchemaFromZod(z => + z.object({ name: z.string().default('child') }), + ), + factory({ config }) { + return { name: config.name }; + }, +}); + +const Child2 = createExtension({ + name: 'child2', + attachTo: { id: 'test/3', input: 'addons' }, + output: { + name: nameExtensionDataRef, + }, + configSchema: createSchemaFromZod(z => + z.object({ name: z.string().default('child2') }), + ), + factory({ config }) { + return { name: config.name }; }, }); const outputExtension = createExtension({ - id: 'test.output', + name: 'output', attachTo: { id: 'core', input: 'root' }, inputs: { names: createExtensionInput({ @@ -97,7 +113,7 @@ const outputExtension = createExtension({ factory({ inputs }) { return { element: React.createElement('span', {}, [ - `Names: ${inputs.names.map(n => n.name).join(', ')}`, + `Names: ${inputs.names.map(n => n.output.name).join(', ')}`, ]), }; }, @@ -118,40 +134,34 @@ function createTestAppRoot({ describe('createPlugin', () => { it('should create an empty plugin', () => { - const plugin = createPlugin({ id: 'empty' }); + const plugin = createPlugin({ id: 'test' }); expect(plugin).toBeDefined(); }); it('should create a plugin with extension instances', async () => { const plugin = createPlugin({ - id: 'empty', - extensions: [TechRadarPage, CatalogPage, outputExtension], + id: 'test', + extensions: [Extension1, Extension2, outputExtension], }); expect(plugin).toBeDefined(); await renderWithEffects( createTestAppRoot({ features: [plugin], - config: { app: { extensions: [{ 'core.layout': false }] } }, + config: { app: { extensions: [{ 'core/router': false }] } }, }), ); await expect( - screen.findByText('Names: TechRadar, Catalog'), + screen.findByText('Names: extension-1, extension-2'), ).resolves.toBeInTheDocument(); }); it('should create a plugin with nested extension instances', async () => { const plugin = createPlugin({ - id: 'empty', - extensions: [ - TechRadarPage, - CatalogPage, - TechDocsPage, - TechDocsAddon, - outputExtension, - ], + id: 'test', + extensions: [Extension1, Extension2, Extension3, Child, outputExtension], }); expect(plugin).toBeDefined(); @@ -161,10 +171,10 @@ describe('createPlugin', () => { config: { app: { extensions: [ - { 'core.layout': false }, + { 'core/router': false }, { - 'plugin.catalog.page': { - config: { name: 'CatalogRenamed' }, + 'test/2': { + config: { name: 'extension-2-renamed' }, }, }, ], @@ -175,8 +185,63 @@ describe('createPlugin', () => { await expect( screen.findByText( - 'Names: TechRadar, CatalogRenamed, TechDocs-TechDocsAddon', + 'Names: extension-1, extension-2-renamed, extension-3:child', ), ).resolves.toBeInTheDocument(); }); + + it('should create a plugin with nested extension instances and multiple children', async () => { + const plugin = createPlugin({ + id: 'test', + extensions: [ + Extension1, + Extension2, + Extension3, + Child, + Child2, + outputExtension, + ], + }); + expect(plugin).toBeDefined(); + + await renderWithEffects( + createTestAppRoot({ + features: [plugin], + config: { + app: { + extensions: [{ 'core/router': false }], + }, + }, + }), + ); + + await expect( + screen.findByText( + 'Names: extension-1, extension-2, extension-3:child-child2', + ), + ).resolves.toBeInTheDocument(); + }); + + it('should throw on duplicate extensions', async () => { + expect(() => + createPlugin({ + id: 'test', + extensions: [Extension1, Extension1], + }), + ).toThrow("Plugin 'test' provided duplicate extensions: test/1"); + + expect(() => + createPlugin({ + id: 'test', + extensions: [ + Extension1, + Extension2, + Extension2, + Extension3, + Extension3, + Extension3, + ], + }), + ).toThrow("Plugin 'test' provided duplicate extensions: test/2, test/3"); + }); }); diff --git a/packages/frontend-plugin-api/src/wiring/createPlugin.ts b/packages/frontend-plugin-api/src/wiring/createPlugin.ts index 84edd954ef..ecc4d08f9a 100644 --- a/packages/frontend-plugin-api/src/wiring/createPlugin.ts +++ b/packages/frontend-plugin-api/src/wiring/createPlugin.ts @@ -14,8 +14,10 @@ * limitations under the License. */ -import { Extension } from './createExtension'; +import { Extension, ExtensionDefinition } from './createExtension'; import { ExternalRouteRef, RouteRef } from '../routing'; +import { FeatureFlagConfig } from './types'; +import { resolveExtensionDefinition } from './resolveExtensionDefinition'; /** @public */ export type AnyRoutes = { [name in string]: RouteRef }; @@ -31,7 +33,8 @@ export interface PluginOptions< id: string; routes?: Routes; externalRoutes?: ExternalRoutes; - extensions?: Extension[]; + extensions?: ExtensionDefinition[]; + featureFlags?: FeatureFlagConfig[]; } /** @public */ @@ -39,11 +42,20 @@ export interface BackstagePlugin< Routes extends AnyRoutes = AnyRoutes, ExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, > { - $$type: '@backstage/BackstagePlugin'; - id: string; - extensions: Extension[]; - routes: Routes; - externalRoutes: ExternalRoutes; + readonly $$type: '@backstage/BackstagePlugin'; + readonly id: string; + readonly routes: Routes; + readonly externalRoutes: ExternalRoutes; +} + +/** @public */ +export interface InternalBackstagePlugin< + Routes extends AnyRoutes = AnyRoutes, + ExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, +> extends BackstagePlugin { + readonly version: 'v1'; + readonly extensions: Extension[]; + readonly featureFlags: FeatureFlagConfig[]; } /** @public */ @@ -53,11 +65,48 @@ export function createPlugin< >( options: PluginOptions, ): BackstagePlugin { + const extensions = (options.extensions ?? []).map(def => + resolveExtensionDefinition(def, { namespace: options.id }), + ); + + const extensionIds = extensions.map(e => e.id); + if (extensionIds.length !== new Set(extensionIds).size) { + const duplicates = Array.from( + new Set( + extensionIds.filter((id, index) => extensionIds.indexOf(id) !== index), + ), + ); + // TODO(Rugvip): This could provide some more information about the kind + name of the extensions + throw new Error( + `Plugin '${options.id}' provided duplicate extensions: ${duplicates.join( + ', ', + )}`, + ); + } + return { - ...options, + $$type: '@backstage/BackstagePlugin', + version: 'v1', + id: options.id, routes: options.routes ?? ({} as Routes), externalRoutes: options.externalRoutes ?? ({} as ExternalRoutes), - extensions: options.extensions ?? [], - $$type: '@backstage/BackstagePlugin', - }; + featureFlags: options.featureFlags ?? [], + extensions, + } as InternalBackstagePlugin; +} + +/** @internal */ +export function toInternalBackstagePlugin( + plugin: BackstagePlugin, +): InternalBackstagePlugin { + const internal = plugin as InternalBackstagePlugin; + if (internal.$$type !== '@backstage/BackstagePlugin') { + throw new Error(`Invalid plugin instance, bad type '${internal.$$type}'`); + } + if (internal.version !== 'v1') { + throw new Error( + `Invalid plugin instance, bad version '${internal.version}'`, + ); + } + return internal; } diff --git a/packages/frontend-plugin-api/src/wiring/index.ts b/packages/frontend-plugin-api/src/wiring/index.ts index ec685d6c81..3f33910ca7 100644 --- a/packages/frontend-plugin-api/src/wiring/index.ts +++ b/packages/frontend-plugin-api/src/wiring/index.ts @@ -14,13 +14,19 @@ * limitations under the License. */ -export { coreExtensionData, type NavTarget } from './coreExtensionData'; +export { + coreExtensionData, + type LogoElements, + type NavTarget, +} from './coreExtensionData'; export { createExtension, type Extension, + type ExtensionDefinition, type CreateExtensionOptions, type ExtensionDataValues, - type ExtensionInputValues, + type ResolvedExtensionInput, + type ResolvedExtensionInputs, type AnyExtensionInputMap, type AnyExtensionDataMap, } from './createExtension'; @@ -45,3 +51,4 @@ export { type ExtensionOverrides, type ExtensionOverridesOptions, } from './createExtensionOverrides'; +export type { FeatureFlagConfig } from './types'; diff --git a/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.test.ts b/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.test.ts new file mode 100644 index 0000000000..8f3755ac5d --- /dev/null +++ b/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.test.ts @@ -0,0 +1,48 @@ +/* + * 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. + */ + +import { ExtensionDefinition } from './createExtension'; +import { resolveExtensionDefinition } from './resolveExtensionDefinition'; + +describe('resolveExtensionDefinition', () => { + it.each([ + [{ namespace: 'ns' }, 'ns'], + [{ namespace: 'n' }, 'n'], + [{ namespace: 'ns', name: 'n' }, 'ns/n'], + [{ kind: 'k', namespace: 'ns' }, 'k:ns'], + [{ kind: 'k', namespace: 'ns', name: 'n' }, 'k:ns/n'], + ])(`should resolve extension IDs %s`, (definition, expected) => { + const resolved = resolveExtensionDefinition( + definition as ExtensionDefinition, + ); + expect(resolved.id).toBe(expected); + }); + + it('should fail to resolve extension ID without namespace', () => { + expect(() => + resolveExtensionDefinition({ + kind: 'k', + } as ExtensionDefinition), + ).toThrow( + 'Extension must declare an explicit namespace or name as it could not be resolved from context, kind=k namespace=undefined name=undefined', + ); + expect(() => + resolveExtensionDefinition({} as ExtensionDefinition), + ).toThrow( + 'Extension must declare an explicit namespace or name as it could not be resolved from context, kind=undefined namespace=undefined name=undefined', + ); + }); +}); diff --git a/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts b/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts new file mode 100644 index 0000000000..42f3a75246 --- /dev/null +++ b/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts @@ -0,0 +1,40 @@ +/* + * 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. + */ + +import { Extension, ExtensionDefinition } from './createExtension'; + +/** @internal */ +export function resolveExtensionDefinition( + definition: ExtensionDefinition, + context?: { namespace?: string }, +): Extension { + const { name, kind, namespace: _, ...rest } = definition; + const namespace = definition.namespace ?? context?.namespace; + + const namePart = + name && namespace ? `${namespace}/${name}` : namespace || name; + if (!namePart) { + throw new Error( + `Extension must declare an explicit namespace or name as it could not be resolved from context, kind=${kind} namespace=${namespace} name=${name}`, + ); + } + + return { + ...rest, + id: kind ? `${kind}:${namePart}` : namePart, + $$type: '@backstage/Extension', + }; +} diff --git a/packages/frontend-plugin-api/src/wiring/types.ts b/packages/frontend-plugin-api/src/wiring/types.ts new file mode 100644 index 0000000000..ab9f07b35e --- /dev/null +++ b/packages/frontend-plugin-api/src/wiring/types.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +/** + * Feature flag configuration. + * + * @public + */ +export type FeatureFlagConfig = { + /** Feature flag name */ + name: string; +}; diff --git a/plugins/catalog-graphql/.eslintrc.js b/packages/frontend-test-utils/.eslintrc.js similarity index 100% rename from plugins/catalog-graphql/.eslintrc.js rename to packages/frontend-test-utils/.eslintrc.js diff --git a/packages/frontend-test-utils/CHANGELOG.md b/packages/frontend-test-utils/CHANGELOG.md new file mode 100644 index 0000000000..a141d85d90 --- /dev/null +++ b/packages/frontend-test-utils/CHANGELOG.md @@ -0,0 +1,40 @@ +# @backstage/frontend-test-utils + +## 0.1.0-next.2 + +### Patch Changes + +- 818eea4: Updates for compatibility with the new extension IDs. +- b9aa6e4: Migrate `renderInTestApp` to `@backstage/frontend-test-utils` for testing individual React components in an app. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/frontend-app-api@0.4.0-next.2 + - @backstage/test-utils@1.4.6-next.2 + - @backstage/types@1.1.1 + +## 0.1.0-next.1 + +### Patch Changes + +- e539735435: Updates for `core.router` addition. +- c21c9cf07b: Re-export mock API implementations as well as `TestApiProvider`, `TestApiRegistry`, `withLogCollector`, and `setupRequestMockHandlers` from `@backstage/test-utils`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/frontend-app-api@0.4.0-next.1 + - @backstage/test-utils@1.4.6-next.1 + - @backstage/types@1.1.1 + +## 0.1.0-next.0 + +### Minor Changes + +- 59fabd5106: New testing utility library for `@backstage/frontend-app-api` and `@backstage/frontend-plugin-api`. + +### Patch Changes + +- 59fabd5106: Added `createExtensionTester` for rendering extensions in tests. +- Updated dependencies + - @backstage/frontend-app-api@0.3.1-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/test-utils@1.4.6-next.0 + - @backstage/types@1.1.1 diff --git a/packages/frontend-test-utils/README.md b/packages/frontend-test-utils/README.md new file mode 100644 index 0000000000..50f853d9ed --- /dev/null +++ b/packages/frontend-test-utils/README.md @@ -0,0 +1,12 @@ +# @backstage/frontend-test-utils + +Contains utilities that can be used when testing frontend features such as extensions. + +## Installation + +Install the package via Yarn into your own packages: + +```sh +cd # if within a monorepo +yarn add --dev @backstage/frontend-test-utils +``` diff --git a/packages/frontend-test-utils/api-report.md b/packages/frontend-test-utils/api-report.md new file mode 100644 index 0000000000..36fc5e30b6 --- /dev/null +++ b/packages/frontend-test-utils/api-report.md @@ -0,0 +1,80 @@ +## API Report File for "@backstage/frontend-test-utils" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { ErrorWithContext } from '@backstage/test-utils'; +import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; +import { JsonObject } from '@backstage/types'; +import { MockAnalyticsApi } from '@backstage/test-utils'; +import { MockConfigApi } from '@backstage/test-utils'; +import { MockErrorApi } from '@backstage/test-utils'; +import { MockErrorApiOptions } from '@backstage/test-utils'; +import { MockFetchApi } from '@backstage/test-utils'; +import { MockFetchApiOptions } from '@backstage/test-utils'; +import { MockPermissionApi } from '@backstage/test-utils'; +import { MockStorageApi } from '@backstage/test-utils'; +import { MockStorageBucket } from '@backstage/test-utils'; +import { RenderResult } from '@testing-library/react'; +import { setupRequestMockHandlers } from '@backstage/test-utils'; +import { TestApiProvider } from '@backstage/test-utils'; +import { TestApiProviderProps } from '@backstage/test-utils'; +import { TestApiRegistry } from '@backstage/test-utils'; +import { withLogCollector } from '@backstage/test-utils'; + +// @public (undocumented) +export function createExtensionTester( + subject: ExtensionDefinition, + options?: { + config?: TConfig; + }, +): ExtensionTester; + +export { ErrorWithContext }; + +// @public (undocumented) +export class ExtensionTester { + // (undocumented) + add( + extension: ExtensionDefinition, + options?: { + config?: TConfig; + }, + ): ExtensionTester; + // (undocumented) + render(options?: { config?: JsonObject }): RenderResult; +} + +export { MockAnalyticsApi }; + +export { MockConfigApi }; + +export { MockErrorApi }; + +export { MockErrorApiOptions }; + +export { MockFetchApi }; + +export { MockFetchApiOptions }; + +export { MockPermissionApi }; + +export { MockStorageApi }; + +export { MockStorageBucket }; + +// @public +export function renderInTestApp(element: JSX.Element): RenderResult; + +export { setupRequestMockHandlers }; + +export { TestApiProvider }; + +export { TestApiProviderProps }; + +export { TestApiRegistry }; + +export { withLogCollector }; +``` diff --git a/packages/frontend-test-utils/catalog-info.yaml b/packages/frontend-test-utils/catalog-info.yaml new file mode 100644 index 0000000000..e2d2a57897 --- /dev/null +++ b/packages/frontend-test-utils/catalog-info.yaml @@ -0,0 +1,9 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-frontend-test-utils + title: '@backstage/frontend-test-utils' +spec: + lifecycle: experimental + type: backstage-web-library + owner: maintainers diff --git a/packages/frontend-test-utils/package.json b/packages/frontend-test-utils/package.json new file mode 100644 index 0000000000..9fba262c21 --- /dev/null +++ b/packages/frontend-test-utils/package.json @@ -0,0 +1,42 @@ +{ + "name": "@backstage/frontend-test-utils", + "version": "0.1.0-next.2", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "web-library" + }, + "sideEffects": false, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@testing-library/jest-dom": "^6.0.0" + }, + "files": [ + "dist" + ], + "dependencies": { + "@backstage/frontend-app-api": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@backstage/types": "workspace:^" + }, + "peerDependencies": { + "@testing-library/react": "^12.1.3 || ^13.0.0 || ^14.0.0", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0" + } +} diff --git a/packages/frontend-test-utils/src/apis/index.ts b/packages/frontend-test-utils/src/apis/index.ts new file mode 100644 index 0000000000..81bd8a7abd --- /dev/null +++ b/packages/frontend-test-utils/src/apis/index.ts @@ -0,0 +1,28 @@ +/* + * 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 { + MockAnalyticsApi, + MockConfigApi, + type ErrorWithContext, + MockErrorApi, + type MockErrorApiOptions, + MockFetchApi, + type MockFetchApiOptions, + MockPermissionApi, + MockStorageApi, + type MockStorageBucket, +} from '@backstage/test-utils'; diff --git a/packages/frontend-test-utils/src/app/createExtensionTester.test.tsx b/packages/frontend-test-utils/src/app/createExtensionTester.test.tsx new file mode 100644 index 0000000000..e738bee7d1 --- /dev/null +++ b/packages/frontend-test-utils/src/app/createExtensionTester.test.tsx @@ -0,0 +1,68 @@ +/* + * 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. + */ + +import { + coreExtensionData, + createExtension, +} from '@backstage/frontend-plugin-api'; +import { screen } from '@testing-library/react'; +import React from 'react'; +import { createExtensionTester } from './createExtensionTester'; + +describe('createExtensionTester', () => { + it('should render a simple extension', async () => { + createExtensionTester( + createExtension({ + namespace: 'test', + attachTo: { id: 'ignored', input: 'ignored' }, + output: { element: coreExtensionData.reactElement }, + factory: () => ({ element:
test
}), + }), + ).render(); + + await expect(screen.findByText('test')).resolves.toBeInTheDocument(); + }); + + it('should render an extension even if disabled by default', async () => { + createExtensionTester( + createExtension({ + namespace: 'test', + attachTo: { id: 'ignored', input: 'ignored' }, + disabled: true, + output: { element: coreExtensionData.reactElement }, + factory: () => ({ element:
test
}), + }), + ).render(); + + await expect(screen.findByText('test')).resolves.toBeInTheDocument(); + }); + + it("should fail to render an extension that doesn't output a react element", async () => { + expect(() => + createExtensionTester( + createExtension({ + namespace: 'test', + attachTo: { id: 'ignored', input: 'ignored' }, + disabled: true, + output: { path: coreExtensionData.routePath }, + factory: () => ({ path: '/foo' }), + }), + ).render(), + ).toThrow( + "Failed to instantiate extension 'core/router', input 'children' did not receive required extension data 'core.reactElement' from extension 'test'", + ); + }); +}); diff --git a/packages/frontend-test-utils/src/app/createExtensionTester.ts b/packages/frontend-test-utils/src/app/createExtensionTester.ts new file mode 100644 index 0000000000..257a47439c --- /dev/null +++ b/packages/frontend-test-utils/src/app/createExtensionTester.ts @@ -0,0 +1,124 @@ +/* + * 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. + */ + +import { createSpecializedApp } from '@backstage/frontend-app-api'; +import { + ExtensionDefinition, + createExtensionOverrides, +} from '@backstage/frontend-plugin-api'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { resolveExtensionDefinition } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition'; +import { MockConfigApi } from '@backstage/test-utils'; +import { JsonArray, JsonObject, JsonValue } from '@backstage/types'; +import { RenderResult, render } from '@testing-library/react'; + +/** @public */ +export class ExtensionTester { + /** @internal */ + static forSubject( + subject: ExtensionDefinition, + options?: { config?: TConfig }, + ): ExtensionTester { + const tester = new ExtensionTester(); + tester.add(subject, options); + return tester; + } + + readonly #extensions = new Array<{ + id: string; + extension: ExtensionDefinition; + config?: JsonValue; + }>(); + + add( + extension: ExtensionDefinition, + options?: { config?: TConfig }, + ): ExtensionTester { + const withNamespace = { + ...extension, + name: !extension.namespace && !extension.name ? 'test' : extension.name, + }; + this.#extensions.push({ + id: resolveExtensionDefinition(withNamespace).id, + extension: withNamespace, + config: options?.config as JsonValue, + }); + + return this; + } + + render(options?: { config?: JsonObject }): RenderResult { + const { config = {} } = options ?? {}; + + const [subject, ...rest] = this.#extensions; + if (!subject) { + throw new Error( + 'No subject found. At least one extension should be added to the tester.', + ); + } + + const extensionsConfig: JsonArray = [ + ...rest.map(entry => ({ + [entry.id]: { + config: entry.config, + }, + })), + { + [subject.id]: { + attachTo: { id: 'core/router', input: 'children' }, + config: subject.config, + disabled: false, + }, + }, + { + 'core/layout': false, + }, + { + 'core/nav': false, + }, + { + 'core/routes': false, + }, + ]; + + const finalConfig = { + ...config, + app: { + ...(typeof config.app === 'object' ? config.app : undefined), + extensions: extensionsConfig, + }, + }; + + const app = createSpecializedApp({ + features: [ + createExtensionOverrides({ + extensions: this.#extensions.map(entry => entry.extension), + }), + ], + config: new MockConfigApi(finalConfig), + }); + + return render(app.createRoot()); + } +} + +/** @public */ +export function createExtensionTester( + subject: ExtensionDefinition, + options?: { config?: TConfig }, +): ExtensionTester { + return ExtensionTester.forSubject(subject, options); +} diff --git a/packages/frontend-test-utils/src/app/index.ts b/packages/frontend-test-utils/src/app/index.ts new file mode 100644 index 0000000000..3f19146c5c --- /dev/null +++ b/packages/frontend-test-utils/src/app/index.ts @@ -0,0 +1,22 @@ +/* + * 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 { + createExtensionTester, + type ExtensionTester, +} from './createExtensionTester'; + +export { renderInTestApp } from './renderInTestApp'; diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx new file mode 100644 index 0000000000..e13d1157ef --- /dev/null +++ b/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx @@ -0,0 +1,27 @@ +/* + * 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. + */ + +import React from 'react'; +import { screen } from '@testing-library/react'; +import { renderInTestApp } from './renderInTestApp'; + +describe('renderInTestApp', () => { + it('should render the given component in a page', async () => { + const Component = () =>
Test
; + renderInTestApp(); + expect(screen.getByText('Test')).toBeInTheDocument(); + }); +}); diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.tsx new file mode 100644 index 0000000000..f4011535a4 --- /dev/null +++ b/packages/frontend-test-utils/src/app/renderInTestApp.tsx @@ -0,0 +1,38 @@ +/* + * 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. + */ + +import { + coreExtensionData, + createExtension, +} from '@backstage/frontend-plugin-api'; +import { createExtensionTester } from './createExtensionTester'; + +/** + * @public + * Renders the given element in a test app, for use in unit tests. + */ +export function renderInTestApp(element: JSX.Element) { + const extension = createExtension({ + namespace: 'test', + attachTo: { id: 'core', input: 'root' }, + output: { + element: coreExtensionData.reactElement, + }, + factory: () => ({ element }), + }); + const tester = createExtensionTester(extension); + return tester.render(); +} diff --git a/packages/frontend-test-utils/src/index.ts b/packages/frontend-test-utils/src/index.ts new file mode 100644 index 0000000000..0dab8e75b7 --- /dev/null +++ b/packages/frontend-test-utils/src/index.ts @@ -0,0 +1,31 @@ +/* + * 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. + */ + +/** + * @packageDocumentation + * + * Contains utilities that can be used when testing frontend features such as extensions. + */ + +export * from './apis'; +export * from './app'; + +export { TestApiProvider, TestApiRegistry } from '@backstage/test-utils'; +export type { TestApiProviderProps } from '@backstage/test-utils'; + +export { withLogCollector } from '@backstage/test-utils'; + +export { setupRequestMockHandlers } from '@backstage/test-utils'; diff --git a/packages/frontend-test-utils/src/setupTests.ts b/packages/frontend-test-utils/src/setupTests.ts new file mode 100644 index 0000000000..c30f1d15cb --- /dev/null +++ b/packages/frontend-test-utils/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +import '@testing-library/jest-dom'; diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index bf652b4170..34a24e7602 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/integration-react +## 1.1.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/config@1.1.1 + +## 1.1.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/config@1.1.1 + ## 1.1.21 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index 23cfbcb589..4c7defc2d4 100644 --- a/packages/integration-react/package.json +++ b/packages/integration-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration-react", "description": "Frontend package for managing integrations towards external systems", - "version": "1.1.21", + "version": "1.1.22-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index eac92f3009..74dee088d5 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/integration +## 1.8.0-next.1 + +### Patch Changes + +- 99fb54183b: Updated dependency `@azure/identity` to `^4.0.0`. +- Updated dependencies + - @backstage/config@1.1.1 + +## 1.8.0-next.0 + +### Minor Changes + +- 870db76a45: Implemented `readTree` for Gitea provider to support TechDocs functionality + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + ## 1.7.2 ### Patch Changes diff --git a/packages/integration/package.json b/packages/integration/package.json index f7437bf094..8e403c2ce4 100644 --- a/packages/integration/package.json +++ b/packages/integration/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration", "description": "Helpers for managing integrations towards external systems", - "version": "1.7.2", + "version": "1.8.0-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,7 +33,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@azure/identity": "^3.2.1", + "@azure/identity": "^4.0.0", "@backstage/config": "workspace:^", "@octokit/auth-app": "^4.0.0", "@octokit/rest": "^19.0.3", diff --git a/packages/repo-tools/CHANGELOG.md b/packages/repo-tools/CHANGELOG.md index b439c08fc6..d416aa11b4 100644 --- a/packages/repo-tools/CHANGELOG.md +++ b/packages/repo-tools/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/repo-tools +## 0.5.0-next.1 + +### Patch Changes + +- f909e9d: Includes templates in @backstage/repo-tools package and use them in the CLI +- da3c4db: Updates the `schema openapi generate-client` command to export all generated types from the generated directory. +- 7959f23: The `api-reports` command now checks for api report files that no longer apply. + If it finds such files, it's treated basically the same as report errors do, and + the check fails. + + For example, if you had an `api-report-alpha.md` but then removed the alpha + export, the reports generator would now report that this file needs to be + deleted. + +- f49e237: Fixed a bug where `schema openapi init` created an invalid test command. +- f91be2c: Updated dependency `@stoplight/types` to `^14.0.0`. +- 45bfb20: Execute `openapi-generator-cli` from `@backstage/repo-tools` directory to force it to use our openapitools.json config file. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/errors@1.2.3 + +## 0.5.0-next.0 + +### Minor Changes + +- aea8f8d329: **BREAKING**: API Reports generated for sub-path exports now place the name as a suffix rather than prefix, for example `api-report-alpha.md` instead of `alpha-api-report.md`. When upgrading to this version you'll need to re-create any such API reports and delete the old ones. +- 38340678c3: Adds a new command `schema openapi generate-client` that creates a Typescript client with Backstage flavor, including the discovery API and fetch API. This command doesn't currently generate a complete client and needs to be wrapped or exported manually by a separate Backstage plugin. See `@backstage/catalog-client/src/generated` for example output. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.2.0 + - @backstage/errors@1.2.3 + ## 0.4.0 ### Minor Changes diff --git a/packages/repo-tools/openapitools.json b/packages/repo-tools/openapitools.json new file mode 100644 index 0000000000..65c0d8ead7 --- /dev/null +++ b/packages/repo-tools/openapitools.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../node_modules/@openapitools/openapi-generator-cli/config.schema.json", + "spaces": 2, + "generator-cli": { + "version": "6.5.0" + } +} diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index 3bd76a6e60..d0c00f3f9a 100644 --- a/packages/repo-tools/package.json +++ b/packages/repo-tools/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/repo-tools", "description": "CLI for Backstage repo tooling ", - "version": "0.4.0", + "version": "0.5.0-next.1", "publishConfig": { "access": "public" }, @@ -32,6 +32,7 @@ "dependencies": { "@apidevtools/swagger-parser": "^10.1.0", "@apisyouwonthate/style-guide": "^1.4.0", + "@backstage/backend-common": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/cli-common": "workspace:^", "@backstage/cli-node": "workspace:^", @@ -39,13 +40,14 @@ "@manypkg/get-packages": "^1.1.3", "@microsoft/api-documenter": "^7.22.33", "@microsoft/api-extractor": "^7.36.4", + "@openapitools/openapi-generator-cli": "^2.7.0", "@stoplight/spectral-core": "^1.18.0", "@stoplight/spectral-formatters": "^1.1.0", "@stoplight/spectral-functions": "^1.7.2", "@stoplight/spectral-parsers": "^1.0.2", "@stoplight/spectral-rulesets": "^1.18.0", "@stoplight/spectral-runtime": "^1.1.2", - "@stoplight/types": "^13.14.0", + "@stoplight/types": "^14.0.0", "chalk": "^4.0.0", "codeowners-utils": "^1.0.2", "commander": "^9.1.0", @@ -84,7 +86,9 @@ }, "files": [ "bin", - "dist/**/*.js" + "dist/**/*.js", + "templates", + "openapitools.json" ], "nodemonConfig": { "watch": "./src", 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 ce3e6f5b20..b8c241bb0b 100644 --- a/packages/repo-tools/src/commands/api-reports/api-extractor.ts +++ b/packages/repo-tools/src/commands/api-reports/api-extractor.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { groupBy } from 'lodash'; import { resolve as resolvePath, relative as relativePath, @@ -363,7 +364,9 @@ export async function runApiExtraction({ } const warnings = new Array(); - for (const { packageDir, name } of packageEntryPoints) { + for (const [packageDir, group] of Object.entries( + groupBy(packageEntryPoints, ep => ep.packageDir), + )) { console.log(`## Processing ${packageDir}`); const noBail = Array.isArray(allowWarnings) ? allowWarnings.some(aw => aw === packageDir || minimatch(packageDir, aw)) @@ -374,209 +377,242 @@ export async function runApiExtraction({ './dist-types', packageDir, ); + const names = group.map(ep => ep.name); - const prefix = name === 'index' ? '' : `${name}-`; - const reportFileName = `${prefix}api-report.md`; - const reportPath = resolvePath(projectFolder, reportFileName); + const remainingReportFiles = new Set( + fs + .readdirSync(projectFolder) + .filter( + filename => + filename.match(/^(.+)-api-report\.md$/) || + filename.match(/^api-report(-.+)?\.md$/), + ), + ); - const warningCountBefore = await countApiReportWarnings(reportPath); + for (const name of names) { + const suffix = name === 'index' ? '' : `-${name}`; + const reportFileName = `api-report${suffix}.md`; + const reportPath = resolvePath(projectFolder, reportFileName); + remainingReportFiles.delete(reportFileName); - const extractorConfig = ExtractorConfig.prepare({ - configObject: { - mainEntryPointFilePath: resolvePath(packageFolder, `src/${name}.d.ts`), - bundledPackages: [], + const warningCountBefore = await countApiReportWarnings(reportPath); - compiler: { - tsconfigFilePath, - }, - - apiReport: { - enabled: true, - reportFileName, - reportFolder: projectFolder, - reportTempFolder: resolvePath( - outputDir, - `${prefix}`, + const extractorConfig = ExtractorConfig.prepare({ + configObject: { + mainEntryPointFilePath: resolvePath( + packageFolder, + `src/${name}.d.ts`, ), - }, + bundledPackages: [], - docModel: { - // TODO(Rugvip): This skips docs for non-index entry points. We can try to work around it, but - // most likely it makes sense to wait for API Extractor to natively support exports. - enabled: name === 'index', - apiJsonFilePath: resolvePath( - outputDir, - `${prefix}.api.json`, - ), - }, + compiler: { + tsconfigFilePath, + }, - dtsRollup: { - enabled: false, - }, + apiReport: { + enabled: true, + reportFileName, + reportFolder: projectFolder, + reportTempFolder: resolvePath( + outputDir, + `${suffix}`, + ), + }, - tsdocMetadata: { - enabled: false, - }, + docModel: { + // TODO(Rugvip): This skips docs for non-index entry points. We can try to work around it, but + // most likely it makes sense to wait for API Extractor to natively support exports. + enabled: name === 'index', + apiJsonFilePath: resolvePath( + outputDir, + `${suffix}.api.json`, + ), + }, - messages: { - // Silence compiler warnings, as these will prevent the CI build to work - compilerMessageReporting: { - default: { - logLevel: 'none' as ExtractorLogLevel.None, - // These contain absolute file paths, so can't be included in the report - // addToApiReportFile: true, - }, - }, - extractorMessageReporting: { - default: { - logLevel: 'warning' as ExtractorLogLevel.Warning, - addToApiReportFile: true, - }, - ...messagesConf, - }, - tsdocMessageReporting: { - default: { - logLevel: 'warning' as ExtractorLogLevel.Warning, - addToApiReportFile: true, + dtsRollup: { + enabled: false, + }, + + tsdocMetadata: { + enabled: false, + }, + + messages: { + // Silence compiler warnings, as these will prevent the CI build to work + compilerMessageReporting: { + default: { + logLevel: 'none' as ExtractorLogLevel.None, + // These contain absolute file paths, so can't be included in the report + // addToApiReportFile: true, + }, + }, + extractorMessageReporting: { + default: { + logLevel: 'warning' as ExtractorLogLevel.Warning, + addToApiReportFile: true, + }, + ...messagesConf, + }, + tsdocMessageReporting: { + default: { + logLevel: 'warning' as ExtractorLogLevel.Warning, + addToApiReportFile: true, + }, }, }, + + newlineKind: 'lf', + + projectFolder, }, - - newlineKind: 'lf', - - projectFolder, - }, - 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 - // paths to be logged. Unfortunately the `prepare` method above derives it from the `packageJsonFullPath`, - // which needs to point to the actual file, so we override `packageFolder` afterwards. - ( - extractorConfig as { - packageFolder: string; - } - ).packageFolder = packageFolder; - - if (!compilerState) { - compilerState = CompilerState.create(extractorConfig, { - additionalEntryPoints: entryPoints, + configObjectFullPath: projectFolder, + packageJsonFullPath: resolvePath(projectFolder, 'package.json'), + tsdocConfigFile: await getTsDocConfig(), + ignoreMissingEntryPoint: true, }); - } - // Message verbosity can't be configured, so just skip the check instead - (Extractor as any)._checkCompilerCompatibility = () => {}; - - let shouldLogInstructions = false; - let conflictingFile: undefined | string = undefined; - - // Invoke API Extractor - const extractorResult = Extractor.invoke(extractorConfig, { - localBuild: isLocalBuild, - showVerboseMessages: false, - showDiagnostics: false, - messageCallback(message) { - if (message.text.includes('The API report file is missing')) { - shouldLogInstructions = true; + // The `packageFolder` needs to point to the location within `dist-types` in order for relative + // paths to be logged. Unfortunately the `prepare` method above derives it from the `packageJsonFullPath`, + // which needs to point to the actual file, so we override `packageFolder` afterwards. + ( + extractorConfig as { + packageFolder: string; } - if ( - message.text.includes( - 'You have changed the public API signature for this project.', - ) - ) { - shouldLogInstructions = true; - const match = message.text.match( - /Please copy the file "(.*)" to "api-report\.md"/, - ); - if (match) { - conflictingFile = match[1]; + ).packageFolder = packageFolder; + + if (!compilerState) { + compilerState = CompilerState.create(extractorConfig, { + additionalEntryPoints: entryPoints, + }); + } + + // Message verbosity can't be configured, so just skip the check instead + (Extractor as any)._checkCompilerCompatibility = () => {}; + + let shouldLogInstructions = false; + let conflictingFile: undefined | string = undefined; + + // Invoke API Extractor + const extractorResult = Extractor.invoke(extractorConfig, { + localBuild: isLocalBuild, + showVerboseMessages: false, + showDiagnostics: false, + messageCallback(message) { + if (message.text.includes('The API report file is missing')) { + shouldLogInstructions = true; } - } - }, - compilerState, - }); - - // This release tag validation makes sure that the release tag of known entry points match expectations. - // The root index entrypoint is only allowed @public exports, while /alpha and /beta only allow @alpha and @beta. - if ( - validateReleaseTags && - fs.pathExistsSync(extractorConfig.reportFilePath) - ) { - if (['index', 'alpha', 'beta'].includes(name)) { - const report = await fs.readFile( - extractorConfig.reportFilePath, - 'utf8', - ); - const lines = report.split(/\r?\n/); - const expectedTag = name === 'index' ? 'public' : name; - for (let i = 0; i < lines.length; i += 1) { - const line = lines[i]; - const match = line.match(/^\/\/ @(alpha|beta|public)/); - if (match && match[1] !== expectedTag) { - // Because of limitations in the type script rollup logic we need to allow public exports from the other release stages - // TODO(Rugvip): Try to work around the need for this exception - if (expectedTag !== 'public' && match[1] === 'public') { - continue; - } - throw new Error( - `Unexpected release tag ${match[1]} in ${ - extractorConfig.reportFilePath - } at line ${i + 1}`, + if ( + message.text.includes( + 'You have changed the public API signature for this project.', + ) + ) { + shouldLogInstructions = true; + const match = message.text.match( + /Please copy the file "(.*)" to "api-report\.md"/, ); + if (match) { + conflictingFile = match[1]; + } + } + }, + compilerState, + }); + + // This release tag validation makes sure that the release tag of known entry points match expectations. + // The root index entrypoint is only allowed @public exports, while /alpha and /beta only allow @alpha and @beta. + if ( + validateReleaseTags && + fs.pathExistsSync(extractorConfig.reportFilePath) + ) { + if (['index', 'alpha', 'beta'].includes(name)) { + const report = await fs.readFile( + extractorConfig.reportFilePath, + 'utf8', + ); + const lines = report.split(/\r?\n/); + const expectedTag = name === 'index' ? 'public' : name; + for (let i = 0; i < lines.length; i += 1) { + const line = lines[i]; + const match = line.match(/^\/\/ @(alpha|beta|public)/); + if (match && match[1] !== expectedTag) { + // Because of limitations in the type script rollup logic we need to allow public exports from the other release stages + // TODO(Rugvip): Try to work around the need for this exception + if (expectedTag !== 'public' && match[1] === 'public') { + continue; + } + throw new Error( + `Unexpected release tag ${match[1]} in ${ + extractorConfig.reportFilePath + } at line ${i + 1}`, + ); + } } } } - } - - if (!extractorResult.succeeded) { - if (shouldLogInstructions) { - logApiReportInstructions(); - - if (conflictingFile) { - console.log(''); - console.log( - `The conflicting file is ${relativePath( - tmpDir, - conflictingFile, - )}, with the following content:`, - ); - console.log(''); - - const content = await fs.readFile(conflictingFile, 'utf8'); - console.log(content); + if (!extractorResult.succeeded) { + if (shouldLogInstructions) { logApiReportInstructions(); + + if (conflictingFile) { + console.log(''); + console.log( + `The conflicting file is ${relativePath( + tmpDir, + conflictingFile, + )}, with the following content:`, + ); + console.log(''); + + const content = await fs.readFile(conflictingFile, 'utf8'); + console.log(content); + + logApiReportInstructions(); + } } + + throw new Error( + `API Extractor completed with ${extractorResult.errorCount} errors` + + ` and ${extractorResult.warningCount} warnings`, + ); } - throw new Error( - `API Extractor completed with ${extractorResult.errorCount} errors` + - ` and ${extractorResult.warningCount} warnings`, - ); + const warningCountAfter = await countApiReportWarnings(reportPath); + if (noBail) { + console.log(`Skipping warnings check for ${packageDir}`); + } + if (warningCountAfter > 0 && !noBail) { + throw new Error( + `The API Report for ${packageDir} is not allowed to have warnings`, + ); + } + if (warningCountAfter === 0 && allowWarningPkg.includes(packageDir)) { + console.log( + `No need to allow warnings for ${packageDir}, it does not have any`, + ); + } + if (warningCountAfter > warningCountBefore) { + warnings.push( + `The API Report for ${packageDir} introduces new warnings. ` + + 'Please fix these warnings in order to keep the API Reports tidy.', + ); + } } - const warningCountAfter = await countApiReportWarnings(reportPath); - if (noBail) { - console.log(`Skipping warnings check for ${packageDir}`); - } - if (warningCountAfter > 0 && !noBail) { - throw new Error( - `The API Report for ${packageDir} is not allowed to have warnings`, - ); - } - if (warningCountAfter === 0 && allowWarningPkg.includes(packageDir)) { - console.log( - `No need to allow warnings for ${packageDir}, it does not have any`, - ); - } - if (warningCountAfter > warningCountBefore) { - warnings.push( - `The API Report for ${packageDir} introduces new warnings. ` + - 'Please fix these warnings in order to keep the API Reports tidy.', - ); + if (remainingReportFiles.size > 0) { + if (isLocalBuild) { + for (const f of remainingReportFiles) { + fs.rmSync(resolvePath(projectFolder, f)); + console.log(`Deleted deprecated API report ${f}`); + } + } else { + const staleList = [...remainingReportFiles] + .map(f => join(packageDir, f)) + .join(', '); + throw new Error( + `The API Report(s) ${staleList} are no longer relevant and should be deleted`, + ); + } } } diff --git a/packages/repo-tools/src/commands/index.ts b/packages/repo-tools/src/commands/index.ts index 4f9ea87708..d9c6d892f5 100644 --- a/packages/repo-tools/src/commands/index.ts +++ b/packages/repo-tools/src/commands/index.ts @@ -32,14 +32,18 @@ function registerSchemaCommand(program: Command) { .description( 'Verify that all OpenAPI schemas are valid and have a matching `schemas/openapi.generated.ts` file.', ) - .action(lazy(() => import('./openapi/verify').then(m => m.bulkCommand))); + .action( + lazy(() => import('./openapi/schema/verify').then(m => m.bulkCommand)), + ); openApiCommand .command('generate [paths...]') .description( 'Generates a Typescript file from an OpenAPI yaml spec. For use with the `@backstage/backend-openapi-utils` ApiRouter type.', ) - .action(lazy(() => import('./openapi/generate').then(m => m.bulkCommand))); + .action( + lazy(() => import('./openapi/schema/generate').then(m => m.bulkCommand)), + ); openApiCommand .command('lint [paths...]') @@ -60,6 +64,16 @@ function registerSchemaCommand(program: Command) { .command('init ') .description('Creates any config needed for the test command.') .action(lazy(() => import('./openapi/test/init').then(m => m.default))); + + openApiCommand + .command('generate-client') + .requiredOption('--input-spec ') + .requiredOption('--output-directory ') + .action( + lazy(() => + import('./openapi/client/generate').then(m => m.singleCommand), + ), + ); } export function registerCommands(program: Command) { diff --git a/packages/repo-tools/src/commands/openapi/client/generate.ts b/packages/repo-tools/src/commands/openapi/client/generate.ts new file mode 100644 index 0000000000..f827f1005f --- /dev/null +++ b/packages/repo-tools/src/commands/openapi/client/generate.ts @@ -0,0 +1,100 @@ +/* + * 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. + */ + +import chalk from 'chalk'; +import { resolve } from 'path'; +import { OPENAPI_IGNORE_FILES, OUTPUT_PATH } from '../constants'; +import { paths as cliPaths } from '../../../lib/paths'; +import { mkdirpSync } from 'fs-extra'; +import fs from 'fs-extra'; +import { exec } from '../../../lib/exec'; +import { resolvePackagePath } from '@backstage/backend-common'; + +async function generate(spec: string, outputDirectory: string) { + const resolvedOpenapiPath = resolve(spec); + const resolvedOutputDirectory = resolve(outputDirectory, OUTPUT_PATH); + mkdirpSync(resolvedOutputDirectory); + + await fs.mkdirp(resolvedOutputDirectory); + + await fs.writeFile( + resolve(resolvedOutputDirectory, '.openapi-generator-ignore'), + OPENAPI_IGNORE_FILES.join('\n'), + ); + + await exec( + 'node', + [ + resolvePackagePath('@openapitools/openapi-generator-cli', 'main.js'), + 'generate', + '-i', + resolvedOpenapiPath, + '-o', + resolvedOutputDirectory, + '-g', + 'typescript', + '-c', + resolvePackagePath( + '@backstage/repo-tools', + 'templates/typescript-backstage.yaml', + ), + '--generator-key', + 'v3.0', + ], + { + maxBuffer: Number.MAX_VALUE, + cwd: resolvePackagePath('@backstage/repo-tools'), + env: { + ...process.env, + }, + }, + ); + + await exec( + `yarn backstage-cli package lint --fix ${resolvedOutputDirectory}`, + ); + + const prettier = cliPaths.resolveTargetRoot('node_modules/.bin/prettier'); + if (prettier) { + await exec(`${prettier} --write ${resolvedOutputDirectory}`); + } + + fs.removeSync(resolve(resolvedOutputDirectory, '.openapi-generator-ignore')); + + fs.rmSync(resolve(resolvedOutputDirectory, '.openapi-generator'), { + recursive: true, + force: true, + }); +} + +export async function singleCommand({ + inputSpec, + outputDirectory, +}: { + inputSpec: string; + outputDirectory: string; +}): Promise { + try { + await generate(inputSpec, outputDirectory); + console.log(chalk.green(`Generated client for ${inputSpec}`)); + } catch (err) { + console.log(); + console.log(chalk.red(`Client generation failed in ${outputDirectory}:`)); + console.log(err); + + process.exit(1); + } +} diff --git a/packages/repo-tools/src/commands/openapi/constants.ts b/packages/repo-tools/src/commands/openapi/constants.ts index defef4ab53..2e7a57522a 100644 --- a/packages/repo-tools/src/commands/openapi/constants.ts +++ b/packages/repo-tools/src/commands/openapi/constants.ts @@ -19,3 +19,44 @@ export const YAML_SCHEMA_PATH = 'src/schema/openapi.yaml'; export const TS_MODULE = 'src/schema/openapi.generated'; export const TS_SCHEMA_PATH = `${TS_MODULE}.ts`; + +export const GENERATOR_VERSION = `1.0.0`; +export const GENERATOR_NAME = 'typescript-backstage'; +export const GENERATOR_FILE = `packages/template-openapi-plugin-client/generator/target/${GENERATOR_NAME}-openapi-generator-${GENERATOR_VERSION}.jar`; + +export const OUTPUT_PATH = 'src/generated'; + +export const OPENAPI_IGNORE_FILES = [ + // Get rid of the default files. + '*.md', + // The rest of these have to be explicit, otherwise they get added if this was a *.* + 'apis/baseapi.ts', + 'apis/exception.ts', + 'auth/*', + 'http/*', + 'middleware.ts', + 'servers.ts', + 'util.ts', + 'configuration.ts', + 'rxjsStub.ts', + '.gitignore', + + // Override the created version. + 'apis/*.ts', + '!apis/*.client.ts', + 'models/*.ts', + '!models/*.model.ts', + + // Always include index.ts files. + '!index.ts', + '!**/index.ts', + + // Weird API typings. + 'types/ObjectParamAPI.ts', + 'types/ObservableAPI.ts', + 'types/PromiseAPI.ts', + + 'git_push.sh', + 'package.json', + 'tsconfig.json', +]; diff --git a/packages/repo-tools/src/commands/openapi/generate.ts b/packages/repo-tools/src/commands/openapi/schema/generate.ts similarity index 95% rename from packages/repo-tools/src/commands/openapi/generate.ts rename to packages/repo-tools/src/commands/openapi/schema/generate.ts index 52b8e5b840..cd9f572f2d 100644 --- a/packages/repo-tools/src/commands/openapi/generate.ts +++ b/packages/repo-tools/src/commands/openapi/schema/generate.ts @@ -18,9 +18,9 @@ import fs from 'fs-extra'; import YAML from 'js-yaml'; import chalk from 'chalk'; import { resolve } from 'path'; -import { paths as cliPaths } from '../../lib/paths'; -import { runner } from './runner'; -import { TS_SCHEMA_PATH, YAML_SCHEMA_PATH } from './constants'; +import { paths as cliPaths } from '../../../lib/paths'; +import { runner } from '../runner'; +import { TS_SCHEMA_PATH, YAML_SCHEMA_PATH } from '../constants'; import { promisify } from 'util'; import { exec as execCb } from 'child_process'; diff --git a/packages/repo-tools/src/commands/openapi/verify.ts b/packages/repo-tools/src/commands/openapi/schema/verify.ts similarity index 93% rename from packages/repo-tools/src/commands/openapi/verify.ts rename to packages/repo-tools/src/commands/openapi/schema/verify.ts index 2808e72702..7120dd67ad 100644 --- a/packages/repo-tools/src/commands/openapi/verify.ts +++ b/packages/repo-tools/src/commands/openapi/schema/verify.ts @@ -21,9 +21,9 @@ import { join } from 'path'; import chalk from 'chalk'; import { relative as relativePath, resolve as resolvePath } from 'path'; import Parser from '@apidevtools/swagger-parser'; -import { runner } from './runner'; -import { paths as cliPaths } from '../../lib/paths'; -import { TS_MODULE, TS_SCHEMA_PATH, YAML_SCHEMA_PATH } from './constants'; +import { runner } from '../runner'; +import { paths as cliPaths } from '../../../lib/paths'; +import { TS_MODULE, TS_SCHEMA_PATH, YAML_SCHEMA_PATH } from '../constants'; async function verify(directoryPath: string) { const openapiPath = join(directoryPath, YAML_SCHEMA_PATH); diff --git a/packages/repo-tools/src/commands/openapi/test/init.ts b/packages/repo-tools/src/commands/openapi/test/init.ts index 13c3aeb2b6..a38416aabb 100644 --- a/packages/repo-tools/src/commands/openapi/test/init.ts +++ b/packages/repo-tools/src/commands/openapi/test/init.ts @@ -35,7 +35,7 @@ async function init(directoryPath: string) { ); } const opticConfigFilePath = join(directoryPath, 'optic.yml'); - if (!(await fs.pathExists(opticConfigFilePath))) { + if (await fs.pathExists(opticConfigFilePath)) { throw new Error(`This directory already has an optic.yml file. Exiting.`); } await fs.writeFile( @@ -56,7 +56,7 @@ capture: # 🔧 Specify a command that will generate traffic command: yarn backstage-cli package test --no-watch ${ROUTER_TEST_PATHS.map( e => `"${e}"`, - ).join(',')} + ).join(' ')} `, ); if (await cliPaths.resolveTargetRoot('node_modules/.bin/prettier')) { diff --git a/packages/repo-tools/templates/typescript-backstage.yaml b/packages/repo-tools/templates/typescript-backstage.yaml new file mode 100644 index 0000000000..b2b068856d --- /dev/null +++ b/packages/repo-tools/templates/typescript-backstage.yaml @@ -0,0 +1,21 @@ +templateDir: templates/typescript-backstage + +files: + api.mustache: + templateType: API + # For some reason, they check for destinationFilename differences. We have to change the ending to override the file. + destinationFilename: .client.ts + model.mustache: + templateType: Model + destinationFilename: .model.ts + models/models_all.mustache: + templateType: SupportingFiles + destinationFilename: models/index.ts + types/fetch.ts: {} + types/discovery.ts: {} + apis/index.mustache: + templateType: SupportingFiles + destinationFilename: apis/index.ts + pluginId.mustache: + templateType: SupportingFiles + destinationFilename: pluginId.ts diff --git a/packages/repo-tools/templates/typescript-backstage/api.mustache b/packages/repo-tools/templates/typescript-backstage/api.mustache new file mode 100644 index 0000000000..1b8739ba57 --- /dev/null +++ b/packages/repo-tools/templates/typescript-backstage/api.mustache @@ -0,0 +1,114 @@ +{{>licenseInfo}} +import { DiscoveryApi } from '../types/discovery'; +import { FetchApi } from '../types/fetch'; +import crossFetch from 'cross-fetch'; +import {pluginId} from '../pluginId'; +import * as parser from 'uri-template'; + +{{#imports}} +import { {{classname}} } from '{{filename}}.model{{importFileExtension}}'; +{{/imports}} + +type TypedResponse = Omit & { + json: () => Promise; +}; + +{{#operations}} + +/** + * Options you can pass into a request for additional information. + * + * @public + */ +export interface RequestOptions { + token?: string; +} + +/** + * {{{description}}}{{^description}}no description{{/description}} + */ +export class {{classname}}Client { + private readonly discoveryApi: DiscoveryApi; + private readonly fetchApi: FetchApi; + + constructor(options: { + discoveryApi: { getBaseUrl(pluginId: string): Promise }; + fetchApi?: { fetch: typeof fetch }; + }) { + this.discoveryApi = options.discoveryApi; + this.fetchApi = options.fetchApi || { fetch: crossFetch }; + } + + {{#operation}} + /** + {{#notes}} + * {{¬es}} + {{/notes}} + {{#summary}} + * {{&summary}} + {{/summary}} + {{#allParams}} + * @param {{paramName}} {{description}} + {{/allParams}} + */ + public async {{nickname}}( + // @ts-ignore + request: { + {{#hasPathParams}} + path: { + {{#pathParams}} + {{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, + {{/pathParams}} + }, + {{/hasPathParams}} + {{#hasBodyParam}} + {{#bodyParam}} + body: {{{dataType}}}, + {{/bodyParam}} + {{/hasBodyParam}} + {{#hasQueryParams}} + query: { + {{#queryParams}} + {{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, + {{/queryParams}} + }, + {{/hasQueryParams}} + {{#hasHeaderParams}} + header: { + {{#headerParams}} + {{paramName}}{{^required}}?{{/required}}: {{{dataType}}}, + {{/headerParams}} + }, + {{/hasHeaderParams}} + }, + options?: RequestOptions + ): Promise> { + const baseUrl = await this.discoveryApi.getBaseUrl(pluginId); + + const uriTemplate = `{{{path}}}{{#hasQueryParams}}{?{{#queryParams}}{{baseName}}{{#isArray}}{{#isExplode}}*{{/isExplode}}{{/isArray}}{{^-last}},{{/-last}}{{/queryParams}}}{{/hasQueryParams}}`; + + const uri = parser.parse(uriTemplate).expand({ + {{#pathParams}} + {{baseName}}: request.path.{{paramName}}, + {{/pathParams}} + {{#hasQueryParams}} + ...request.query, + {{/hasQueryParams}} + }) + + return await this.fetchApi.fetch(`${baseUrl}${uri}`, { + headers: { + {{#hasHeaderParams}} + ...request.header, + {{/hasHeaderParams}} + 'Content-Type': 'application/json', + ...(options?.token && { Authorization: `Bearer ${options?.token}` }), + }, + method: '{{httpMethod}}', + {{#hasBodyParam}} body: JSON.stringify(request.body), {{/hasBodyParam}} + }); + } + + {{/operation}} +} +{{/operations}} diff --git a/packages/repo-tools/templates/typescript-backstage/apis/index.mustache b/packages/repo-tools/templates/typescript-backstage/apis/index.mustache new file mode 100644 index 0000000000..4c8996c5ee --- /dev/null +++ b/packages/repo-tools/templates/typescript-backstage/apis/index.mustache @@ -0,0 +1,3 @@ +// + +export * from './DefaultApi.client'; diff --git a/packages/repo-tools/templates/typescript-backstage/index.mustache b/packages/repo-tools/templates/typescript-backstage/index.mustache new file mode 100644 index 0000000000..b95e48ff08 --- /dev/null +++ b/packages/repo-tools/templates/typescript-backstage/index.mustache @@ -0,0 +1,4 @@ +// + +export * from './apis'; +export * from './models'; \ No newline at end of file diff --git a/packages/repo-tools/templates/typescript-backstage/model.mustache b/packages/repo-tools/templates/typescript-backstage/model.mustache new file mode 100644 index 0000000000..1f288380e0 --- /dev/null +++ b/packages/repo-tools/templates/typescript-backstage/model.mustache @@ -0,0 +1,43 @@ +// + +{{#models}} +{{#model}} +{{#tsImports}} +import { {{classname}} } from '{{filename}}.model{{importFileExtension}}'; +{{/tsImports}} + +{{#description}} +/** +* {{{.}}} +*/ +{{/description}} +{{^isEnum}} +export interface {{classname}} { +{{#additionalPropertiesType}} + [key: string]: {{{additionalPropertiesType}}}; +{{/additionalPropertiesType}} +{{#vars}} +{{#description}} + /** + * {{{.}}} + */ +{{/description}} + '{{name}}'{{^required}}?{{/required}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#isNullable}} | null{{/isNullable}}; +{{/vars}} +} + +{{#hasEnums}} + +{{#vars}} +{{#isEnum}} +export type {{classname}}{{enumName}} ={{#allowableValues}}{{#values}} "{{.}}" {{^-last}}|{{/-last}}{{/values}}{{/allowableValues}}; +{{/isEnum}} +{{/vars}} + +{{/hasEnums}} +{{/isEnum}} +{{#isEnum}} +export type {{classname}} ={{#allowableValues}}{{#values}} "{{.}}" {{^-last}}|{{/-last}}{{/values}}{{/allowableValues}}; +{{/isEnum}} +{{/model}} +{{/models}} \ No newline at end of file diff --git a/packages/repo-tools/templates/typescript-backstage/models/models_all.mustache b/packages/repo-tools/templates/typescript-backstage/models/models_all.mustache new file mode 100644 index 0000000000..d076cfb3ff --- /dev/null +++ b/packages/repo-tools/templates/typescript-backstage/models/models_all.mustache @@ -0,0 +1,7 @@ +// + +{{#models}} +{{#model}} +export * from '{{{ importPath }}}.model{{importFileExtension}}' +{{/model}} +{{/models}} \ No newline at end of file diff --git a/packages/repo-tools/templates/typescript-backstage/pluginId.mustache b/packages/repo-tools/templates/typescript-backstage/pluginId.mustache new file mode 100644 index 0000000000..8bc8461cc9 --- /dev/null +++ b/packages/repo-tools/templates/typescript-backstage/pluginId.mustache @@ -0,0 +1,6 @@ + +{{#servers}} +{{#-last}} +export const pluginId = "{{url}}"; +{{/-last}} +{{/servers}} \ No newline at end of file diff --git a/packages/repo-tools/templates/typescript-backstage/types/discovery.ts b/packages/repo-tools/templates/typescript-backstage/types/discovery.ts new file mode 100644 index 0000000000..a7f87d3780 --- /dev/null +++ b/packages/repo-tools/templates/typescript-backstage/types/discovery.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +/** + * This is a copy of the DiscoveryApi, to avoid importing core-plugin-api. + */ +export type DiscoveryApi = { + getBaseUrl(pluginId: string): Promise; +}; diff --git a/packages/repo-tools/templates/typescript-backstage/types/fetch.ts b/packages/repo-tools/templates/typescript-backstage/types/fetch.ts new file mode 100644 index 0000000000..3de56c028e --- /dev/null +++ b/packages/repo-tools/templates/typescript-backstage/types/fetch.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +/** + * This is a copy of FetchApi, to avoid importing core-plugin-api. + */ +export type FetchApi = { + fetch: typeof fetch; +}; diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index 75abfcc0b1..a7a804b74e 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,70 @@ # techdocs-cli-embedded-app +## 0.2.89-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.25.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-techdocs@1.9.2-next.3 + - @backstage/plugin-catalog@1.16.0-next.3 + - @backstage/app-defaults@1.4.6-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/test-utils@1.4.6-next.2 + - @backstage/plugin-techdocs-react@1.1.14-next.2 + +## 0.2.89-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/cli@0.25.0-next.1 + - @backstage/plugin-catalog@1.16.0-next.2 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/test-utils@1.4.6-next.1 + - @backstage/plugin-techdocs@1.9.2-next.2 + - @backstage/app-defaults@1.4.6-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-techdocs-react@1.1.14-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + +## 0.2.89-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.16.0-next.1 + - @backstage/plugin-techdocs@1.9.2-next.1 + +## 0.2.89-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-catalog@1.16.0-next.0 + - @backstage/plugin-techdocs@1.9.2-next.0 + - @backstage/cli@0.24.1-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/app-defaults@1.4.6-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/test-utils@1.4.6-next.0 + - @backstage/plugin-techdocs-react@1.1.14-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + ## 0.2.88 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 1e2b47c479..d487da2722 100644 --- a/packages/techdocs-cli-embedded-app/package.json +++ b/packages/techdocs-cli-embedded-app/package.json @@ -1,6 +1,6 @@ { "name": "techdocs-cli-embedded-app", - "version": "0.2.88", + "version": "0.2.89-next.3", "private": true, "backstage": { "role": "frontend" diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index c459fe6689..5e82b98a3f 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,46 @@ # @techdocs/cli +## 1.8.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/plugin-techdocs-node@1.11.0-next.2 + +## 1.8.0-next.1 + +### Minor Changes + +- b2dccad7b3: Support passing additional `mkdocs-server` CLI parameters (`--dirtyreload`, `--strict` and `--clean`) when run in containerized mode. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs-node@1.11.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + +## 1.8.0-next.0 + +### Minor Changes + +- d15d483a49: Add command `--runAsDefaultUser` for `@techdocs/cli generate` to bypass running the docker builds as host user for macOS and Linux. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-techdocs-node@1.11.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + ## 1.7.0 ### Minor Changes diff --git a/packages/techdocs-cli/cli-report.md b/packages/techdocs-cli/cli-report.md index 890718b0d2..9777b2c4b8 100644 --- a/packages/techdocs-cli/cli-report.md +++ b/packages/techdocs-cli/cli-report.md @@ -38,6 +38,7 @@ Options: --omitTechdocsCoreMkdocsPlugin --legacyCopyReadmeMdToIndexMd --defaultPlugin [defaultPlugins...] + --runAsDefaultUser -h, --help ``` @@ -107,6 +108,9 @@ Options: --preview-app-bundle-path --preview-app-port -c, --mkdocs-config-file-name + --mkdocs-parameter-clean + --mkdocs-parameter-dirtyreload + --mkdocs-parameter-strict -h, --help ``` diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 9719267c22..0e0d4c3a04 100644 --- a/packages/techdocs-cli/package.json +++ b/packages/techdocs-cli/package.json @@ -1,7 +1,7 @@ { "name": "@techdocs/cli", "description": "Utility CLI for managing TechDocs sites in Backstage.", - "version": "1.7.0", + "version": "1.8.0-next.2", "publishConfig": { "access": "public" }, diff --git a/packages/techdocs-cli/src/commands/generate/generate.ts b/packages/techdocs-cli/src/commands/generate/generate.ts index 934eaf1efd..bf6910ff4a 100644 --- a/packages/techdocs-cli/src/commands/generate/generate.ts +++ b/packages/techdocs-cli/src/commands/generate/generate.ts @@ -114,6 +114,7 @@ export default async function generate(opts: OptionValues) { etag: opts.etag, logStream: getLogStream(logger), siteOptions: { name: opts.siteName }, + runAsDefaultUser: opts.runAsDefaultUser, }); if (configIsTemporary) { diff --git a/packages/techdocs-cli/src/commands/index.ts b/packages/techdocs-cli/src/commands/index.ts index 10a00da513..ac9523e639 100644 --- a/packages/techdocs-cli/src/commands/index.ts +++ b/packages/techdocs-cli/src/commands/index.ts @@ -75,6 +75,11 @@ export function registerCommands(program: Command) { 'Plugins which should be added automatically to the mkdocs.yaml file', [], ) + .option( + '--runAsDefaultUser', + 'Bypass setting the container user as the same user and group id as host for Linux and MacOS', + false, + ) .alias('build') .action(lazy(() => import('./generate/generate').then(m => m.default))); @@ -289,6 +294,21 @@ export function registerCommands(program: Command) { '-c, --mkdocs-config-file-name ', 'Mkdocs config file name', ) + .option( + '--mkdocs-parameter-clean', + 'Pass "--clean" parameter to mkdocs server running in containerized environment', + false, + ) + .option( + '--mkdocs-parameter-dirtyreload', + 'Pass "--dirtyreload" parameter to mkdocs server running in containerized environment', + false, + ) + .option( + '--mkdocs-parameter-strict', + 'Pass "--strict" parameter to mkdocs server running in containerized environment', + false, + ) .hook('preAction', command => { if ( command.opts().previewAppPort !== defaultPreviewAppPort && diff --git a/packages/techdocs-cli/src/commands/serve/serve.ts b/packages/techdocs-cli/src/commands/serve/serve.ts index 98c9982b21..de681c2de4 100644 --- a/packages/techdocs-cli/src/commands/serve/serve.ts +++ b/packages/techdocs-cli/src/commands/serve/serve.ts @@ -116,6 +116,9 @@ export default async function serve(opts: OptionValues) { stdoutLogFunc: mkdocsLogFunc, stderrLogFunc: mkdocsLogFunc, mkdocsConfigFileName: mkdocsYmlPath, + mkdocsParameterClean: opts.mkdocsParameterClean, + mkdocsParameterDirtyReload: opts.mkdocsParameterDirtyReload, + mkdocsParameterStrict: opts.mkdocsParameterStrict, }); // Wait until mkdocs server has started so that Backstage starts with docs loaded diff --git a/packages/techdocs-cli/src/lib/mkdocsServer.test.ts b/packages/techdocs-cli/src/lib/mkdocsServer.test.ts index 8484c4e242..83f9c9f382 100644 --- a/packages/techdocs-cli/src/lib/mkdocsServer.test.ts +++ b/packages/techdocs-cli/src/lib/mkdocsServer.test.ts @@ -97,6 +97,24 @@ describe('runMkdocsServer', () => { expect.objectContaining({}), ); }); + + it('should accept additinoal mkdocs CLI parameters', async () => { + await runMkdocsServer({ + mkdocsParameterClean: true, + mkdocsParameterStrict: true, + }); + expect(run).toHaveBeenCalledWith( + 'docker', + expect.arrayContaining([ + 'serve', + '--dev-addr', + '0.0.0.0:8000', + '--clean', + '--strict', + ]), + expect.objectContaining({}), + ); + }); }); describe('mkdocs', () => { diff --git a/packages/techdocs-cli/src/lib/mkdocsServer.ts b/packages/techdocs-cli/src/lib/mkdocsServer.ts index 42409acb46..a793643367 100644 --- a/packages/techdocs-cli/src/lib/mkdocsServer.ts +++ b/packages/techdocs-cli/src/lib/mkdocsServer.ts @@ -26,6 +26,9 @@ export const runMkdocsServer = async (options: { stdoutLogFunc?: LogFunc; stderrLogFunc?: LogFunc; mkdocsConfigFileName?: string; + mkdocsParameterClean?: boolean; + mkdocsParameterDirtyReload?: boolean; + mkdocsParameterStrict?: boolean; }): Promise => { const port = options.port ?? '8000'; const useDocker = options.useDocker ?? true; @@ -55,6 +58,9 @@ export const runMkdocsServer = async (options: { ...(options.mkdocsConfigFileName ? ['--config-file', options.mkdocsConfigFileName] : []), + ...(options.mkdocsParameterClean ? ['--clean'] : []), + ...(options.mkdocsParameterDirtyReload ? ['--dirtyreload'] : []), + ...(options.mkdocsParameterStrict ? ['--strict'] : []), ], { stdoutLogFunc: options.stdoutLogFunc, @@ -72,6 +78,9 @@ export const runMkdocsServer = async (options: { ...(options.mkdocsConfigFileName ? ['--config-file', options.mkdocsConfigFileName] : []), + ...(options.mkdocsParameterClean ? ['--clean'] : []), + ...(options.mkdocsParameterDirtyReload ? ['--dirtyreload'] : []), + ...(options.mkdocsParameterStrict ? ['--strict'] : []), ], { stdoutLogFunc: options.stdoutLogFunc, diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 70b2c70f6f..476c3b5ad8 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/test-utils +## 1.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-react@0.4.18-next.1 + +## 1.4.6-next.1 + +### Patch Changes + +- e8f2acef80: Deprecated `mockBreakpoint`, as it is now available from `@backstage/core-components/testUtils` instead. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + +## 1.4.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + ## 1.4.5 ### Patch Changes diff --git a/packages/test-utils/alpha-api-report.md b/packages/test-utils/api-report-alpha.md similarity index 100% rename from packages/test-utils/alpha-api-report.md rename to packages/test-utils/api-report-alpha.md diff --git a/packages/test-utils/api-report.md b/packages/test-utils/api-report.md index 60bd352726..913413acd1 100644 --- a/packages/test-utils/api-report.md +++ b/packages/test-utils/api-report.md @@ -74,7 +74,7 @@ export class MockAnalyticsApi implements AnalyticsApi { getEvents(): AnalyticsEvent[]; } -// @public +// @public @deprecated export function mockBreakpoint(options: { matches: boolean }): void; // @public diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index bce7e0ea5b..e2632227e7 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/test-utils", "description": "Utilities to test Backstage plugins and apps.", - "version": "1.4.5", + "version": "1.4.6-next.2", "publishConfig": { "access": "public" }, diff --git a/packages/test-utils/src/testUtils/mockBreakpoint.ts b/packages/test-utils/src/testUtils/mockBreakpoint.ts index 78d7c9497f..c674c98f06 100644 --- a/packages/test-utils/src/testUtils/mockBreakpoint.ts +++ b/packages/test-utils/src/testUtils/mockBreakpoint.ts @@ -25,6 +25,7 @@ * https://mui.com/material-ui/react-use-media-query/#testing * * @public + * @deprecated Import from `@backstage/core-components/testUtils` instead. */ export default function mockBreakpoint(options: { matches: boolean }) { Object.defineProperty(window, 'matchMedia', { diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md index f734ed13da..808c899d43 100644 --- a/packages/theme/CHANGELOG.md +++ b/packages/theme/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/theme +## 0.5.0-next.1 + +### Patch Changes + +- cd0dd4c: Align Material UI v5 `Paper` component background color in dark mode to v4. + +## 0.5.0-next.0 + +### Minor Changes + +- 4d9e3b39e4: Added a global `OverrideComponentNameToClassKeys` for other plugins and packages to populate using module augmentation. This will in turn will provide component style override types for `createUnifiedTheme`. + ## 0.4.4 ### Patch Changes diff --git a/packages/theme/api-report.md b/packages/theme/api-report.md index 4ab05e8770..21d6be6a78 100644 --- a/packages/theme/api-report.md +++ b/packages/theme/api-report.md @@ -15,6 +15,7 @@ import { Theme as Theme_3 } from '@material-ui/core'; import { ThemeOptions } from '@mui/material/styles'; import { ThemeOptions as ThemeOptions_2 } from '@material-ui/core/styles'; import type { ThemeOptions as ThemeOptions_3 } from '@material-ui/core'; +import { UnifiedTheme as UnifiedTheme_2 } from '@backstage/theme'; // @public @deprecated export type BackstagePalette = Palette & BackstagePaletteAdditions; @@ -216,6 +217,9 @@ export function genPageTheme(props: { // @public @deprecated export const lightTheme: Theme_3; +// @public +export interface OverrideComponentNameToClassKeys {} + // @public export type PageTheme = { colors: string[]; @@ -401,8 +405,8 @@ export type SupportedVersions = 'v4' | 'v5'; // @public export const themes: { - light: UnifiedTheme; - dark: UnifiedTheme; + light: UnifiedTheme_2; + dark: UnifiedTheme_2; }; // @public diff --git a/packages/theme/package.json b/packages/theme/package.json index 5f49b904a7..ac7d418ef7 100644 --- a/packages/theme/package.json +++ b/packages/theme/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/theme", "description": "material-ui theme for use with Backstage.", - "version": "0.4.4", + "version": "0.5.0-next.1", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -45,6 +45,9 @@ }, "devDependencies": { "@backstage/cli": "workspace:^", + "@mui/styles": "^5.14.18", + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0", "@types/react": "^16.13.1 || ^17.0.0" }, "files": [ diff --git a/plugins/graphql-backend/src/setupTests.ts b/packages/theme/src/setupTests.ts similarity index 94% rename from plugins/graphql-backend/src/setupTests.ts rename to packages/theme/src/setupTests.ts index d3232290a7..963c0f188b 100644 --- a/plugins/graphql-backend/src/setupTests.ts +++ b/packages/theme/src/setupTests.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export {}; +import '@testing-library/jest-dom'; diff --git a/packages/theme/src/unified/UnifiedThemeProvider.test.tsx b/packages/theme/src/unified/UnifiedThemeProvider.test.tsx new file mode 100644 index 0000000000..da4af5abab --- /dev/null +++ b/packages/theme/src/unified/UnifiedThemeProvider.test.tsx @@ -0,0 +1,86 @@ +/* + * 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 { + useTheme as useV4Theme, + makeStyles as makeV4Styles, +} from '@material-ui/core/styles'; +import { useTheme as useV5Theme } from '@mui/material/styles'; +import { makeStyles as makeV5Styles } from '@mui/styles'; +import { render, screen } from '@testing-library/react'; +import React from 'react'; +import './MuiClassNameSetup'; +import { UnifiedThemeProvider } from './UnifiedThemeProvider'; +import { themes } from './themes'; + +describe('UnifiedThemeProvider', () => { + it('provides a themes for v4 and v5 directly', () => { + function MyV4Component() { + const theme = useV4Theme(); + return v4-grey: {theme.palette.grey[500]}; + } + function MyV5Component() { + const theme = useV5Theme(); + return v5-grey: {theme.palette.grey[500]}; + } + + render( + + + + , + ); + + expect(screen.getByText('v4-grey: #9e9e9e')).toBeInTheDocument(); + expect(screen.getByText('v5-grey: #9e9e9e')).toBeInTheDocument(); + }); + + it('provides a themes for v4 and v5 through makeStyles', () => { + const useV4Styles = makeV4Styles(theme => ({ + root: { + color: theme.palette.grey[500], + }, + })); + const useV5Styles = makeV5Styles(theme => ({ + root: { + color: theme.palette.grey[500], + }, + })); + + function MyV4Component() { + const classes = useV4Styles(); + return v4; + } + function MyV5Component() { + const classes = useV5Styles(); + return v5; + } + + render( + + + + , + ); + + expect(window.getComputedStyle(screen.getByText('v4')).color).toBe( + 'rgb(158, 158, 158)', + ); + expect(window.getComputedStyle(screen.getByText('v5')).color).toBe( + 'rgb(158, 158, 158)', + ); + }); +}); diff --git a/packages/theme/src/v5/defaultComponentThemes.ts b/packages/theme/src/v5/defaultComponentThemes.ts index e484300818..60caa47e90 100644 --- a/packages/theme/src/v5/defaultComponentThemes.ts +++ b/packages/theme/src/v5/defaultComponentThemes.ts @@ -239,4 +239,7 @@ export const defaultComponentThemes: ThemeOptions['components'] = { underline: 'hover', }, }, + MuiPaper: { + styleOverrides: { root: { backgroundImage: 'unset' } }, + }, }; diff --git a/packages/theme/src/v5/types.test.ts b/packages/theme/src/v5/types.test.ts new file mode 100644 index 0000000000..12bd0ff2b8 --- /dev/null +++ b/packages/theme/src/v5/types.test.ts @@ -0,0 +1,47 @@ +/* + * 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. + */ + +import { palettes } from '../base'; +import { createUnifiedTheme } from '../unified'; + +declare module '@backstage/theme' { + interface OverrideComponentNameToClassKeys { + MyTestComponent: 'root' | 'header'; + } +} + +describe('OverrideComponentNameToClassKeys', () => { + it('should provide type safe component style overrides', () => { + const theme = createUnifiedTheme({ + palette: palettes.light, + components: { + MyTestComponent: { + styleOverrides: { + root: { + color: '#f00', + }, + // @ts-expect-error + invalid: { + color: '#b45', + }, + }, + }, + }, + }); + + expect(theme).toBeDefined(); + }); +}); diff --git a/packages/theme/src/v5/types.ts b/packages/theme/src/v5/types.ts index 0d6d46cef9..aa80c903fa 100644 --- a/packages/theme/src/v5/types.ts +++ b/packages/theme/src/v5/types.ts @@ -19,6 +19,8 @@ import { BackstagePaletteAdditions, BackstageThemeAdditions, } from '../base/types'; +// eslint-disable-next-line no-restricted-imports +import { OverridesStyleRules } from '@mui/material/styles/overrides'; declare module '@mui/material/styles' { interface Palette extends BackstagePaletteAdditions {} @@ -35,3 +37,30 @@ declare module '@mui/material/styles' { declare module '@mui/private-theming/defaultTheme' { interface DefaultTheme extends Theme {} } + +/** + * Merge interface declarations into this type to register overrides for your components. + * + * @public + * @example + * ```ts + * declare module '@backstage/theme' { + * interface OverrideComponentNameToClassKeys { + * MyComponent: 'root' | 'header'; + * } + * } + * ``` + */ +export interface OverrideComponentNameToClassKeys {} + +type BackstageComponentOverrides = { + [TName in keyof OverrideComponentNameToClassKeys]?: { + styleOverrides?: Partial< + OverridesStyleRules + >; + }; +}; + +declare module '@mui/material/styles' { + interface Components extends BackstageComponentOverrides {} +} diff --git a/plugins/adr-backend/CHANGELOG.md b/plugins/adr-backend/CHANGELOG.md index ee16741ca0..d55efec464 100644 --- a/plugins/adr-backend/CHANGELOG.md +++ b/plugins/adr-backend/CHANGELOG.md @@ -1,5 +1,50 @@ # @backstage/plugin-adr-backend +## 0.4.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-adr-common@0.2.18-next.1 + - @backstage/plugin-search-common@1.2.8 + +## 0.4.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-adr-common@0.2.18-next.1 + - @backstage/plugin-search-common@1.2.8 + +## 0.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-adr-common@0.2.18-next.0 + - @backstage/plugin-search-common@1.2.8 + ## 0.4.4 ### Patch Changes diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index 2d1a7a742d..03f469462a 100644 --- a/plugins/adr-backend/package.json +++ b/plugins/adr-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr-backend", - "version": "0.4.4", + "version": "0.4.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr-common/CHANGELOG.md b/plugins/adr-common/CHANGELOG.md index 13f766e3fb..3f02901db7 100644 --- a/plugins/adr-common/CHANGELOG.md +++ b/plugins/adr-common/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-adr-common +## 0.2.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-search-common@1.2.8 + +## 0.2.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-search-common@1.2.8 + ## 0.2.17 ### Patch Changes diff --git a/plugins/adr-common/package.json b/plugins/adr-common/package.json index be6e9c37bc..e04af0ade0 100644 --- a/plugins/adr-common/package.json +++ b/plugins/adr-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-adr-common", "description": "Common functionalities for the adr plugin", - "version": "0.2.17", + "version": "0.2.18-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr/CHANGELOG.md b/plugins/adr/CHANGELOG.md index f46d74f99a..96af85f974 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,55 @@ # @backstage/plugin-adr +## 0.6.11-next.2 + +### Patch Changes + +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-adr-common@0.2.18-next.1 + - @backstage/plugin-search-common@1.2.8 + +## 0.6.11-next.1 + +### Patch Changes + +- fb8f3bdbc2: Updated alpha translation message keys to use nested format and camel case. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-adr-common@0.2.18-next.1 + - @backstage/plugin-search-common@1.2.8 + +## 0.6.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-adr-common@0.2.18-next.0 + - @backstage/plugin-search-common@1.2.8 + ## 0.6.9 ### Patch Changes diff --git a/plugins/adr/alpha-api-report.md b/plugins/adr/api-report-alpha.md similarity index 67% rename from plugins/adr/alpha-api-report.md rename to plugins/adr/api-report-alpha.md index 5740556904..4c9ac1d17e 100644 --- a/plugins/adr/alpha-api-report.md +++ b/plugins/adr/api-report-alpha.md @@ -4,11 +4,11 @@ ```ts import { BackstagePlugin } from '@backstage/frontend-plugin-api'; -import { Extension } from '@backstage/frontend-plugin-api'; +import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; // @alpha (undocumented) -export const AdrSearchResultListItemExtension: Extension<{ +export const AdrSearchResultListItemExtension: ExtensionDefinition<{ lineClamp: number; noTrack: boolean; }>; @@ -17,9 +17,9 @@ export const AdrSearchResultListItemExtension: Extension<{ export const adrTranslationRef: TranslationRef< 'adr', { - readonly content_header_title: 'Architecture Decision Records'; - readonly failed_to_fetch: 'Failed to fetch ADRs'; - readonly no_adrs: 'No ADRs found'; + readonly contentHeaderTitle: 'Architecture Decision Records'; + readonly failedToFetch: 'Failed to fetch ADRs'; + readonly notFound: 'No ADRs found'; } >; diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 3cb1ce1999..61cbc53d78 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.6.9", + "version": "0.6.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/adr/src/alpha.tsx b/plugins/adr/src/alpha.tsx index 1f6fa0711d..ea4d32e0da 100644 --- a/plugins/adr/src/alpha.tsx +++ b/plugins/adr/src/alpha.tsx @@ -31,7 +31,6 @@ function isAdrDocument(result: any): result is AdrDocument { /** @alpha */ export const AdrSearchResultListItemExtension = createSearchResultListItemExtension({ - id: 'adr', configSchema: createSchemaFromZod(z => z.object({ // TODO: Define how the icon can be configurable diff --git a/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx b/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx index 261dd994fb..5c8d244d26 100644 --- a/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx +++ b/plugins/adr/src/components/EntityAdrContent/EntityAdrContent.tsx @@ -219,7 +219,7 @@ export const EntityAdrContent = (props: { return ( - + {appSupportConfigured && } @@ -230,7 +230,7 @@ export const EntityAdrContent = (props: { {loading && } {entityHasAdrs && !loading && error && ( - + )} {entityHasAdrs && @@ -257,7 +257,7 @@ export const EntityAdrContent = (props: { ) : ( - {t('no_adrs')} + {t('notFound')} ))} ); diff --git a/plugins/adr/src/translations.ts b/plugins/adr/src/translations.ts index cc0995f597..038b0fd064 100644 --- a/plugins/adr/src/translations.ts +++ b/plugins/adr/src/translations.ts @@ -19,8 +19,8 @@ import { createTranslationRef } from '@backstage/core-plugin-api/alpha'; export const adrTranslationRef = createTranslationRef({ id: 'adr', messages: { - content_header_title: 'Architecture Decision Records', - failed_to_fetch: 'Failed to fetch ADRs', - no_adrs: 'No ADRs found', + contentHeaderTitle: 'Architecture Decision Records', + failedToFetch: 'Failed to fetch ADRs', + notFound: 'No ADRs found', }, }); diff --git a/plugins/airbrake-backend/CHANGELOG.md b/plugins/airbrake-backend/CHANGELOG.md index c9e4c0ea32..d17b7163c0 100644 --- a/plugins/airbrake-backend/CHANGELOG.md +++ b/plugins/airbrake-backend/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-airbrake-backend +## 0.3.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + +## 0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + +## 0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + ## 0.3.4 ### Patch Changes diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json index 763fa27192..ae21abc68d 100644 --- a/plugins/airbrake-backend/package.json +++ b/plugins/airbrake-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake-backend", - "version": "0.3.4", + "version": "0.3.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/airbrake/CHANGELOG.md b/plugins/airbrake/CHANGELOG.md index 3f9b700373..73fed7ebf8 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-airbrake +## 0.3.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/dev-utils@1.0.25-next.2 + - @backstage/test-utils@1.4.6-next.2 + +## 0.3.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/test-utils@1.4.6-next.1 + - @backstage/dev-utils@1.0.25-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.3.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/dev-utils@1.0.25-next.0 + - @backstage/test-utils@1.4.6-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.3.26 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 2f92cadad7..617e0cb230 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.3.26", + "version": "0.3.28-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx index 3e82d60d81..666a7ffea2 100644 --- a/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx +++ b/plugins/airbrake/src/components/EntityAirbrakeWidget/EntityAirbrakeWidget.tsx @@ -22,7 +22,6 @@ import { Progress, } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; -import { BackstageTheme } from '@backstage/theme'; import { Grid, Typography } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import React from 'react'; @@ -31,11 +30,11 @@ import { airbrakeApiRef } from '../../api'; import { MissingAnnotationEmptyState } from '@backstage/plugin-catalog-react'; import { AIRBRAKE_PROJECT_ID_ANNOTATION, useProjectId } from '../useProjectId'; -const useStyles = makeStyles(() => ({ +const useStyles = makeStyles({ multilineText: { whiteSpace: 'pre-wrap', }, -})); +}); export const EntityAirbrakeWidget = ({ entity }: { entity: Entity }) => { const classes = useStyles(); diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index ec28c8bade..973eb19b10 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-allure +## 0.1.44-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.1.44-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.1.44-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.1.42 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index 43ce9c71bd..7e3cb96dcf 100644 --- a/plugins/allure/package.json +++ b/plugins/allure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-allure", "description": "A Backstage plugin that integrates with Allure", - "version": "0.1.42", + "version": "0.1.44-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index a59b7a4401..4f16059c68 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-analytics-module-ga +## 0.1.36-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.1.36-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + +## 0.1.36-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/config@1.1.1 + ## 0.1.35 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index f4ad73af39..f3f736e2b8 100644 --- a/plugins/analytics-module-ga/package.json +++ b/plugins/analytics-module-ga/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga", - "version": "0.1.35", + "version": "0.1.36-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-ga4/CHANGELOG.md b/plugins/analytics-module-ga4/CHANGELOG.md index 3d6368f301..1a92081a96 100644 --- a/plugins/analytics-module-ga4/CHANGELOG.md +++ b/plugins/analytics-module-ga4/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-analytics-module-ga4 +## 0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + +## 0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/config@1.1.1 + ## 0.1.6 ### Patch Changes diff --git a/plugins/analytics-module-ga4/package.json b/plugins/analytics-module-ga4/package.json index 54739172a4..13e9e65415 100644 --- a/plugins/analytics-module-ga4/package.json +++ b/plugins/analytics-module-ga4/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-ga4", - "version": "0.1.6", + "version": "0.1.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/analytics-module-newrelic-browser/CHANGELOG.md b/plugins/analytics-module-newrelic-browser/CHANGELOG.md index 96fc0f27d0..eea3c0d58a 100644 --- a/plugins/analytics-module-newrelic-browser/CHANGELOG.md +++ b/plugins/analytics-module-newrelic-browser/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-analytics-module-newrelic-browser +## 0.0.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.0.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + +## 0.0.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/config@1.1.1 + ## 0.0.4 ### Patch Changes diff --git a/plugins/analytics-module-newrelic-browser/package.json b/plugins/analytics-module-newrelic-browser/package.json index b332904e21..a146aa4adf 100644 --- a/plugins/analytics-module-newrelic-browser/package.json +++ b/plugins/analytics-module-newrelic-browser/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-analytics-module-newrelic-browser", - "version": "0.0.4", + "version": "0.0.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index 4add797c2c..ac404ebdd5 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-apache-airflow +## 0.2.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.2.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.2.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + ## 0.2.17 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index b48955679e..40fbe80434 100644 --- a/plugins/apache-airflow/package.json +++ b/plugins/apache-airflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apache-airflow", - "version": "0.2.17", + "version": "0.2.18-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index abc662eff5..646cf298fd 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,52 @@ # @backstage/plugin-api-docs +## 0.10.2-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog@1.16.0-next.3 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.10.2-next.2 + +### Patch Changes + +- e16e7ce6a5: Updated dependency `@asyncapi/react-component` to `1.2.2`. +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-catalog@1.16.0-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.10.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.16.0-next.1 + +## 0.10.2-next.0 + +### Patch Changes + +- 816d331d16: Add dependency on `graphql-config` to compensate for `graphql-language-service` needing it but not shipping the dep properly +- 615159e536: Updated dependency `graphiql` to `3.0.10`. +- 53e2c06f41: Updated dependency `@asyncapi/react-component` to `1.1.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-catalog@1.16.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.10.0 ### Minor Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index fdf5e79d45..089f8b6acf 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-api-docs", "description": "A Backstage plugin that helps represent API entities in the frontend", - "version": "0.10.0", + "version": "0.10.2-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,7 +33,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@asyncapi/react-component": "1.0.0-next.48", + "@asyncapi/react-component": "1.2.6", "@backstage/catalog-model": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", @@ -45,8 +45,9 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", "@types/react": "^16.13.1 || ^17.0.0", - "graphiql": "3.0.9", + "graphiql": "3.0.10", "graphql": "^16.0.0", + "graphql-config": "^5.0.2", "graphql-ws": "^5.4.1", "isomorphic-form-data": "^2.0.0", "react-use": "^17.2.4", diff --git a/plugins/api-docs/src/components/ApiDefinitionDialog/ApiDefinitionDialog.tsx b/plugins/api-docs/src/components/ApiDefinitionDialog/ApiDefinitionDialog.tsx index 2f82a0cc5a..6673420732 100644 --- a/plugins/api-docs/src/components/ApiDefinitionDialog/ApiDefinitionDialog.tsx +++ b/plugins/api-docs/src/components/ApiDefinitionDialog/ApiDefinitionDialog.tsx @@ -16,7 +16,6 @@ import { ApiEntity } from '@backstage/catalog-model'; import { useApi } from '@backstage/core-plugin-api'; -import { BackstageTheme } from '@backstage/theme'; import { Box, Button, @@ -33,7 +32,7 @@ import React, { useEffect } from 'react'; import { apiDocsConfigRef } from '../../config'; import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ fullHeightDialog: { height: 'calc(100% - 64px)', }, diff --git a/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinition.test.tsx b/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinition.test.tsx index c9f979edad..ed3a3e98ce 100644 --- a/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinition.test.tsx +++ b/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinition.test.tsx @@ -54,7 +54,7 @@ components: expect(getByText(/Account Service/i)).toBeInTheDocument(); expect(getByText(/user\/signedup/i)).toBeInTheDocument(); - expect(getAllByText(/UserSignedUp/i)).toHaveLength(2); + expect(getAllByText(/UserSignedUp/i)).toHaveLength(4); expect(getAllByText(/displayName/i)).toHaveLength(3); }); }); diff --git a/plugins/api-docs/src/components/GraphQlDefinitionWidget/GraphQlDefinition.tsx b/plugins/api-docs/src/components/GraphQlDefinitionWidget/GraphQlDefinition.tsx index 6ad8643111..bf45a0e637 100644 --- a/plugins/api-docs/src/components/GraphQlDefinitionWidget/GraphQlDefinition.tsx +++ b/plugins/api-docs/src/components/GraphQlDefinitionWidget/GraphQlDefinition.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; import { makeStyles } from '@material-ui/core/styles'; import { DocExplorer, @@ -26,7 +25,7 @@ import 'graphiql/graphiql.css'; import { buildSchema } from 'graphql'; import React from 'react'; -const useStyles = makeStyles(() => ({ +const useStyles = makeStyles({ root: { height: '100%', display: 'flex', @@ -46,7 +45,7 @@ const useStyles = makeStyles(() => ({ }, }, }, -})); +}); type Props = { definition: string; diff --git a/plugins/api-docs/src/components/GrpcApiDefinitionWidget/GrpcApiDefinitionWidget.tsx b/plugins/api-docs/src/components/GrpcApiDefinitionWidget/GrpcApiDefinitionWidget.tsx index b6bf317099..8363ebaedc 100644 --- a/plugins/api-docs/src/components/GrpcApiDefinitionWidget/GrpcApiDefinitionWidget.tsx +++ b/plugins/api-docs/src/components/GrpcApiDefinitionWidget/GrpcApiDefinitionWidget.tsx @@ -17,7 +17,6 @@ import React from 'react'; import { CodeSnippet } from '@backstage/core-components'; import { useTheme } from '@material-ui/core/styles'; -import { BackstageTheme } from '@backstage/theme'; /** @public */ export type GrpcApiDefinitionWidgetProps = { @@ -28,7 +27,7 @@ export type GrpcApiDefinitionWidgetProps = { export const GrpcApiDefinitionWidget = ( props: GrpcApiDefinitionWidgetProps, ) => { - const theme = useTheme(); + const theme = useTheme(); return ( { const { definition } = props; - const theme = useTheme(); + const theme = useTheme(); return ( (theme => ({ +const useStyles = makeStyles(theme => ({ tabs: { background: theme.palette.background.paper, }, diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index 6ef1c8f63f..451ac6c219 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-app-backend +## 0.3.56-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.6.0-next.0 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-app-node@0.1.8-next.2 + +## 0.3.56-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/types@1.1.1 + - @backstage/plugin-app-node@0.1.8-next.1 + +## 0.3.56-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/types@1.1.1 + - @backstage/plugin-app-node@0.1.8-next.0 + ## 0.3.55 ### Patch Changes diff --git a/plugins/app-backend/alpha-api-report.md b/plugins/app-backend/api-report-alpha.md similarity index 100% rename from plugins/app-backend/alpha-api-report.md rename to plugins/app-backend/api-report-alpha.md diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index b0a7ce6503..1d888fc838 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-app-backend", "description": "A Backstage backend plugin that serves the Backstage frontend app", - "version": "0.3.55", + "version": "0.3.56-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/app-node/CHANGELOG.md b/plugins/app-node/CHANGELOG.md index 96e16cee92..a0ad9dda64 100644 --- a/plugins/app-node/CHANGELOG.md +++ b/plugins/app-node/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-app-node +## 0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + +## 0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + +## 0.1.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + ## 0.1.7 ### Patch Changes diff --git a/plugins/app-node/package.json b/plugins/app-node/package.json index 45e379f3a8..2121752c17 100644 --- a/plugins/app-node/package.json +++ b/plugins/app-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-app-node", "description": "Node.js library for the app plugin", - "version": "0.1.7", + "version": "0.1.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphql-backend/.eslintrc.js b/plugins/auth-backend-module-atlassian-provider/.eslintrc.js similarity index 100% rename from plugins/graphql-backend/.eslintrc.js rename to plugins/auth-backend-module-atlassian-provider/.eslintrc.js diff --git a/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md b/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md new file mode 100644 index 0000000000..79dac8b182 --- /dev/null +++ b/plugins/auth-backend-module-atlassian-provider/CHANGELOG.md @@ -0,0 +1,33 @@ +# @backstage/plugin-auth-backend-module-atlassian-provider + +## 0.1.0-next.2 + +### Patch Changes + +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## 0.1.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.1.0-next.0 + +### Minor Changes + +- 2a5891e816: New module for `@backstage/plugin-auth-backend` that adds an atlassian auth provider + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 diff --git a/plugins/auth-backend-module-atlassian-provider/README.md b/plugins/auth-backend-module-atlassian-provider/README.md new file mode 100644 index 0000000000..fb326f68be --- /dev/null +++ b/plugins/auth-backend-module-atlassian-provider/README.md @@ -0,0 +1,8 @@ +# Auth Module: Atlassian Provider + +This module provides an Atlassian auth provider implementation for `@backstage/plugin-auth-backend`. + +## Links + +- [Repository](https://atlassian.com/backstage/backstage/tree/master/plugins/auth-backend-module-atlassian-provider) +- [Backstage Project Homepage](https://backstage.io) diff --git a/plugins/auth-backend-module-atlassian-provider/api-report.md b/plugins/auth-backend-module-atlassian-provider/api-report.md new file mode 100644 index 0000000000..8a30e6b493 --- /dev/null +++ b/plugins/auth-backend-module-atlassian-provider/api-report.md @@ -0,0 +1,30 @@ +## API Report File for "@backstage/plugin-auth-backend-module-atlassian-provider" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; +import { OAuthAuthenticator } from '@backstage/plugin-auth-node'; +import { OAuthAuthenticatorResult } from '@backstage/plugin-auth-node'; +import { PassportOAuthAuthenticatorHelper } from '@backstage/plugin-auth-node'; +import { PassportProfile } from '@backstage/plugin-auth-node'; +import { SignInResolverFactory } from '@backstage/plugin-auth-node'; + +// @public (undocumented) +export const atlassianAuthenticator: OAuthAuthenticator< + PassportOAuthAuthenticatorHelper, + PassportProfile +>; + +// @public +export namespace atlassianSignInResolvers { + const usernameMatchingUserEntityName: SignInResolverFactory< + OAuthAuthenticatorResult, + unknown + >; +} + +// @public (undocumented) +const authModuleAtlassianProvider: () => BackendFeature; +export default authModuleAtlassianProvider; +``` diff --git a/plugins/auth-backend-module-atlassian-provider/catalog-info.yaml b/plugins/auth-backend-module-atlassian-provider/catalog-info.yaml new file mode 100644 index 0000000000..d3e2c11c17 --- /dev/null +++ b/plugins/auth-backend-module-atlassian-provider/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-auth-backend-module-atlassian-provider + title: '@backstage/plugin-auth-backend-module-atlassian-provider' + description: The atlassian-provider backend module for the auth plugin. +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: maintainers diff --git a/plugins/auth-backend-module-atlassian-provider/config.d.ts b/plugins/auth-backend-module-atlassian-provider/config.d.ts new file mode 100644 index 0000000000..999bf1b304 --- /dev/null +++ b/plugins/auth-backend-module-atlassian-provider/config.d.ts @@ -0,0 +1,34 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Config { + auth?: { + providers?: { + /** @visibility frontend */ + atlassian?: { + [authEnv: string]: { + clientId: string; + /** + * @visibility secret + */ + clientSecret: string; + audience?: string; + callbackUrl?: string; + }; + }; + }; + }; +} diff --git a/plugins/auth-backend-module-atlassian-provider/dev/index.ts b/plugins/auth-backend-module-atlassian-provider/dev/index.ts new file mode 100644 index 0000000000..d3c18c1d48 --- /dev/null +++ b/plugins/auth-backend-module-atlassian-provider/dev/index.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); + +backend.add(import('@backstage/plugin-auth-backend')); +backend.add(import('../src')); + +backend.start(); diff --git a/plugins/auth-backend-module-atlassian-provider/package.json b/plugins/auth-backend-module-atlassian-provider/package.json new file mode 100644 index 0000000000..f3be6d9bab --- /dev/null +++ b/plugins/auth-backend-module-atlassian-provider/package.json @@ -0,0 +1,45 @@ +{ + "name": "@backstage/plugin-auth-backend-module-atlassian-provider", + "description": "The atlassian-provider backend module for the auth plugin.", + "version": "0.1.0-next.2", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin-module" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", + "@backstage/plugin-auth-node": "workspace:^", + "express": "^4.18.2", + "passport": "^0.7.0", + "passport-atlassian-oauth2": "^2.1.0" + }, + "devDependencies": { + "@backstage/backend-defaults": "workspace:^", + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "@backstage/plugin-auth-backend": "workspace:^", + "supertest": "^6.3.3" + }, + "configSchema": "config.d.ts", + "files": [ + "dist", + "config.d.ts" + ] +} diff --git a/plugins/auth-backend-module-atlassian-provider/src/authenticator.ts b/plugins/auth-backend-module-atlassian-provider/src/authenticator.ts new file mode 100644 index 0000000000..3e5ed50246 --- /dev/null +++ b/plugins/auth-backend-module-atlassian-provider/src/authenticator.ts @@ -0,0 +1,77 @@ +/* + * 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. + */ + +import { Strategy as AtlassianStrategy } from 'passport-atlassian-oauth2'; +import { + createOAuthAuthenticator, + PassportOAuthAuthenticatorHelper, + PassportOAuthDoneCallback, + PassportProfile, +} from '@backstage/plugin-auth-node'; + +/** @public */ +export const atlassianAuthenticator = createOAuthAuthenticator({ + defaultProfileTransform: + PassportOAuthAuthenticatorHelper.defaultProfileTransform, + initialize({ callbackUrl, config }) { + const clientId = config.getString('clientId'); + const clientSecret = config.getString('clientSecret'); + const baseUrl = + config.getOptionalString('audience') || 'https://atlassian.com'; + + return PassportOAuthAuthenticatorHelper.from( + new AtlassianStrategy( + { + clientID: clientId, + clientSecret: clientSecret, + callbackURL: callbackUrl, + baseURL: baseUrl, + authorizationURL: `${baseUrl}/oauth/authorize`, + tokenURL: `${baseUrl}/oauth/token`, + profileURL: `${baseUrl}/api/v4/user`, + }, + ( + accessToken: string, + refreshToken: string, + params: any, + fullProfile: PassportProfile, + done: PassportOAuthDoneCallback, + ) => { + done( + undefined, + { fullProfile, params, accessToken }, + { refreshToken }, + ); + }, + ), + ); + }, + + async start(input, helper) { + return helper.start(input, { + accessType: 'offline', + prompt: 'consent', + }); + }, + + async authenticate(input, helper) { + return helper.authenticate(input); + }, + + async refresh(input, helper) { + return helper.refresh(input); + }, +}); diff --git a/plugins/auth-backend-module-atlassian-provider/src/index.ts b/plugins/auth-backend-module-atlassian-provider/src/index.ts new file mode 100644 index 0000000000..cc71c9b7e3 --- /dev/null +++ b/plugins/auth-backend-module-atlassian-provider/src/index.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +/** + * The atlassian-provider backend module for the auth plugin. + * + * @packageDocumentation + */ + +export { atlassianAuthenticator } from './authenticator'; +export { authModuleAtlassianProvider as default } from './module'; +export { atlassianSignInResolvers } from './resolvers'; diff --git a/plugins/auth-backend-module-atlassian-provider/src/module.test.ts b/plugins/auth-backend-module-atlassian-provider/src/module.test.ts new file mode 100644 index 0000000000..8d02b0b7a5 --- /dev/null +++ b/plugins/auth-backend-module-atlassian-provider/src/module.test.ts @@ -0,0 +1,77 @@ +/* + * 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. + */ + +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; +import { authModuleAtlassianProvider } from './module'; +import request from 'supertest'; +import { decodeOAuthState } from '@backstage/plugin-auth-node'; + +describe('authModuleAtlassianProvider', () => { + it('should start', async () => { + const { server } = await startTestBackend({ + features: [ + import('@backstage/plugin-auth-backend'), + authModuleAtlassianProvider, + mockServices.rootConfig.factory({ + data: { + app: { + baseUrl: 'http://localhost:3000', + }, + auth: { + providers: { + atlassian: { + development: { + clientId: 'my-client-id', + clientSecret: 'my-client-secret', + }, + }, + }, + }, + }, + }), + ], + }); + + const agent = request.agent(server); + + const res = await agent.get('/api/auth/atlassian/start?env=development'); + + expect(res.status).toEqual(302); + + const nonceCookie = agent.jar.getCookie('atlassian-nonce', { + domain: 'localhost', + path: '/api/auth/atlassian/handler', + script: false, + secure: false, + }); + expect(nonceCookie).toBeDefined(); + + const startUrl = new URL(res.get('location')); + expect(startUrl.origin).toBe('https://atlassian.com'); + expect(startUrl.pathname).toBe('/oauth/authorize'); + expect(Object.fromEntries(startUrl.searchParams)).toEqual({ + response_type: 'code', + client_id: 'my-client-id', + redirect_uri: `http://localhost:${server.port()}/api/auth/atlassian/handler/frame`, + state: expect.any(String), + }); + + expect(decodeOAuthState(startUrl.searchParams.get('state')!)).toEqual({ + env: 'development', + nonce: decodeURIComponent(nonceCookie.value), + }); + }); +}); diff --git a/plugins/auth-backend-module-atlassian-provider/src/module.ts b/plugins/auth-backend-module-atlassian-provider/src/module.ts new file mode 100644 index 0000000000..9acb665ede --- /dev/null +++ b/plugins/auth-backend-module-atlassian-provider/src/module.ts @@ -0,0 +1,48 @@ +/* + * 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. + */ +import { createBackendModule } from '@backstage/backend-plugin-api'; +import { + authProvidersExtensionPoint, + commonSignInResolvers, + createOAuthProviderFactory, +} from '@backstage/plugin-auth-node'; +import { atlassianAuthenticator } from './authenticator'; +import { atlassianSignInResolvers } from './resolvers'; + +/** @public */ +export const authModuleAtlassianProvider = createBackendModule({ + pluginId: 'auth', + moduleId: 'atlassian-provider', + register(reg) { + reg.registerInit({ + deps: { + providers: authProvidersExtensionPoint, + }, + async init({ providers }) { + providers.registerProvider({ + providerId: 'atlassian', + factory: createOAuthProviderFactory({ + authenticator: atlassianAuthenticator, + signInResolverFactories: { + ...atlassianSignInResolvers, + ...commonSignInResolvers, + }, + }), + }); + }, + }); + }, +}); diff --git a/plugins/auth-backend-module-atlassian-provider/src/resolvers.ts b/plugins/auth-backend-module-atlassian-provider/src/resolvers.ts new file mode 100644 index 0000000000..1f3090bfdd --- /dev/null +++ b/plugins/auth-backend-module-atlassian-provider/src/resolvers.ts @@ -0,0 +1,50 @@ +/* + * 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. + */ + +import { + createSignInResolverFactory, + OAuthAuthenticatorResult, + PassportProfile, + SignInInfo, +} from '@backstage/plugin-auth-node'; + +/** + * Available sign-in resolvers for the Atlassian auth provider. + * + * @public + */ +export namespace atlassianSignInResolvers { + /** + * Looks up the user by matching their Atlassian username to the entity name. + */ + export const usernameMatchingUserEntityName = createSignInResolverFactory({ + create() { + return async ( + info: SignInInfo>, + ctx, + ) => { + const { result } = info; + + const id = result.fullProfile.username; + if (!id) { + throw new Error(`Atlassian user profile does not contain a username`); + } + + return ctx.signInWithCatalogUser({ entityRef: { name: id } }); + }; + }, + }); +} diff --git a/plugins/auth-backend-module-atlassian-provider/src/types.d.ts b/plugins/auth-backend-module-atlassian-provider/src/types.d.ts new file mode 100644 index 0000000000..5fd47bf885 --- /dev/null +++ b/plugins/auth-backend-module-atlassian-provider/src/types.d.ts @@ -0,0 +1,25 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare module 'passport-atlassian-oauth2' { + import { Request } from 'express'; + import { StrategyCreated } from 'passport'; + + export class Strategy { + constructor(options: any, verify: any); + authenticate(this: StrategyCreated, req: Request, options?: any): any; + } +} diff --git a/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md b/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md index c2cec39184..c201bad5dc 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-auth-backend-module-gcp-iap-provider +## 0.2.2-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## 0.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.2.1 ### Patch Changes diff --git a/plugins/auth-backend-module-gcp-iap-provider/package.json b/plugins/auth-backend-module-gcp-iap-provider/package.json index 9c309d4e22..a1d91c3a0e 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/package.json +++ b/plugins/auth-backend-module-gcp-iap-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-gcp-iap-provider", "description": "A GCP IAP auth provider module for the Backstage auth backend", - "version": "0.2.1", + "version": "0.2.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-gcp-iap-provider/src/module.ts b/plugins/auth-backend-module-gcp-iap-provider/src/module.ts index 90771eecb9..23c503c317 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/src/module.ts +++ b/plugins/auth-backend-module-gcp-iap-provider/src/module.ts @@ -26,7 +26,7 @@ import { gcpIapSignInResolvers } from './resolvers'; /** @public */ export const authModuleGcpIapProvider = createBackendModule({ pluginId: 'auth', - moduleId: 'gcpIapProvider', + moduleId: 'gcp-iap-provider', register(reg) { reg.registerInit({ deps: { diff --git a/plugins/auth-backend-module-github-provider/CHANGELOG.md b/plugins/auth-backend-module-github-provider/CHANGELOG.md index f5e95fe98f..c13445232a 100644 --- a/plugins/auth-backend-module-github-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-github-provider/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-auth-backend-module-github-provider +## 0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + ## 0.1.4 ### Patch Changes diff --git a/plugins/auth-backend-module-github-provider/package.json b/plugins/auth-backend-module-github-provider/package.json index c61542e3c5..1ac20f0e63 100644 --- a/plugins/auth-backend-module-github-provider/package.json +++ b/plugins/auth-backend-module-github-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-github-provider", "description": "The github-provider backend module for the auth plugin.", - "version": "0.1.4", + "version": "0.1.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md b/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md index d52e884e5e..6223835fe9 100644 --- a/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-auth-backend-module-gitlab-provider +## 0.1.5-next.2 + +### Patch Changes + +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + ## 0.1.4 ### Patch Changes diff --git a/plugins/auth-backend-module-gitlab-provider/package.json b/plugins/auth-backend-module-gitlab-provider/package.json index 4fb139587f..79ea08e46f 100644 --- a/plugins/auth-backend-module-gitlab-provider/package.json +++ b/plugins/auth-backend-module-gitlab-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-gitlab-provider", "description": "The gitlab-provider backend module for the auth plugin.", - "version": "0.1.4", + "version": "0.1.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -27,7 +27,7 @@ "@backstage/backend-plugin-api": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "express": "^4.18.2", - "passport": "^0.6.0", + "passport": "^0.7.0", "passport-gitlab2": "^5.0.0" }, "devDependencies": { diff --git a/plugins/auth-backend-module-google-provider/CHANGELOG.md b/plugins/auth-backend-module-google-provider/CHANGELOG.md index 05d70c2ce7..1db56eac77 100644 --- a/plugins/auth-backend-module-google-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-google-provider/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-auth-backend-module-google-provider +## 0.1.5-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + ## 0.1.4 ### Patch Changes diff --git a/plugins/auth-backend-module-google-provider/package.json b/plugins/auth-backend-module-google-provider/package.json index 719e694e1a..6638a28b9d 100644 --- a/plugins/auth-backend-module-google-provider/package.json +++ b/plugins/auth-backend-module-google-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-google-provider", "description": "A Google auth provider module for the Backstage auth backend", - "version": "0.1.4", + "version": "0.1.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-google-provider/src/module.ts b/plugins/auth-backend-module-google-provider/src/module.ts index 0354f99880..d0f8020b92 100644 --- a/plugins/auth-backend-module-google-provider/src/module.ts +++ b/plugins/auth-backend-module-google-provider/src/module.ts @@ -26,7 +26,7 @@ import { googleSignInResolvers } from './resolvers'; /** @public */ export const authModuleGoogleProvider = createBackendModule({ pluginId: 'auth', - moduleId: 'googleProvider', + moduleId: 'google-provider', register(reg) { reg.registerInit({ deps: { diff --git a/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md b/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md index 8a84f09e56..06e0039d27 100644 --- a/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-auth-backend-module-microsoft-provider +## 0.1.3-next.2 + +### Patch Changes + +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## 0.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + ## 0.1.2 ### Patch Changes diff --git a/plugins/auth-backend-module-microsoft-provider/package.json b/plugins/auth-backend-module-microsoft-provider/package.json index 4978b50e8e..c54ea24171 100644 --- a/plugins/auth-backend-module-microsoft-provider/package.json +++ b/plugins/auth-backend-module-microsoft-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-microsoft-provider", "description": "The microsoft-provider backend module for the auth plugin.", - "version": "0.1.2", + "version": "0.1.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,7 +29,7 @@ "express": "^4.18.2", "jose": "^4.6.0", "node-fetch": "^2.6.7", - "passport": "^0.6.0", + "passport": "^0.7.0", "passport-microsoft": "^1.0.0" }, "devDependencies": { diff --git a/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md b/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md index d78003079e..30a31520ae 100644 --- a/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-auth-backend-module-oauth2-provider +## 0.1.5-next.2 + +### Patch Changes + +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + ## 0.1.4 ### Patch Changes diff --git a/plugins/auth-backend-module-oauth2-provider/package.json b/plugins/auth-backend-module-oauth2-provider/package.json index b8757a5b86..e23af756f8 100644 --- a/plugins/auth-backend-module-oauth2-provider/package.json +++ b/plugins/auth-backend-module-oauth2-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-oauth2-provider", "description": "The oauth2-provider backend module for the auth plugin.", - "version": "0.1.4", + "version": "0.1.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -27,7 +27,7 @@ "@backstage/backend-plugin-api": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "express": "^4.18.2", - "passport": "^0.6.0", + "passport": "^0.7.0", "passport-oauth2": "^1.6.1" }, "devDependencies": { diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/.eslintrc.js b/plugins/auth-backend-module-oauth2-proxy-provider/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/auth-backend-module-oauth2-proxy-provider/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md b/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md new file mode 100644 index 0000000000..0a4e29ffe2 --- /dev/null +++ b/plugins/auth-backend-module-oauth2-proxy-provider/CHANGELOG.md @@ -0,0 +1,28 @@ +# @backstage/plugin-auth-backend-module-oauth2-proxy-provider + +## 0.1.0-next.1 + +### Patch Changes + +- a6be465: Exported the provider as default so it gets discovered when using `featureDiscoveryServiceFactory()` +- 510dab4: Change provider id from `oauth2ProxyProvider` to `oauth2Proxy` +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/errors@1.2.3 + +## 0.1.0-next.0 + +### Minor Changes + +- 271aa12c7c: Release of `oauth2-proxy-provider` plugin + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/README.md b/plugins/auth-backend-module-oauth2-proxy-provider/README.md new file mode 100644 index 0000000000..edec8fb3c2 --- /dev/null +++ b/plugins/auth-backend-module-oauth2-proxy-provider/README.md @@ -0,0 +1,5 @@ +# @backstage/plugin-auth-backend-module-oauth2-proxy-provider + +The oauth2-proxy-provider backend module for the auth plugin. + +_This plugin was created through the Backstage CLI_ diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/api-report.md b/plugins/auth-backend-module-oauth2-proxy-provider/api-report.md new file mode 100644 index 0000000000..1a4c1ee6d6 --- /dev/null +++ b/plugins/auth-backend-module-oauth2-proxy-provider/api-report.md @@ -0,0 +1,32 @@ +## API Report File for "@backstage/plugin-auth-backend-module-oauth2-proxy-provider" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { BackendFeature } from '@backstage/backend-plugin-api'; +import { IncomingHttpHeaders } from 'http'; +import { ProxyAuthenticator } from '@backstage/plugin-auth-node'; + +// @public (undocumented) +const authModuleOauth2ProxyProvider: () => BackendFeature; +export default authModuleOauth2ProxyProvider; + +// @public +export const OAUTH2_PROXY_JWT_HEADER = 'X-OAUTH2-PROXY-ID-TOKEN'; + +// @public (undocumented) +export const oauth2ProxyAuthenticator: ProxyAuthenticator< + unknown, + OAuth2ProxyResult +>; + +// @public +export type OAuth2ProxyResult = { + fullProfile: JWTPayload; + accessToken: string; + headers: IncomingHttpHeaders; + getHeader(name: string): string | undefined; +}; +``` diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/catalog-info.yaml b/plugins/auth-backend-module-oauth2-proxy-provider/catalog-info.yaml new file mode 100644 index 0000000000..c26202c97d --- /dev/null +++ b/plugins/auth-backend-module-oauth2-proxy-provider/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-auth-backend-module-oauth2-proxy-provider + title: '@backstage/plugin-auth-backend-module-oauth2-proxy-provider' + description: The oauth2-proxy-provider backend module for the auth plugin. +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: maintainers diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/package.json b/plugins/auth-backend-module-oauth2-proxy-provider/package.json new file mode 100644 index 0000000000..9276176ea9 --- /dev/null +++ b/plugins/auth-backend-module-oauth2-proxy-provider/package.json @@ -0,0 +1,39 @@ +{ + "name": "@backstage/plugin-auth-backend-module-oauth2-proxy-provider", + "description": "The oauth2-proxy-provider backend module for the auth plugin.", + "version": "0.1.0-next.1", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin-module" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/plugin-auth-node": "workspace:^", + "jose": "^4.6.0" + }, + "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/src/authenticator.ts b/plugins/auth-backend-module-oauth2-proxy-provider/src/authenticator.ts new file mode 100644 index 0000000000..a3da83791a --- /dev/null +++ b/plugins/auth-backend-module-oauth2-proxy-provider/src/authenticator.ts @@ -0,0 +1,71 @@ +/* + * 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. + */ + +import { AuthenticationError } from '@backstage/errors'; +import { + createProxyAuthenticator, + getBearerTokenFromAuthorizationHeader, +} from '@backstage/plugin-auth-node'; +import { decodeJwt } from 'jose'; +import { OAuth2ProxyResult } from './types'; + +/** + * NOTE: This may come in handy if you're doing work on this provider: + * plugins/auth-backend/examples/docker-compose.oauth2-proxy.yaml + * + * @public + */ +export const OAUTH2_PROXY_JWT_HEADER = 'X-OAUTH2-PROXY-ID-TOKEN'; + +/** @public */ +export const oauth2ProxyAuthenticator = createProxyAuthenticator< + unknown, + OAuth2ProxyResult +>({ + defaultProfileTransform: async (result: OAuth2ProxyResult) => { + return { + profile: { + email: result.getHeader('x-forwarded-email'), + displayName: + result.getHeader('x-forwarded-preferred-username') || + result.getHeader('x-forwarded-user'), + }, + }; + }, + async initialize() {}, + async authenticate({ req }) { + try { + const authHeader = req.header(OAUTH2_PROXY_JWT_HEADER); + const jwt = getBearerTokenFromAuthorizationHeader(authHeader); + const decodedJWT = jwt && decodeJwt(jwt); + + const result = { + fullProfile: decodedJWT || {}, + accessToken: jwt || '', + headers: req.headers, + getHeader(name: string) { + if (name.toLocaleLowerCase('en-US') === 'set-cookie') { + throw new Error('Access Set-Cookie via the headers object instead'); + } + return req.get(name); + }, + }; + return { result }; + } catch (e) { + throw new AuthenticationError('Authentication failed', e); + } + }, +}); diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/src/index.ts b/plugins/auth-backend-module-oauth2-proxy-provider/src/index.ts new file mode 100644 index 0000000000..b804f666c7 --- /dev/null +++ b/plugins/auth-backend-module-oauth2-proxy-provider/src/index.ts @@ -0,0 +1,27 @@ +/* + * 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. + */ + +/** + * The oauth2-proxy-provider backend module for the auth plugin. + * + * @packageDocumentation + */ +export { authModuleOauth2ProxyProvider as default } from './module'; +export { + oauth2ProxyAuthenticator, + OAUTH2_PROXY_JWT_HEADER, +} from './authenticator'; +export type { OAuth2ProxyResult } from './types'; diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/src/module.ts b/plugins/auth-backend-module-oauth2-proxy-provider/src/module.ts new file mode 100644 index 0000000000..70ce506d73 --- /dev/null +++ b/plugins/auth-backend-module-oauth2-proxy-provider/src/module.ts @@ -0,0 +1,49 @@ +/* + * 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. + */ + +import { createBackendModule } from '@backstage/backend-plugin-api'; +import { + authProvidersExtensionPoint, + createProxyAuthProviderFactory, + commonSignInResolvers, +} from '@backstage/plugin-auth-node'; +import { oauth2ProxyAuthenticator } from './authenticator'; +import { oauth2ProxySignInResolvers } from './resolvers'; + +/** @public */ +export const authModuleOauth2ProxyProvider = createBackendModule({ + pluginId: 'auth', + moduleId: 'oauth2-proxy-provider', + register(reg) { + reg.registerInit({ + deps: { + providers: authProvidersExtensionPoint, + }, + async init({ providers }) { + providers.registerProvider({ + providerId: 'oauth2Proxy', + factory: createProxyAuthProviderFactory({ + authenticator: oauth2ProxyAuthenticator, + signInResolverFactories: { + ...commonSignInResolvers, + ...oauth2ProxySignInResolvers, + }, + }), + }); + }, + }); + }, +}); diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/src/resolvers.ts b/plugins/auth-backend-module-oauth2-proxy-provider/src/resolvers.ts new file mode 100644 index 0000000000..99ca8bc156 --- /dev/null +++ b/plugins/auth-backend-module-oauth2-proxy-provider/src/resolvers.ts @@ -0,0 +1,41 @@ +/* + * 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. + */ + +import { + createSignInResolverFactory, + SignInInfo, +} from '@backstage/plugin-auth-node'; +import { OAuth2ProxyResult } from './types'; + +/** + * @public + */ +export namespace oauth2ProxySignInResolvers { + export const forwardedUserMatchingUserEntityName = + createSignInResolverFactory({ + create() { + return async (info: SignInInfo, ctx) => { + const name = info.result.getHeader('x-forwarded-user'); + if (!name) { + throw new Error('Request did not contain a user'); + } + return ctx.signInWithCatalogUser({ + entityRef: { name }, + }); + }; + }, + }); +} diff --git a/plugins/auth-backend-module-oauth2-proxy-provider/src/types.ts b/plugins/auth-backend-module-oauth2-proxy-provider/src/types.ts new file mode 100644 index 0000000000..5b9e97ab05 --- /dev/null +++ b/plugins/auth-backend-module-oauth2-proxy-provider/src/types.ts @@ -0,0 +1,60 @@ +/* + * 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. + */ + +import { IncomingHttpHeaders } from 'http'; + +/** + * JWT header extraction result, containing the raw value and the parsed JWT + * payload. + * + * @public + */ +export type OAuth2ProxyResult = { + /** + * The parsed payload of the `accessToken`. The token is only parsed, not verified. + * + * @deprecated Access through the `headers` instead. This will be removed in a future release. + */ + fullProfile: JWTPayload; + + /** + * The token received via the X-OAUTH2-PROXY-ID-TOKEN header. Will be an empty string + * if the header is not set. Note the this is typically an OpenID Connect token. + * + * @deprecated Access through the `headers` instead. This will be removed in a future release. + */ + accessToken: string; + + /** + * The headers of the incoming request from the OAuth2 proxy. This will include + * both the headers set by the client as well as the ones added by the OAuth2 proxy. + * You should only trust the headers that are injected by the OAuth2 proxy. + * + * Useful headers to use to complete the sign-in are for example `x-forwarded-user` + * and `x-forwarded-email`. See the OAuth2 proxy documentation for more information + * about the available headers and how to enable them. In particular it is possible + * to forward access and identity tokens, which can be user for additional verification + * and lookups. + */ + headers: IncomingHttpHeaders; + + /** + * Provides convenient access to the request headers. + * + * This call is simply forwarded to `req.get(name)`. + */ + getHeader(name: string): string | undefined; +}; diff --git a/plugins/auth-backend-module-okta-provider/.eslintrc.js b/plugins/auth-backend-module-okta-provider/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/auth-backend-module-okta-provider/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/auth-backend-module-okta-provider/CHANGELOG.md b/plugins/auth-backend-module-okta-provider/CHANGELOG.md new file mode 100644 index 0000000000..e6e91adb13 --- /dev/null +++ b/plugins/auth-backend-module-okta-provider/CHANGELOG.md @@ -0,0 +1,30 @@ +# @backstage/plugin-auth-backend-module-okta-provider + +## 0.0.1-next.2 + +### Patch Changes + +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + +## 0.0.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.0.1-next.0 + +### Patch Changes + +- e1c189b524: Adds okta-provider backend module for the auth plugin +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 diff --git a/plugins/auth-backend-module-okta-provider/README.md b/plugins/auth-backend-module-okta-provider/README.md new file mode 100644 index 0000000000..3a320a9b1a --- /dev/null +++ b/plugins/auth-backend-module-okta-provider/README.md @@ -0,0 +1,30 @@ +# Auth Module: Okta Provider + +This module provides an Okta auth provider implementation for `@backstage/plugin-auth-backend`. + +## Utilization + +This module is used in `auth-backend/src/providers/okta` + +```ts +import { oktaAuthenticator } from '@backstage/plugin-auth-backend-module-okta-provider'; + +export const okta = createAuthProviderIntegration({ + create({ + authHandler?: AuthHandler, + + signIn?: { + resolver: SignInResolver, + }, + }) { + return createOAuthProviderFactory({ + authenticator: oktaAuthenticator, + }); + }, +}); +``` + +## Links + +- [Repository](https://okta.com/backstage/backstage/tree/master/plugins/auth-backend-module-okta-provider) +- [Backstage Project Homepage](https://backstage.io) diff --git a/plugins/auth-backend-module-okta-provider/api-report.md b/plugins/auth-backend-module-okta-provider/api-report.md new file mode 100644 index 0000000000..e04c762fe2 --- /dev/null +++ b/plugins/auth-backend-module-okta-provider/api-report.md @@ -0,0 +1,30 @@ +## API Report File for "@backstage/plugin-auth-backend-module-okta-provider" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; +import { OAuthAuthenticator } from '@backstage/plugin-auth-node'; +import { OAuthAuthenticatorResult } from '@backstage/plugin-auth-node'; +import { PassportOAuthAuthenticatorHelper } from '@backstage/plugin-auth-node'; +import { PassportProfile } from '@backstage/plugin-auth-node'; +import { SignInResolverFactory } from '@backstage/plugin-auth-node'; + +// @public (undocumented) +const authModuleOktaProvider: () => BackendFeature; +export default authModuleOktaProvider; + +// @public (undocumented) +export const oktaAuthenticator: OAuthAuthenticator< + PassportOAuthAuthenticatorHelper, + PassportProfile +>; + +// @public +export namespace oktaSignInResolvers { + const emailMatchingUserEntityAnnotation: SignInResolverFactory< + OAuthAuthenticatorResult, + unknown + >; +} +``` diff --git a/plugins/auth-backend-module-okta-provider/catalog-info.yaml b/plugins/auth-backend-module-okta-provider/catalog-info.yaml new file mode 100644 index 0000000000..7a5536edcf --- /dev/null +++ b/plugins/auth-backend-module-okta-provider/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-auth-backend-module-okta-provider + title: '@backstage/plugin-auth-backend-module-okta-provider' + description: The okta-provider backend module for the auth plugin. +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: maintainers diff --git a/plugins/auth-backend-module-okta-provider/config.d.ts b/plugins/auth-backend-module-okta-provider/config.d.ts new file mode 100644 index 0000000000..f047c96739 --- /dev/null +++ b/plugins/auth-backend-module-okta-provider/config.d.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Config { + auth?: { + providers?: { + /** @visibility frontend */ + okta?: { + [authEnv: string]: { + clientId: string; + /** + * @visibility secret + */ + clientSecret: string; + audience?: string; + authServerId?: string; + idp?: string; + callbackUrl?: string; + }; + }; + }; + }; +} diff --git a/plugins/auth-backend-module-okta-provider/dev/index.ts b/plugins/auth-backend-module-okta-provider/dev/index.ts new file mode 100644 index 0000000000..d3c18c1d48 --- /dev/null +++ b/plugins/auth-backend-module-okta-provider/dev/index.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); + +backend.add(import('@backstage/plugin-auth-backend')); +backend.add(import('../src')); + +backend.start(); diff --git a/plugins/auth-backend-module-okta-provider/package.json b/plugins/auth-backend-module-okta-provider/package.json new file mode 100644 index 0000000000..765ef45c6d --- /dev/null +++ b/plugins/auth-backend-module-okta-provider/package.json @@ -0,0 +1,45 @@ +{ + "name": "@backstage/plugin-auth-backend-module-okta-provider", + "description": "The okta-provider backend module for the auth plugin.", + "version": "0.0.1-next.2", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin-module" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", + "@backstage/plugin-auth-node": "workspace:^", + "@davidzemon/passport-okta-oauth": "^0.0.5", + "express": "^4.18.2", + "passport": "^0.7.0" + }, + "devDependencies": { + "@backstage/backend-defaults": "workspace:^", + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "@backstage/plugin-auth-backend": "workspace:^", + "supertest": "^6.3.3" + }, + "configSchema": "config.d.ts", + "files": [ + "dist", + "config.d.ts" + ] +} diff --git a/plugins/auth-backend-module-okta-provider/src/authenticator.ts b/plugins/auth-backend-module-okta-provider/src/authenticator.ts new file mode 100644 index 0000000000..42201232f1 --- /dev/null +++ b/plugins/auth-backend-module-okta-provider/src/authenticator.ts @@ -0,0 +1,93 @@ +/* + * 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. + */ + +import { Strategy as OktaStrategy } from '@davidzemon/passport-okta-oauth'; +import { + createOAuthAuthenticator, + PassportOAuthAuthenticatorHelper, + PassportOAuthDoneCallback, + PassportProfile, +} from '@backstage/plugin-auth-node'; + +/** @public */ +export const oktaAuthenticator = createOAuthAuthenticator({ + defaultProfileTransform: + PassportOAuthAuthenticatorHelper.defaultProfileTransform, + initialize({ callbackUrl, config }) { + const clientId = config.getString('clientId'); + const clientSecret = config.getString('clientSecret'); + const audience = config.getOptionalString('audience') || 'https://okta.com'; + const authServerId = config.getOptionalString('authServerId'); + const idp = config.getOptionalString('idp'); + // default scopes are taken from + // https://developer.okta.com/docs/reference/api/oidc/#response-example-success-refresh-token + const defaultScopes = 'openid profile email'; + // additional scopes can be configured in the config as a space separated string + const additionalScopes = config.getOptionalString('additionalScopes') || ''; + // combine default and additional scopes and remove duplicates + const combineScopeStrings = (scopesA: string, scopesB: string) => { + const scopesAArray = scopesA.split(' '); + const scopesBArray = scopesB.split(' '); + const combinedScopes = new Set([...scopesAArray, ...scopesBArray]); + return Array.from(combinedScopes).join(' '); + }; + const scope = combineScopeStrings(defaultScopes, additionalScopes); + + return PassportOAuthAuthenticatorHelper.from( + new OktaStrategy( + { + clientID: clientId, + clientSecret: clientSecret, + callbackURL: callbackUrl, + audience: audience, + authServerID: authServerId, + idp: idp, + passReqToCallback: false, + response_type: 'code', + scope, + }, + ( + accessToken: string, + refreshToken: string, + params: any, + fullProfile: PassportProfile, + done: PassportOAuthDoneCallback, + ) => { + done( + undefined, + { fullProfile, params, accessToken }, + { refreshToken }, + ); + }, + ), + ); + }, + + async start(input, helper) { + return helper.start(input, { + accessType: 'offline', + prompt: 'consent', + }); + }, + + async authenticate(input, helper) { + return helper.authenticate(input); + }, + + async refresh(input, helper) { + return helper.refresh(input); + }, +}); diff --git a/plugins/auth-backend-module-okta-provider/src/index.ts b/plugins/auth-backend-module-okta-provider/src/index.ts new file mode 100644 index 0000000000..43a075d56f --- /dev/null +++ b/plugins/auth-backend-module-okta-provider/src/index.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +/** + * The okta-provider backend module for the auth plugin. + * + * @packageDocumentation + */ + +export { oktaAuthenticator } from './authenticator'; +export { authModuleOktaProvider as default } from './module'; +export { oktaSignInResolvers } from './resolvers'; diff --git a/plugins/auth-backend-module-okta-provider/src/module.test.ts b/plugins/auth-backend-module-okta-provider/src/module.test.ts new file mode 100644 index 0000000000..e469067b3f --- /dev/null +++ b/plugins/auth-backend-module-okta-provider/src/module.test.ts @@ -0,0 +1,82 @@ +/* + * 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. + */ + +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; +import { authModuleOktaProvider } from './module'; +import request from 'supertest'; +import { decodeOAuthState } from '@backstage/plugin-auth-node'; + +describe('authModuleOktaProvider', () => { + it('should start', async () => { + const defaultScopes = 'openid profile email'; + const additionalScopes = 'groups phone'; + const combinedScopes = `${defaultScopes} ${additionalScopes}`; + const { server } = await startTestBackend({ + features: [ + import('@backstage/plugin-auth-backend'), + authModuleOktaProvider, + mockServices.rootConfig.factory({ + data: { + app: { + baseUrl: 'http://localhost:3000', + }, + auth: { + providers: { + okta: { + development: { + clientId: 'my-client-id', + clientSecret: 'my-client-secret', + additionalScopes, + }, + }, + }, + }, + }, + }), + ], + }); + + const agent = request.agent(server); + + const res = await agent.get('/api/auth/okta/start?env=development'); + + expect(res.status).toEqual(302); + + const nonceCookie = agent.jar.getCookie('okta-nonce', { + domain: 'localhost', + path: '/api/auth/okta/handler', + script: false, + secure: false, + }); + expect(nonceCookie).toBeDefined(); + + const startUrl = new URL(res.get('location')); + expect(startUrl.origin).toBe('https://okta.com'); + expect(startUrl.pathname).toBe('/oauth2/v1/authorize'); + expect(Object.fromEntries(startUrl.searchParams)).toEqual({ + response_type: 'code', + scope: combinedScopes, + client_id: 'my-client-id', + redirect_uri: `http://localhost:${server.port()}/api/auth/okta/handler/frame`, + state: expect.any(String), + }); + + expect(decodeOAuthState(startUrl.searchParams.get('state')!)).toEqual({ + env: 'development', + nonce: decodeURIComponent(nonceCookie.value), + }); + }); +}); diff --git a/plugins/auth-backend-module-okta-provider/src/module.ts b/plugins/auth-backend-module-okta-provider/src/module.ts new file mode 100644 index 0000000000..35cb6634d5 --- /dev/null +++ b/plugins/auth-backend-module-okta-provider/src/module.ts @@ -0,0 +1,48 @@ +/* + * 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. + */ +import { createBackendModule } from '@backstage/backend-plugin-api'; +import { + authProvidersExtensionPoint, + commonSignInResolvers, + createOAuthProviderFactory, +} from '@backstage/plugin-auth-node'; +import { oktaAuthenticator } from './authenticator'; +import { oktaSignInResolvers } from './resolvers'; + +/** @public */ +export const authModuleOktaProvider = createBackendModule({ + pluginId: 'auth', + moduleId: 'okta-provider', + register(reg) { + reg.registerInit({ + deps: { + providers: authProvidersExtensionPoint, + }, + async init({ providers }) { + providers.registerProvider({ + providerId: 'okta', + factory: createOAuthProviderFactory({ + authenticator: oktaAuthenticator, + signInResolverFactories: { + ...oktaSignInResolvers, + ...commonSignInResolvers, + }, + }), + }); + }, + }); + }, +}); diff --git a/plugins/auth-backend-module-okta-provider/src/resolvers.ts b/plugins/auth-backend-module-okta-provider/src/resolvers.ts new file mode 100644 index 0000000000..8bc3f38f17 --- /dev/null +++ b/plugins/auth-backend-module-okta-provider/src/resolvers.ts @@ -0,0 +1,54 @@ +/* + * 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. + */ + +import { + createSignInResolverFactory, + OAuthAuthenticatorResult, + PassportProfile, + SignInInfo, +} from '@backstage/plugin-auth-node'; + +/** + * Available sign-in resolvers for the Okta auth provider. + * + * @public + */ +export namespace oktaSignInResolvers { + /** + * Looks up the user by matching their Okta email to the entity email. + */ + + export const emailMatchingUserEntityAnnotation = createSignInResolverFactory({ + create() { + return async ( + info: SignInInfo>, + ctx, + ) => { + const { profile } = info; + + if (!profile.email) { + throw new Error('Okta profile contained no email'); + } + + return ctx.signInWithCatalogUser({ + annotations: { + 'okta.com/email': profile.email, + }, + }); + }; + }, + }); +} diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/eks.ts b/plugins/auth-backend-module-okta-provider/src/types.d.ts similarity index 69% rename from plugins/kubernetes-react/src/utils/clusterLinks/formatters/eks.ts rename to plugins/auth-backend-module-okta-provider/src/types.d.ts index 975c39797c..58cfb74173 100644 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/eks.ts +++ b/plugins/auth-backend-module-okta-provider/src/types.d.ts @@ -13,8 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ClusterLinksFormatterOptions } from '../../../types/types'; -export function eksFormatter(_options: ClusterLinksFormatterOptions): URL { - throw new Error('EKS formatter is not yet implemented. Please, contribute!'); +declare module 'passport-okta2' { + import { Request } from 'express'; + import { StrategyCreated } from 'passport'; + + export class Strategy { + constructor(options: any, verify: any); + authenticate(this: StrategyCreated, req: Request, options?: any): any; + } } diff --git a/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md b/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md index 14dfd67840..d0153f1e26 100644 --- a/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-auth-backend-module-pinniped-provider +## 0.1.2-next.2 + +### Patch Changes + +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + ## 0.1.1 ### Patch Changes diff --git a/plugins/auth-backend-module-pinniped-provider/package.json b/plugins/auth-backend-module-pinniped-provider/package.json index b2153128e9..0d799504a1 100644 --- a/plugins/auth-backend-module-pinniped-provider/package.json +++ b/plugins/auth-backend-module-pinniped-provider/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend-module-pinniped-provider", "description": "The pinniped-provider backend module for the auth plugin.", - "version": "0.1.1", + "version": "0.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -41,7 +41,7 @@ "express-session": "^1.17.3", "jose": "^4.14.6", "msw": "^1.3.0", - "passport": "^0.6.0", + "passport": "^0.7.0", "supertest": "^6.3.3" }, "files": [ diff --git a/plugins/auth-backend-module-pinniped-provider/src/module.test.ts b/plugins/auth-backend-module-pinniped-provider/src/module.test.ts index ed285cff86..a5c8fb4599 100644 --- a/plugins/auth-backend-module-pinniped-provider/src/module.test.ts +++ b/plugins/auth-backend-module-pinniped-provider/src/module.test.ts @@ -13,30 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; -import request from 'supertest'; -import { setupServer } from 'msw/node'; -import { rest } from 'msw'; -import { Server } from 'http'; -import express from 'express'; -import cookieParser from 'cookie-parser'; -import session from 'express-session'; -import passport from 'passport'; -import { AddressInfo } from 'net'; import { - AuthProviderRouteHandlers, - createOAuthRouteHandlers, -} from '@backstage/plugin-auth-node'; -import Router from 'express-promise-router'; -import { pinnipedAuthenticator } from './authenticator'; -import { ConfigReader } from '@backstage/config'; + mockServices, + setupRequestMockHandlers, + startTestBackend, +} from '@backstage/backend-test-utils'; +import { Server } from 'http'; import { JWK, SignJWT, exportJWK, generateKeyPair } from 'jose'; +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; +import request from 'supertest'; +import { authModulePinnipedProvider } from './module'; describe('authModulePinnipedProvider', () => { - let app: express.Express; - let backstageServer: Server; - let appUrl: string; - let providerRouteHandler: AuthProviderRouteHandlers; + let server: Server; + let port: number; let idToken: string; let publicKey: JWK; @@ -151,73 +142,38 @@ describe('authModulePinnipedProvider', () => { }), ); - const secret = 'secret'; - app = express() - .use(cookieParser(secret)) - .use( - session({ - secret, - saveUninitialized: false, - resave: false, - cookie: { secure: false }, - }), - ) - .use(passport.initialize()) - .use(passport.session()); - await new Promise(resolve => { - backstageServer = app.listen(0, '0.0.0.0', () => { - appUrl = `http://127.0.0.1:${ - (backstageServer.address() as AddressInfo).port - }`; - resolve(null); - }); - }); - - mswServer.use(rest.all(`${appUrl}/*`, req => req.passthrough())); - - providerRouteHandler = createOAuthRouteHandlers({ - authenticator: pinnipedAuthenticator, - appUrl, - baseUrl: `${appUrl}/api/auth`, - isOriginAllowed: _ => true, - providerId: 'pinniped', - config: new ConfigReader({ - federationDomain: 'https://federationDomain.test', - clientId: 'clientId', - clientSecret: 'clientSecret', - }), - resolverContext: { - issueToken: async _ => ({ token: '' }), - findCatalogUser: async _ => ({ - entity: { - apiVersion: '', - kind: '', - metadata: { name: '' }, + const backend = await startTestBackend({ + features: [ + authModulePinnipedProvider, + import('@backstage/plugin-auth-backend'), + mockServices.rootConfig.factory({ + data: { + app: { baseUrl: 'http://localhost' }, + auth: { + session: { secret: 'test' }, + providers: { + pinniped: { + development: { + federationDomain: 'https://federationDomain.test', + clientId: 'clientId', + clientSecret: 'clientSecret', + }, + }, + }, + }, }, }), - signInWithCatalogUser: async _ => ({ token: '' }), - }, + ], }); - const router = Router(); - router - .use( - '/api/auth/pinniped/start', - providerRouteHandler.start.bind(providerRouteHandler), - ) - .use( - '/api/auth/pinniped/handler/frame', - providerRouteHandler.frameHandler.bind(providerRouteHandler), - ); - app.use(router); - }); + server = backend.server; + port = backend.server.port(); - afterEach(() => { - backstageServer.close(); + mswServer.use(rest.all(`http://*:${port}/*`, req => req.passthrough())); }); it('should start', async () => { - const agent = request.agent(backstageServer); + const agent = request.agent(server); const startResponse = await agent.get( `/api/auth/pinniped/start?env=development&audience=test_cluster`, ); @@ -230,15 +186,20 @@ describe('authModulePinnipedProvider', () => { // make /start request with audience parameter const startResponse = await agent.get( - `${appUrl}/api/auth/pinniped/start?env=development&audience=test_cluster`, + `http://localhost:${port}/api/auth/pinniped/start?env=development&audience=test_cluster`, ); - // follow redirect to authorization endpoint - const authorizationResponse = await agent.get( - startResponse.header.location, + + // Emulate user interaction with the Pinniped login page + const authResponse = await agent.get(startResponse.header.location); + expect(authResponse.status).toBe(302); + const callbackUrl = new URL(authResponse.header.location); + + // follow redirect from the login page back to the callback URL to the Backstage auth backend + const relativeCallbackUrl = String(callbackUrl).slice( + callbackUrl.origin.length, ); - // follow redirect to token_endpoint const handlerResponse = await agent.get( - authorizationResponse.header.location, + `http://localhost:${port}${relativeCallbackUrl}`, ); expect(handlerResponse.text).toContain( diff --git a/plugins/auth-backend-module-vmware-cloud-provider/.eslintrc.js b/plugins/auth-backend-module-vmware-cloud-provider/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md b/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md new file mode 100644 index 0000000000..4defbe348e --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/CHANGELOG.md @@ -0,0 +1,25 @@ +# @backstage/plugin-auth-backend-module-vmware-cloud-provider + +## 0.1.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + +## 0.1.0-next.0 + +### Minor Changes + +- ed02c69a3c: Add VMware Cloud auth backend module provider + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-auth-node@0.4.2-next.1 diff --git a/plugins/auth-backend-module-vmware-cloud-provider/README.md b/plugins/auth-backend-module-vmware-cloud-provider/README.md new file mode 100644 index 0000000000..d06a0d84ab --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/README.md @@ -0,0 +1,7 @@ +# Auth Module: VMware Cloud Provider + +This module provides an VMware Cloud auth provider implementation for `@backstage/plugin-auth-backend`. + +## Links + +- [Backstage](https://backstage.io) diff --git a/plugins/auth-backend-module-vmware-cloud-provider/api-report.md b/plugins/auth-backend-module-vmware-cloud-provider/api-report.md new file mode 100644 index 0000000000..ff9e82dd45 --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/api-report.md @@ -0,0 +1,46 @@ +## API Report File for "@backstage/plugin-auth-backend-module-vmware-cloud-provider" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; +import { OAuthAuthenticator } from '@backstage/plugin-auth-node'; +import { OAuthAuthenticatorResult } from '@backstage/plugin-auth-node'; +import { PassportOAuthAuthenticatorHelper } from '@backstage/plugin-auth-node'; +import { PassportProfile } from '@backstage/plugin-auth-node'; +import { SignInResolverFactory } from '@backstage/plugin-auth-node'; +import { Strategy } from 'passport-oauth2'; + +// @public +const authModuleVmwareCloudProvider: () => BackendFeature; +export default authModuleVmwareCloudProvider; + +// @public +export const vmwareCloudAuthenticator: OAuthAuthenticator< + VMwareCloudAuthenticatorContext, + VMwarePassportProfile +>; + +// @public (undocumented) +export interface VMwareCloudAuthenticatorContext { + // (undocumented) + helper: PassportOAuthAuthenticatorHelper; + // (undocumented) + organizationId?: string; + // (undocumented) + providerStrategy: Strategy; +} + +// @public +export namespace vmwareCloudSignInResolvers { + const profileEmailMatchingUserEntityEmail: SignInResolverFactory< + OAuthAuthenticatorResult, + unknown + >; +} + +// @public (undocumented) +export type VMwarePassportProfile = PassportProfile & { + organizationId?: string; +}; +``` diff --git a/plugins/auth-backend-module-vmware-cloud-provider/catalog-info.yaml b/plugins/auth-backend-module-vmware-cloud-provider/catalog-info.yaml new file mode 100644 index 0000000000..d40b1e4308 --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-auth-backend-module-vmware-cloud-provider + title: '@backstage/plugin-auth-backend-module-vmware-cloud-provider' + description: The vmware-cloud-provider backend module for the auth plugin. +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: maintainers diff --git a/plugins/auth-backend-module-vmware-cloud-provider/config.d.ts b/plugins/auth-backend-module-vmware-cloud-provider/config.d.ts new file mode 100644 index 0000000000..10b3566899 --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/config.d.ts @@ -0,0 +1,31 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Config { + auth?: { + providers?: { + /** @visibility frontend */ + vmwareCloudServices?: { + [authEnv: string]: { + clientId: string; + organizationId: string; + scope?: string; + consoleEndpoint?: string; + }; + }; + }; + }; +} diff --git a/plugins/auth-backend-module-vmware-cloud-provider/dev/index.ts b/plugins/auth-backend-module-vmware-cloud-provider/dev/index.ts new file mode 100644 index 0000000000..d3c18c1d48 --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/dev/index.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +import { createBackend } from '@backstage/backend-defaults'; + +const backend = createBackend(); + +backend.add(import('@backstage/plugin-auth-backend')); +backend.add(import('../src')); + +backend.start(); diff --git a/plugins/auth-backend-module-vmware-cloud-provider/package.json b/plugins/auth-backend-module-vmware-cloud-provider/package.json new file mode 100644 index 0000000000..6a054c2a70 --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/package.json @@ -0,0 +1,47 @@ +{ + "name": "@backstage/plugin-auth-backend-module-vmware-cloud-provider", + "description": "The vmware-cloud-provider backend module for the auth plugin.", + "version": "0.1.0-next.1", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "backstage": { + "role": "backend-plugin-module" + }, + "scripts": { + "start": "backstage-cli package start", + "build": "backstage-cli package build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "clean": "backstage-cli package clean", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack" + }, + "dependencies": { + "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", + "@backstage/catalog-model": "workspace:^", + "@backstage/plugin-auth-node": "workspace:^", + "@types/passport-oauth2": "^1.4.15", + "jose": "^4.6.0", + "passport-oauth2": "^1.6.1" + }, + "devDependencies": { + "@backstage/backend-defaults": "workspace:^", + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/plugin-auth-backend": "workspace:^", + "msw": "^2.0.8", + "supertest": "^6.3.3" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/auth-backend-module-vmware-cloud-provider/src/authenticator.test.ts b/plugins/auth-backend-module-vmware-cloud-provider/src/authenticator.test.ts new file mode 100644 index 0000000000..f38ceeb462 --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/src/authenticator.test.ts @@ -0,0 +1,477 @@ +/* + * 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. + */ + +import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; +import { ConfigReader } from '@backstage/config'; +import { + AuthResolverContext, + encodeOAuthState, + OAuthAuthenticatorAuthenticateInput, + OAuthAuthenticatorRefreshInput, + OAuthAuthenticatorStartInput, + OAuthState, +} from '@backstage/plugin-auth-node'; +import { SignJWT } from 'jose'; +import { http, HttpResponse } from 'msw'; +import { setupServer } from 'msw/node'; + +import { + vmwareCloudAuthenticator, + VMwareCloudAuthenticatorContext, +} from './authenticator'; + +jest.mock('uid2', () => jest.fn().mockReturnValue('sessionid')); + +describe('vmwareCloudAuthenticator', () => { + const server = setupServer(); + setupRequestMockHandlers(server); + + let oAuthState: OAuthState = { + nonce: 'nonce', + env: 'env', + }; + + const signInInfo: Record = { + given_name: 'Givenname', + family_name: 'Familyname', + context_name: 'orgId', + email: 'user@example.com', + }; + + let idToken: string; + + let authResponse: { + access_token: string; + refresh_token: string; + id_token: typeof idToken; + }; + + let fakeSession: Record; + let authenticatorCtx: VMwareCloudAuthenticatorContext; + + beforeAll(async () => { + idToken = await new SignJWT(signInInfo) + .setProtectedHeader({ alg: 'HS256' }) + .sign(Buffer.from('signing key')); + + authResponse = { + access_token: 'accessToken', + refresh_token: 'refreshToken', + id_token: idToken, + }; + }); + + beforeEach(() => { + server.use( + http.post( + 'https://console.cloud.vmware.com/csp/gateway/am/api/auth/token', + ({ request }) => + request.headers.get('Authorization') + ? HttpResponse.json(authResponse) + : HttpResponse.json(null, { status: 500 }), + ), + ); + + authenticatorCtx = vmwareCloudAuthenticator.initialize({ + callbackUrl: 'http://callbackUrl', + config: new ConfigReader({ + clientId: 'placeholderClientId', + organizationId: 'orgId', + }), + }); + }); + + describe('#initialize', () => { + it('fails when organizationId is not configured', () => { + return expect(() => + vmwareCloudAuthenticator.initialize({ + callbackUrl: 'http://callbackUrl', + config: new ConfigReader({ + clientId: 'placeholderClientId', + }), + }), + ).toThrow(`Missing required config value at 'organizationId'`); + }); + }); + + describe('#start', () => { + let startRequest: OAuthAuthenticatorStartInput; + + beforeEach(() => { + fakeSession = {}; + startRequest = { + state: encodeOAuthState(oAuthState), + req: { + query: {}, + session: fakeSession, + }, + } as OAuthAuthenticatorStartInput; + }); + + it('redirects to the Cloud Services Console consent page', async () => { + const startResponse = await vmwareCloudAuthenticator.start( + startRequest, + authenticatorCtx, + ); + const url = new URL(startResponse.url); + + expect(url.protocol).toBe('https:'); + expect(url.hostname).toBe('console.cloud.vmware.com'); + expect(url.pathname).toBe('/csp/gateway/discovery'); + }); + + it('passes client ID from config', async () => { + const startResponse = await vmwareCloudAuthenticator.start( + startRequest, + authenticatorCtx, + ); + const { searchParams } = new URL(startResponse.url); + + expect(searchParams.get('client_id')).toBe('placeholderClientId'); + }); + + it('passes organizationId from config', async () => { + const startResponse = await vmwareCloudAuthenticator.start( + startRequest, + authenticatorCtx, + ); + const { searchParams } = new URL(startResponse.url); + + expect(searchParams.get('orgId')).toBe('orgId'); + }); + + it('passes callback URL', async () => { + const startResponse = await vmwareCloudAuthenticator.start( + startRequest, + authenticatorCtx, + ); + const { searchParams } = new URL(startResponse.url); + + expect(searchParams.get('redirect_uri')).toBe('http://callbackUrl'); + }); + + it('requests scopes for ID and refresh token', async () => { + const startResponse = await vmwareCloudAuthenticator.start( + startRequest, + authenticatorCtx, + ); + const { searchParams } = new URL(startResponse.url); + + expect(searchParams.get('scope')).toBe('openid offline_access'); + }); + + it('generates PKCE challenge', async () => { + const startResponse = await vmwareCloudAuthenticator.start( + startRequest, + authenticatorCtx, + ); + const { searchParams } = new URL(startResponse.url); + + expect(searchParams.get('code_challenge_method')).toBe('S256'); + expect(searchParams.get('code_challenge')).not.toBeNull(); + }); + + it('stores PKCE verifier in session', async () => { + await vmwareCloudAuthenticator.start(startRequest, authenticatorCtx); + + expect( + fakeSession['oauth2:console.cloud.vmware.com'].state.code_verifier, + ).toBeDefined(); + }); + + it('fails when request has no session', () => { + return expect( + vmwareCloudAuthenticator.start( + { + state: encodeOAuthState(oAuthState), + req: { + query: {}, + }, + } as OAuthAuthenticatorStartInput, + authenticatorCtx, + ), + ).rejects.toThrow('requires session support'); + }); + + it('adds session ID handle to state param', async () => { + const startResponse = await vmwareCloudAuthenticator.start( + startRequest, + authenticatorCtx, + ); + const stateParam = new URL(startResponse.url).searchParams.get('state'); + + const state = Object.fromEntries( + new URLSearchParams(Buffer.from(stateParam!, 'hex').toString('utf-8')), + ); + + const { handle } = fakeSession['oauth2:console.cloud.vmware.com'].state; + expect(state.handle).toBe(handle); + }); + }); + + describe('#authenticate', () => { + let resolverContext: jest.Mocked; + let authenticateRequest: OAuthAuthenticatorAuthenticateInput; + + beforeEach(() => { + resolverContext = { + issueToken: jest.fn().mockResolvedValue({ + token: 'defaultBackstageToken', + }), + findCatalogUser: jest.fn(), + signInWithCatalogUser: jest.fn().mockResolvedValue({ + token: 'backstageToken', + }), + }; + + oAuthState = { + code_verifier: 'foo', + handle: 'sessionid', + nonce: 'nonce', + env: 'development', + } as OAuthState; + + fakeSession = { + ['oauth2:console.cloud.vmware.com']: { + state: oAuthState, + }, + }; + + authenticateRequest = { + req: { + query: { + code: 'foo', + state: encodeOAuthState(oAuthState), + } as unknown, + session: fakeSession, + }, + } as OAuthAuthenticatorAuthenticateInput; + }); + + it('stores refresh token in cookie', async () => { + const { + session: { refreshToken }, + } = await vmwareCloudAuthenticator.authenticate( + authenticateRequest, + authenticatorCtx, + ); + + expect(refreshToken).toBe('refreshToken'); + }); + + it('responds with ID token', async () => { + const { session } = await vmwareCloudAuthenticator.authenticate( + authenticateRequest, + authenticatorCtx, + ); + + expect(session.idToken).toBe(idToken); + }); + + it('default transform decodes ID token', async () => { + const result = await vmwareCloudAuthenticator.authenticate( + authenticateRequest, + authenticatorCtx, + ); + + const { profile } = + await vmwareCloudAuthenticator.defaultProfileTransform( + result, + resolverContext, + ); + + expect(profile).toStrictEqual({ + email: signInInfo.email, + displayName: `${signInInfo.given_name} ${signInInfo.family_name}`, + }); + }); + + it('default transform fails if claims are missing', async () => { + authenticatorCtx = vmwareCloudAuthenticator.initialize({ + callbackUrl: 'http://callbackUrl', + config: new ConfigReader({ + clientId: 'placeholderClientId', + organizationId: 'myOrgId', + }), + }); + + const result = await vmwareCloudAuthenticator.authenticate( + authenticateRequest, + authenticatorCtx, + ); + + return expect( + vmwareCloudAuthenticator.defaultProfileTransform( + result, + resolverContext, + ), + ).rejects.toThrow('ID token organizationId mismatch'); + }); + + it('default transform fails if organizationId mismatch', async () => { + const inadequateIdToken: string = await new SignJWT({ sub: 'unusual' }) + .setProtectedHeader({ alg: 'HS256' }) + .sign(Buffer.from('signing key')); + + server.use( + http.post( + 'https://console.cloud.vmware.com/csp/gateway/am/api/auth/token', + () => + HttpResponse.json({ + access_token: 'accessToken', + id_token: inadequateIdToken, + }), + ), + ); + + const result = await vmwareCloudAuthenticator.authenticate( + authenticateRequest, + authenticatorCtx, + ); + + return expect( + vmwareCloudAuthenticator.defaultProfileTransform( + result, + resolverContext, + ), + ).rejects.toThrow( + 'ID token missing required claims: email, given_name, family_name', + ); + }); + + it('fails when request has no session', () => { + return expect( + vmwareCloudAuthenticator.authenticate( + { + req: { + query: {}, + }, + } as OAuthAuthenticatorStartInput, + authenticatorCtx, + ), + ).rejects.toThrow('requires session support'); + }); + + it('fails when request has no authorization code', () => { + return expect( + vmwareCloudAuthenticator.authenticate( + { + req: { + query: {}, + session: fakeSession, + }, + } as OAuthAuthenticatorStartInput, + authenticatorCtx, + ), + ).rejects.toThrow('Unexpected redirect'); + }); + }); + + describe('integration between #start and #authenticate', () => { + beforeEach(() => { + fakeSession = { + ['oauth2:console.cloud.vmware.com']: { + state: oAuthState, + }, + }; + }); + + it('state param is compatible', async () => { + const startResponse = await vmwareCloudAuthenticator.start( + { + req: { + query: {}, + session: {}, + }, + state: encodeOAuthState(oAuthState), + } as OAuthAuthenticatorStartInput, + authenticatorCtx, + ); + const { searchParams } = new URL(startResponse.url); + const { session } = await vmwareCloudAuthenticator.authenticate( + { + req: { + query: { + code: 'authorization_code', + state: searchParams.get('state'), + } as unknown, + session: fakeSession, + }, + } as OAuthAuthenticatorAuthenticateInput, + authenticatorCtx, + ); + + expect(session).toBeDefined(); + expect(session.idToken).toBe(idToken); + }); + }); + + describe('#refresh', () => { + let refreshRequest: OAuthAuthenticatorRefreshInput; + let resolverContext: jest.Mocked; + + beforeEach(() => { + resolverContext = { + issueToken: jest.fn().mockResolvedValue({ + token: 'defaultBackstageToken', + }), + findCatalogUser: jest.fn(), + signInWithCatalogUser: jest.fn().mockResolvedValue({ + token: 'backstageToken', + }), + }; + + refreshRequest = { + req: { + query: { + code: 'foo', + state: 'sessionid', + } as unknown, + session: fakeSession, + }, + } as OAuthAuthenticatorRefreshInput; + }); + + it('gets new refresh token', async () => { + const { + session: { refreshToken }, + } = await vmwareCloudAuthenticator.refresh( + refreshRequest, + authenticatorCtx, + ); + + expect(refreshToken).toBe('refreshToken'); + }); + + it('default transform decodes ID token', async () => { + const result = await vmwareCloudAuthenticator.refresh( + refreshRequest, + authenticatorCtx, + ); + + const { profile } = + await vmwareCloudAuthenticator.defaultProfileTransform( + result, + resolverContext, + ); + + expect(profile).toStrictEqual({ + email: signInInfo.email, + displayName: `${signInInfo.given_name} ${signInInfo.family_name}`, + }); + }); + }); +}); diff --git a/plugins/auth-backend-module-vmware-cloud-provider/src/authenticator.ts b/plugins/auth-backend-module-vmware-cloud-provider/src/authenticator.ts new file mode 100644 index 0000000000..4db4836f13 --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/src/authenticator.ts @@ -0,0 +1,238 @@ +/* + * 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. + */ +import { + createOAuthAuthenticator, + decodeOAuthState, + encodeOAuthState, + OAuthState, + PassportOAuthAuthenticatorHelper, + PassportOAuthDoneCallback, + PassportProfile, +} from '@backstage/plugin-auth-node'; +import { decodeJwt } from 'jose'; +import { + Metadata, + StateStoreStoreCallback, + StateStoreVerifyCallback, + Strategy as OAuth2Strategy, +} from 'passport-oauth2'; + +/** @public */ +export interface VMwareCloudAuthenticatorContext { + organizationId?: string; + providerStrategy: OAuth2Strategy; + helper: PassportOAuthAuthenticatorHelper; +} + +/** @public */ +export type VMwarePassportProfile = PassportProfile & { + organizationId?: string; +}; + +/** + * VMware Cloud Authenticator to be used by `createOAuthProviderFactory` + * + * @public + */ +export const vmwareCloudAuthenticator = createOAuthAuthenticator< + VMwareCloudAuthenticatorContext, + VMwarePassportProfile +>({ + defaultProfileTransform: async input => { + if (!input.session.idToken) { + throw new Error( + `Failed to parse id token and get profile info, missing token from session`, + ); + } + + const vmwareClaims = ['email', 'given_name', 'family_name', 'context_name']; + + const identity = decodeJwt(input.session.idToken); + const missingClaims = vmwareClaims.filter(key => !(key in identity)); + + if (missingClaims.length > 0) { + throw new Error( + `ID token missing required claims: ${missingClaims.join(', ')}`, + ); + } + + const typeMismatchClaims = vmwareClaims.filter( + key => typeof identity[key] !== 'string', + ); + + if (typeMismatchClaims.length > 0) { + throw new Error( + `ID token claims type mismatch: ${typeMismatchClaims.join(', ')}`, + ); + } + + // These claims were checked for presence & type + const { email, given_name, family_name, context_name } = identity as Record< + string, + string + >; + + if (context_name !== input.fullProfile.organizationId) { + throw new Error(`ID token organizationId mismatch`); + } + + return { + profile: { + displayName: `${given_name} ${family_name}`, + email, + }, + }; + }, + initialize({ callbackUrl, config }) { + const consoleEndpoint = + config.getOptionalString('consoleEndpoint') ?? + 'https://console.cloud.vmware.com'; + const organizationId = config.getString('organizationId'); + + const clientId = config.getString('clientId'); + const clientSecret = ''; + const authorizationUrl = `${consoleEndpoint}/csp/gateway/discovery`; + const tokenUrl = `${consoleEndpoint}/csp/gateway/am/api/auth/token`; + const scope = config.getOptionalString('scope') ?? 'openid offline_access'; + + const providerStrategy = new OAuth2Strategy( + { + clientID: clientId, + clientSecret: clientSecret, + callbackURL: callbackUrl, + authorizationURL: authorizationUrl, + tokenURL: tokenUrl, + passReqToCallback: false, + pkce: true, + state: true, + scope: scope, + customHeaders: { + Authorization: `Basic ${encodeClientCredentials( + clientId, + clientSecret, + )}`, + }, + }, + ( + accessToken: any, + refreshToken: any, + params: any, + fullProfile: PassportProfile, + done: PassportOAuthDoneCallback, + ) => { + done(undefined, { fullProfile, params, accessToken }, { refreshToken }); + }, + ); + + // Both VMware & OAuth2Strategy fight over control of the state when PKCE is on, thus this hack + const pkceSessionStore = Object.create( + (providerStrategy as any)._stateStore, + ); + (providerStrategy as any)._stateStore = { + verify(req: Request, state: string, callback: StateStoreVerifyCallback) { + pkceSessionStore.verify( + req, + (decodeOAuthState(state) as any).handle, + callback, + ); + }, + store( + req: Request & { + scope: string; + state: OAuthState; + }, + verifier: string, + state: any, + meta: Metadata, + callback: StateStoreStoreCallback, + ) { + pkceSessionStore.store( + req, + verifier, + state, + meta, + (err: Error, handle: string) => { + callback( + err, + encodeOAuthState({ + handle, + ...state, + ...req.state, + } as OAuthState), + ); + }, + ); + }, + }; + + return { + organizationId, + providerStrategy, + helper: PassportOAuthAuthenticatorHelper.from(providerStrategy), + }; + }, + + async start(input, ctx) { + return new Promise((resolve, reject) => { + const strategy: OAuth2Strategy = Object.create(ctx.providerStrategy); + + strategy.redirect = (url: string, status?: number) => { + const parsed = new URL(url); + if (ctx.organizationId) { + parsed.searchParams.set('orgId', ctx.organizationId); + } + resolve({ url: parsed.toString(), status: status ?? undefined }); + }; + strategy.error = (error: Error) => { + reject(error); + }; + strategy.authenticate(input.req, { + scope: input.scope, + state: decodeOAuthState(input.state), + accessType: 'offline', + prompt: 'consent', + }); + }); + }, + + async authenticate(input, ctx) { + return ctx.helper.authenticate(input).then(result => ({ + ...result, + fullProfile: { + ...result.fullProfile, + organizationId: ctx.organizationId, + } as VMwarePassportProfile, + })); + }, + + async refresh(input, ctx) { + return ctx.helper.refresh(input).then(result => ({ + ...result, + fullProfile: { + ...result.fullProfile, + organizationId: ctx.organizationId, + } as VMwarePassportProfile, + })); + }, +}); + +/** @private */ +function encodeClientCredentials( + clientID: string, + clientSecret: string, +): string { + return Buffer.from(`${clientID}:${clientSecret}`).toString('base64'); +} diff --git a/plugins/auth-backend-module-vmware-cloud-provider/src/index.ts b/plugins/auth-backend-module-vmware-cloud-provider/src/index.ts new file mode 100644 index 0000000000..1d7bb14b63 --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/src/index.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +/** + * The vmware-cloud-provider backend module for the auth plugin. + * + * @packageDocumentation + */ + +export { + vmwareCloudAuthenticator, + type VMwareCloudAuthenticatorContext, + type VMwarePassportProfile, +} from './authenticator'; +export { authModuleVmwareCloudProvider as default } from './module'; +export { vmwareCloudSignInResolvers } from './resolvers'; diff --git a/plugins/auth-backend-module-vmware-cloud-provider/src/module.test.ts b/plugins/auth-backend-module-vmware-cloud-provider/src/module.test.ts new file mode 100644 index 0000000000..9bed931da1 --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/src/module.test.ts @@ -0,0 +1,90 @@ +/* + * 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. + */ +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; +import { decodeOAuthState } from '@backstage/plugin-auth-node'; +import request from 'supertest'; + +import { Config } from '../config'; +import { authModuleVmwareCloudProvider } from './module'; + +describe('authModuleVmwareCloudProvider', () => { + it('should start', async () => { + const backend = await startTestBackend({ + features: [ + import('@backstage/plugin-auth-backend'), + authModuleVmwareCloudProvider, + mockServices.rootConfig.factory({ + data: { + app: { + baseUrl: 'http://localhost:3000', + }, + auth: { + session: { secret: 'test' }, + providers: { + vmwareCloudServices: { + development: { + clientId: 'placeholderClientId', + organizationId: 'orgId', + }, + }, + }, + } as Config['auth'], + }, + }), + ], + }); + + const { server } = backend; + + const agent = request.agent(server); + + const res = await agent.get( + '/api/auth/vmwareCloudServices/start?env=development', + ); + + expect(res.status).toEqual(302); + + const nonceCookie = agent.jar.getCookie('vmwareCloudServices-nonce', { + domain: 'localhost', + path: '/api/auth/vmwareCloudServices/handler', + script: false, + secure: false, + }); + expect(nonceCookie).toBeDefined(); + + const startUrl = new URL(res.get('location')); + expect(startUrl.origin).toBe('https://console.cloud.vmware.com'); + expect(startUrl.pathname).toBe('/csp/gateway/discovery'); + expect(Object.fromEntries(startUrl.searchParams)).toEqual({ + response_type: 'code', + client_id: 'placeholderClientId', + redirect_uri: `http://localhost:${server.port()}/api/auth/vmwareCloudServices/handler/frame`, + code_challenge: expect.any(String), + state: expect.any(String), + scope: 'openid offline_access', + orgId: 'orgId', + code_challenge_method: 'S256', + }); + + expect(decodeOAuthState(startUrl.searchParams.get('state')!)).toEqual({ + env: 'development', + handle: expect.any(String), + nonce: decodeURIComponent(nonceCookie.value), + }); + + backend.stop(); + }); +}); diff --git a/plugins/auth-backend-module-vmware-cloud-provider/src/module.ts b/plugins/auth-backend-module-vmware-cloud-provider/src/module.ts new file mode 100644 index 0000000000..5ef79654a3 --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/src/module.ts @@ -0,0 +1,51 @@ +/* + * 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. + */ +import { createBackendModule } from '@backstage/backend-plugin-api'; +import { + authProvidersExtensionPoint, + commonSignInResolvers, + createOAuthProviderFactory, +} from '@backstage/plugin-auth-node'; + +import { vmwareCloudAuthenticator } from './authenticator'; +import { vmwareCloudSignInResolvers } from './resolvers'; + +/** + * VMware Cloud Provider backend module for the auth plugin + * + * @public + */ +export const authModuleVmwareCloudProvider = createBackendModule({ + pluginId: 'auth', + moduleId: 'vmware-cloud-provider', + register(reg) { + reg.registerInit({ + deps: { providers: authProvidersExtensionPoint }, + async init({ providers }) { + providers.registerProvider({ + providerId: 'vmwareCloudServices', + factory: createOAuthProviderFactory({ + authenticator: vmwareCloudAuthenticator, + signInResolverFactories: { + ...vmwareCloudSignInResolvers, + ...commonSignInResolvers, + }, + }), + }); + }, + }); + }, +}); diff --git a/plugins/auth-backend-module-vmware-cloud-provider/src/resolvers.test.ts b/plugins/auth-backend-module-vmware-cloud-provider/src/resolvers.test.ts new file mode 100644 index 0000000000..250fd430c7 --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/src/resolvers.test.ts @@ -0,0 +1,90 @@ +/* + * 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. + */ +import { NotFoundError } from '@backstage/errors'; +import { + AuthResolverContext, + OAuthAuthenticatorResult, + PassportProfile, + SignInInfo, + SignInResolver, +} from '@backstage/plugin-auth-node'; + +import { vmwareCloudSignInResolvers } from './resolvers'; + +describe('vmwareCloudResolver', () => { + let resolverContext: jest.Mocked; + let signInInfo: SignInInfo>; + let signInResolver: SignInResolver>; + + beforeEach(() => { + resolverContext = { + issueToken: jest.fn().mockResolvedValue({ + token: 'defaultBackstageToken', + }), + findCatalogUser: jest.fn(), + signInWithCatalogUser: jest.fn().mockResolvedValue({ + token: 'backstageToken', + }), + }; + + signInInfo = { + result: {} as any, // Resolver doesn't care about the result object + profile: { + displayName: 'TestName', + email: 'user@example.com', + }, + }; + + signInResolver = + vmwareCloudSignInResolvers.profileEmailMatchingUserEntityEmail(); + }); + + it('looks up backstage identity by email', async () => { + const backstageIdentity = await signInResolver(signInInfo, resolverContext); + + expect(backstageIdentity.token).toBe('backstageToken'); + expect(resolverContext.signInWithCatalogUser).toHaveBeenCalledWith({ + filter: { + 'spec.profile.email': 'user@example.com', + }, + }); + }); + + it('returns "fake" backstage identity when no entity matches', async () => { + resolverContext.signInWithCatalogUser.mockRejectedValue( + new NotFoundError('User not found'), + ); + + const backstageIdentity = await signInResolver(signInInfo, resolverContext); + + expect(backstageIdentity.token).toBe('defaultBackstageToken'); + expect(resolverContext.issueToken).toHaveBeenCalledWith({ + claims: { + sub: 'user:default/user@example.com', + ent: ['user:default/user@example.com'], + }, + }); + }); + + it('fails when resolver context throws other error', () => { + const error = new Error('bizarre'); + resolverContext.signInWithCatalogUser.mockRejectedValue(error); + + return expect(signInResolver(signInInfo, resolverContext)).rejects.toThrow( + error, + ); + }); +}); diff --git a/plugins/auth-backend-module-vmware-cloud-provider/src/resolvers.ts b/plugins/auth-backend-module-vmware-cloud-provider/src/resolvers.ts new file mode 100644 index 0000000000..2b3a78842b --- /dev/null +++ b/plugins/auth-backend-module-vmware-cloud-provider/src/resolvers.ts @@ -0,0 +1,75 @@ +/* + * 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. + */ +import { stringifyEntityRef } from '@backstage/catalog-model'; +import { + createSignInResolverFactory, + OAuthAuthenticatorResult, + PassportProfile, + SignInInfo, +} from '@backstage/plugin-auth-node'; + +/** + * Available sign-in resolvers for the VMware Cloud auth provider. + * + * @public + */ +export namespace vmwareCloudSignInResolvers { + /** + * Looks up the user by matching their profile email to the entity's profile email. + * If that fails, sign in the user without associating with a catalog user. + */ + export const profileEmailMatchingUserEntityEmail = + createSignInResolverFactory({ + create() { + return async ( + info: SignInInfo>, + ctx, + ) => { + const email = info.profile.email; + + if (!email) { + throw new Error( + 'VMware login failed, user profile does not contain an email', + ); + } + + const userEntityRef = stringifyEntityRef({ + kind: 'User', + name: email, + }); + + try { + // we await here so that signInWithCatalogUser throws in the current `try` + return await ctx.signInWithCatalogUser({ + filter: { + 'spec.profile.email': email, + }, + }); + } catch (e) { + if (e.name !== 'NotFoundError') { + throw e; + } + return ctx.issueToken({ + claims: { + sub: userEntityRef, + ent: [userEntityRef], + }, + }); + } + }; + }, + }); +} diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index b3c45ca591..2d89150d33 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,79 @@ # @backstage/plugin-auth-backend +## 0.20.1-next.2 + +### Patch Changes + +- 783797a: fix static token issuer not being able to initialize +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.0-next.1 + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-backend-module-atlassian-provider@0.1.0-next.2 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.5-next.2 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.5-next.2 + - @backstage/plugin-auth-backend-module-okta-provider@0.0.1-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.2-next.2 + - @backstage/plugin-auth-backend-module-google-provider@0.1.5-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-backend-module-github-provider@0.1.5-next.2 + +## 0.20.1-next.1 + +### Patch Changes + +- 7ac25759a5: `oauth2-proxy` auth implementation has been moved to `@backstage/plugin-auth-backend-module-oauth2-proxy-provider` +- bcbbf8e042: Updated dependency `@google-cloud/firestore` to `^7.0.0`. +- Updated dependencies + - @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.1.0-next.0 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/plugin-auth-backend-module-atlassian-provider@0.1.0-next.1 + - @backstage/plugin-auth-backend-module-github-provider@0.1.5-next.1 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.5-next.1 + - @backstage/plugin-auth-backend-module-google-provider@0.1.5-next.1 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.5-next.1 + - @backstage/plugin-auth-backend-module-okta-provider@0.0.1-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.2-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.20.1-next.0 + +### Patch Changes + +- 2a5891e816: Migrate the atlassian auth provider to be implemented using the new `@backstage/plugin-auth-backend-module-atlassian-provider` module +- e1c189b524: The Okta provider implementation is moved to the new module +- Updated dependencies + - @backstage/plugin-auth-backend-module-atlassian-provider@0.1.0-next.0 + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-backend-module-okta-provider@0.0.1-next.0 + - @backstage/plugin-auth-backend-module-github-provider@0.1.5-next.0 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.5-next.0 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.5-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/plugin-auth-backend-module-google-provider@0.1.5-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.2-next.0 + ## 0.20.0 ### Minor Changes diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 6372c2ee60..c269a09d2c 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -3,8 +3,6 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts -/// - import { AuthProviderConfig as AuthProviderConfig_2 } from '@backstage/plugin-auth-node'; import { AuthProviderFactory as AuthProviderFactory_2 } from '@backstage/plugin-auth-node'; import { AuthProviderRouteHandlers as AuthProviderRouteHandlers_2 } from '@backstage/plugin-auth-node'; @@ -23,8 +21,8 @@ import { Entity } from '@backstage/catalog-model'; import express from 'express'; import { GcpIapResult as GcpIapResult_2 } from '@backstage/plugin-auth-backend-module-gcp-iap-provider'; import { GcpIapTokenInfo as GcpIapTokenInfo_2 } from '@backstage/plugin-auth-backend-module-gcp-iap-provider'; -import { IncomingHttpHeaders } from 'http'; import { LoggerService } from '@backstage/backend-plugin-api'; +import { OAuth2ProxyResult as OAuth2ProxyResult_2 } from '@backstage/plugin-auth-backend-module-oauth2-proxy-provider'; import { OAuthEnvironmentHandler as OAuthEnvironmentHandler_2 } from '@backstage/plugin-auth-node'; import { OAuthState as OAuthState_2 } from '@backstage/plugin-auth-node'; import { PluginDatabaseManager } from '@backstage/backend-common'; @@ -228,13 +226,8 @@ export type GithubOAuthResult = { refreshToken?: string; }; -// @public -export type OAuth2ProxyResult = { - fullProfile: JWTPayload; - accessToken: string; - headers: IncomingHttpHeaders; - getHeader(name: string): string | undefined; -}; +// @public @deprecated (undocumented) +export type OAuth2ProxyResult = OAuth2ProxyResult_2; // @public @deprecated (undocumented) export class OAuthAdapter implements AuthProviderRouteHandlers { @@ -560,9 +553,9 @@ export const providers: Readonly<{ }>; oauth2Proxy: Readonly<{ create: (options: { - authHandler?: AuthHandler> | undefined; + authHandler?: AuthHandler | undefined; signIn: { - resolver: SignInResolver>; + resolver: SignInResolver; }; }) => AuthProviderFactory_2; resolvers: never; @@ -599,8 +592,6 @@ export const providers: Readonly<{ | undefined, ) => AuthProviderFactory_2; resolvers: Readonly<{ - emailLocalPartMatchingUserEntityName: () => SignInResolver; - emailMatchingUserEntityProfileEmail: () => SignInResolver; emailMatchingUserEntityAnnotation(): SignInResolver; }>; }>; diff --git a/plugins/auth-backend/config.d.ts b/plugins/auth-backend/config.d.ts index c13c46664c..34139593d3 100644 --- a/plugins/auth-backend/config.d.ts +++ b/plugins/auth-backend/config.d.ts @@ -135,21 +135,6 @@ export interface Config { acceptedClockSkewMs?: number; }; /** @visibility frontend */ - okta?: { - [authEnv: string]: { - clientId: string; - /** - * @visibility secret - */ - clientSecret: string; - audience: string; - authServerId?: string; - idp?: string; - callbackUrl?: string; - additionalScopes?: string; - }; - }; - /** @visibility frontend */ oauth2?: { [authEnv: string]: { clientId: string; diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 5ef46964ea..af5bd43f44 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-auth-backend", "description": "A Backstage backend plugin that handles authentication", - "version": "0.20.0", + "version": "0.20.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,16 +38,18 @@ "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/plugin-auth-backend-module-atlassian-provider": "workspace:^", "@backstage/plugin-auth-backend-module-gcp-iap-provider": "workspace:^", "@backstage/plugin-auth-backend-module-github-provider": "workspace:^", "@backstage/plugin-auth-backend-module-gitlab-provider": "workspace:^", "@backstage/plugin-auth-backend-module-google-provider": "workspace:^", "@backstage/plugin-auth-backend-module-oauth2-provider": "workspace:^", + "@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "workspace:^", + "@backstage/plugin-auth-backend-module-okta-provider": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", "@backstage/types": "workspace:^", - "@davidzemon/passport-okta-oauth": "^0.0.5", - "@google-cloud/firestore": "^6.0.0", + "@google-cloud/firestore": "^7.0.0", "@types/express": "^4.17.6", "@types/passport": "^1.0.3", "compression": "^1.7.4", @@ -69,7 +71,7 @@ "node-cache": "^5.1.2", "node-fetch": "^2.6.7", "openid-client": "^5.2.1", - "passport": "^0.6.0", + "passport": "^0.7.0", "passport-auth0": "^1.4.3", "passport-bitbucket-oauth2": "^0.1.2", "passport-github2": "^0.1.12", diff --git a/plugins/auth-backend/src/identity/KeyStores.ts b/plugins/auth-backend/src/identity/KeyStores.ts index 7242530c57..16f25817a9 100644 --- a/plugins/auth-backend/src/identity/KeyStores.ts +++ b/plugins/auth-backend/src/identity/KeyStores.ts @@ -76,7 +76,7 @@ export class KeyStores { } if (provider === 'static') { - await StaticKeyStore.fromConfig(config); + return await StaticKeyStore.fromConfig(config); } throw new Error(`Unknown KeyStore provider: ${provider}`); diff --git a/plugins/auth-backend/src/providers/atlassian/provider.test.ts b/plugins/auth-backend/src/providers/atlassian/provider.test.ts deleted file mode 100644 index 1fb987d3b0..0000000000 --- a/plugins/auth-backend/src/providers/atlassian/provider.test.ts +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AtlassianAuthProvider } from './provider'; -import * as helpers from '../../lib/passport/PassportStrategyHelper'; -import { OAuthResult } from '../../lib/oauth'; -import { PassportProfile } from '../../lib/passport/types'; -import { AuthResolverContext } from '../types'; - -jest.mock('../../lib/passport/PassportStrategyHelper', () => { - return { - executeFrameHandlerStrategy: jest.fn(), - executeRefreshTokenStrategy: jest.fn(), - executeFetchUserProfileStrategy: jest.fn(), - }; -}); - -const mockFrameHandler = jest.spyOn( - helpers, - 'executeFrameHandlerStrategy', -) as unknown as jest.MockedFunction<() => Promise<{ result: OAuthResult }>>; - -describe('createAtlassianProvider', () => { - const provider = new AtlassianAuthProvider({ - resolverContext: {} as AuthResolverContext, - authHandler: async ({ fullProfile }) => ({ - profile: { - email: fullProfile.emails![0]!.value, - displayName: fullProfile.displayName, - picture: 'http://google.com/lols', - }, - }), - clientId: 'mock', - clientSecret: 'mock', - callbackUrl: 'mock', - scopes: 'scope', - }); - - it('should auth', async () => { - mockFrameHandler.mockResolvedValueOnce({ - result: { - fullProfile: { - photos: [ - { - value: - 'https://a1cf74336522e87f135f-2f21ace9a6cf0052456644b80fa06d4f.ssl.cf2.rackcdn.com/images/characters_opt/p-mystic-river-sean-penn.jpg', - }, - ], - emails: [{ value: 'conrad@example.com' }], - displayName: 'Conrad', - id: 'conrad', - provider: 'google', - }, - params: { - id_token: 'idToken', - scope: 'scope', - expires_in: 123, - }, - accessToken: 'accessToken', - refreshToken: 'wacka', - }, - }); - const result = await provider.handler({} as any); - expect(result).toEqual({ - response: { - providerInfo: { - accessToken: 'accessToken', - expiresInSeconds: 123, - idToken: 'idToken', - scope: 'scope', - }, - profile: { - email: 'conrad@example.com', - displayName: 'Conrad', - picture: 'http://google.com/lols', - }, - }, - refreshToken: 'wacka', - }); - }); - - it('should forward a new refresh token on refresh', async () => { - const mockRefreshToken = jest.spyOn( - helpers, - 'executeRefreshTokenStrategy', - ) as unknown as jest.MockedFunction<() => Promise<{}>>; - - mockRefreshToken.mockResolvedValueOnce({ - accessToken: 'a.b.c', - refreshToken: 'dont-forget-to-send-refresh', - params: { - id_token: 'my-id', - scope: 'read_user', - }, - }); - - const mockUserProfile = jest.spyOn( - helpers, - 'executeFetchUserProfileStrategy', - ) as unknown as jest.MockedFunction<() => Promise>; - - mockUserProfile.mockResolvedValueOnce({ - id: 'uid-my-id', - username: 'mockuser', - provider: 'atlassian', - displayName: 'Mocked User', - emails: [ - { - value: 'mockuser@gmail.com', - }, - ], - }); - - const result = await provider.refresh({} as any); - - expect(result).toEqual({ - response: { - profile: { - displayName: 'Mocked User', - email: 'mockuser@gmail.com', - picture: 'http://google.com/lols', - }, - providerInfo: { - accessToken: 'a.b.c', - idToken: 'my-id', - scope: 'read_user', - }, - }, - refreshToken: 'dont-forget-to-send-refresh', - }); - }); -}); diff --git a/plugins/auth-backend/src/providers/atlassian/provider.ts b/plugins/auth-backend/src/providers/atlassian/provider.ts index e02d899fb1..a142d1de90 100644 --- a/plugins/auth-backend/src/providers/atlassian/provider.ts +++ b/plugins/auth-backend/src/providers/atlassian/provider.ts @@ -14,156 +14,18 @@ * limitations under the License. */ -import AtlassianStrategy from './strategy'; -import { - encodeState, - OAuthAdapter, - OAuthEnvironmentHandler, - OAuthHandlers, - OAuthProviderOptions, - OAuthRefreshRequest, - OAuthResponse, - OAuthResult, - OAuthStartRequest, -} from '../../lib/oauth'; -import passport from 'passport'; -import { - executeFetchUserProfileStrategy, - executeFrameHandlerStrategy, - executeRedirectStrategy, - executeRefreshTokenStrategy, - makeProfileInfo, - PassportDoneCallback, -} from '../../lib/passport'; -import { - AuthHandler, - AuthResolverContext, - OAuthStartResponse, - SignInResolver, -} from '../types'; -import express from 'express'; +import { SignInResolver, AuthHandler } from '../types'; +import { OAuthResult } from '../../lib/oauth'; import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; - -/** @public */ -export type AtlassianAuthProviderOptions = OAuthProviderOptions & { - scopes: string; - signInResolver?: SignInResolver; - authHandler: AuthHandler; - resolverContext: AuthResolverContext; -}; - -export const atlassianDefaultAuthHandler: AuthHandler = async ({ - fullProfile, - params, -}) => ({ - profile: makeProfileInfo(fullProfile, params.id_token), -}); - -export class AtlassianAuthProvider implements OAuthHandlers { - private readonly _strategy: AtlassianStrategy; - private readonly signInResolver?: SignInResolver; - private readonly authHandler: AuthHandler; - private readonly resolverContext: AuthResolverContext; - - constructor(options: AtlassianAuthProviderOptions) { - this.resolverContext = options.resolverContext; - this.authHandler = options.authHandler; - this.signInResolver = options.signInResolver; - - this._strategy = new AtlassianStrategy( - { - clientID: options.clientId, - clientSecret: options.clientSecret, - callbackURL: options.callbackUrl, - scope: options.scopes, - }, - ( - accessToken: any, - refreshToken: any, - params: any, - fullProfile: passport.Profile, - done: PassportDoneCallback, - ) => { - done(undefined, { - fullProfile, - accessToken, - refreshToken, - params, - }); - }, - ); - } - - async start(req: OAuthStartRequest): Promise { - return await executeRedirectStrategy(req, this._strategy, { - state: encodeState(req.state), - }); - } - - async handler(req: express.Request) { - const { result } = await executeFrameHandlerStrategy( - req, - this._strategy, - ); - - return { - response: await this.handleResult(result), - refreshToken: result.refreshToken, - }; - } - - private async handleResult(result: OAuthResult): Promise { - const { profile } = await this.authHandler(result, this.resolverContext); - - const response: OAuthResponse = { - providerInfo: { - idToken: result.params.id_token, - accessToken: result.accessToken, - scope: result.params.scope, - expiresInSeconds: result.params.expires_in, - }, - profile, - }; - - if (this.signInResolver) { - response.backstageIdentity = await this.signInResolver( - { - result, - profile, - }, - this.resolverContext, - ); - } - - return response; - } - - async refresh(req: OAuthRefreshRequest) { - const { accessToken, params, refreshToken } = - await executeRefreshTokenStrategy( - this._strategy, - req.refreshToken, - req.scope, - ); - - const fullProfile = await executeFetchUserProfileStrategy( - this._strategy, - accessToken, - ); - - return { - response: await this.handleResult({ - fullProfile, - params, - accessToken, - }), - refreshToken, - }; - } -} +import { createOAuthProviderFactory } from '@backstage/plugin-auth-node'; +import { + adaptLegacyOAuthHandler, + adaptLegacyOAuthSignInResolver, +} from '../../lib/legacy'; +import { atlassianAuthenticator } from '@backstage/plugin-auth-backend-module-atlassian-provider'; /** - * Auth provider integration for atlassian auth + * Auth provider integration for Atlassian auth * * @public */ @@ -182,33 +44,10 @@ export const atlassian = createAuthProviderIntegration({ resolver: SignInResolver; }; }) { - return ({ providerId, globalConfig, config, resolverContext }) => - OAuthEnvironmentHandler.mapConfig(config, envConfig => { - const clientId = envConfig.getString('clientId'); - const clientSecret = envConfig.getString('clientSecret'); - const scopes = envConfig.getString('scopes'); - const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); - const callbackUrl = - customCallbackUrl || - `${globalConfig.baseUrl}/${providerId}/handler/frame`; - - const authHandler: AuthHandler = - options?.authHandler ?? atlassianDefaultAuthHandler; - - const provider = new AtlassianAuthProvider({ - clientId, - clientSecret, - scopes, - callbackUrl, - authHandler, - signInResolver: options?.signIn?.resolver, - resolverContext, - }); - - return OAuthAdapter.fromConfig(globalConfig, provider, { - providerId, - callbackUrl, - }); - }); + return createOAuthProviderFactory({ + authenticator: atlassianAuthenticator, + profileTransform: adaptLegacyOAuthHandler(options?.authHandler), + signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver), + }); }, }); diff --git a/plugins/auth-backend/src/providers/oauth2-proxy/index.ts b/plugins/auth-backend/src/providers/oauth2-proxy/index.ts index d3004f31e4..2e4e7d016f 100644 --- a/plugins/auth-backend/src/providers/oauth2-proxy/index.ts +++ b/plugins/auth-backend/src/providers/oauth2-proxy/index.ts @@ -15,4 +15,10 @@ */ export { oauth2Proxy } from './provider'; -export type { OAuth2ProxyResult } from './provider'; +import { OAuth2ProxyResult as _OAuth2ProxyResult } from '@backstage/plugin-auth-backend-module-oauth2-proxy-provider'; + +/** + * @public + * @deprecated import from `@backstage/plugin-auth-backend-module-oauth2-proxy-provider` instead + */ +export type OAuth2ProxyResult = _OAuth2ProxyResult; diff --git a/plugins/auth-backend/src/providers/oauth2-proxy/provider.test.ts b/plugins/auth-backend/src/providers/oauth2-proxy/provider.test.ts deleted file mode 100644 index f585d4831f..0000000000 --- a/plugins/auth-backend/src/providers/oauth2-proxy/provider.test.ts +++ /dev/null @@ -1,205 +0,0 @@ -/* - * 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. - */ - -jest.mock('jose', () => ({ - decodeJwt: jest.fn(), -})); -jest.mock('@backstage/catalog-client'); - -import { AuthenticationError } from '@backstage/errors'; -import express from 'express'; -import * as jose from 'jose'; -import { LoggerService } from '@backstage/backend-plugin-api'; -import { AuthHandler, AuthResolverContext, SignInResolver } from '../types'; -import { - oauth2Proxy, - Oauth2ProxyAuthProvider, - OAuth2ProxyResult, - OAUTH2_PROXY_JWT_HEADER, -} from './provider'; - -describe('Oauth2ProxyAuthProvider', () => { - const mockToken = - 'eyblob.eyJzdWIiOiJ1c2VyOmRlZmF1bHQvamltbXltYXJrdW0iLCJlbnQiOlsidXNlcjpkZWZhdWx0L2ppbW15bWFya3VtIl19.eyblob'; - - let provider: Oauth2ProxyAuthProvider; - let logger: jest.Mocked; - let signInResolver: jest.MockedFunction< - SignInResolver> - >; - let authHandler: jest.MockedFunction>>; - let mockResponse: jest.Mocked; - let mockRequest: jest.Mocked; - let mockJwtDecode: jest.MockedFunction; - - beforeEach(() => { - jest.resetAllMocks(); - - mockJwtDecode = jose.decodeJwt as jest.MockedFunction< - typeof jose.decodeJwt - >; - authHandler = jest.fn(); - signInResolver = jest.fn(); - logger = { error: jest.fn() } as unknown as jest.Mocked; - - mockResponse = { - status: jest.fn(), - end: jest.fn(), - json: jest.fn(), - } as unknown as jest.Mocked; - - mockRequest = { - body: {}, - header: jest.fn(), - headers: { - 'x-mock': 'mock', - }, - } as unknown as jest.Mocked; - - provider = new Oauth2ProxyAuthProvider({ - authHandler, - signInResolver, - resolverContext: { - _: 'resolver-context', - } as unknown as AuthResolverContext, - }); - }); - - describe('frameHandler()', () => { - it('should do nothing and return undefined', async () => { - const result = await provider.frameHandler(); - - expect(result).toBeUndefined(); - }); - }); - - describe('start()', () => { - it('should do nothing and return undefined', async () => { - const result = await provider.start(); - - expect(result).toBeUndefined(); - }); - }); - - describe('refresh()', () => { - it('should throw an error when auth header is missing', async () => { - mockRequest.header.mockReturnValue(undefined); - - await expect(provider.refresh(mockRequest, mockResponse)).rejects.toThrow( - AuthenticationError, - ); - }); - - it('should throw an error if the bearer token is invalid', async () => { - mockRequest.header.mockReturnValue('Basic asdf='); - - await expect(provider.refresh(mockRequest, mockResponse)).rejects.toThrow( - AuthenticationError, - ); - }); - - it('should return if auth header is set and valid', async () => { - mockRequest.header.mockReturnValue(`Bearer token`); - authHandler.mockResolvedValue({ - profile: {}, - }); - signInResolver.mockResolvedValue({ - token: mockToken, - }); - - await provider.refresh(mockRequest, mockResponse); - - expect(mockRequest.header).toHaveBeenCalledWith(OAUTH2_PROXY_JWT_HEADER); - expect(mockJwtDecode).toHaveBeenCalledWith('token'); - expect(mockResponse.json).toHaveBeenCalled(); - }); - - it('should load profile from authHandler and backstage identity from signInResolver', async () => { - const decodedToken = { - oid: 'oid', - name: 'name', - upn: 'john.doe@example.com', - }; - const profile = { displayName: 'some value' }; - mockRequest.header.mockReturnValue(`Bearer token`); - signInResolver.mockResolvedValue({ - token: mockToken, - }); - authHandler.mockResolvedValue({ profile: profile }); - mockJwtDecode.mockReturnValue(decodedToken as any); - - await provider.refresh(mockRequest, mockResponse); - - expect(signInResolver).toHaveBeenCalledWith( - { - profile: profile, - result: { - accessToken: 'token', - fullProfile: decodedToken, - getHeader: expect.any(Function), - headers: { - 'x-mock': 'mock', - }, - }, - }, - { _: 'resolver-context' }, - ); - expect(mockResponse.json).toHaveBeenCalledWith({ - backstageIdentity: { - identity: { - type: 'user', - userEntityRef: 'user:default/jimmymarkum', - ownershipEntityRefs: ['user:default/jimmymarkum'], - }, - token: mockToken, - }, - profile: { displayName: 'some value' }, - providerInfo: { - accessToken: 'token', - }, - }); - }); - }); - - describe('oauth2Proxy.create()', () => { - beforeEach(() => { - mockRequest.header.mockReturnValue(`Bearer token`); - authHandler.mockResolvedValue({ - profile: {}, - }); - signInResolver.mockResolvedValue({ - token: mockToken, - }); - }); - - it('should create a valid provider', async () => { - const factory = oauth2Proxy.create({ - authHandler, - signIn: { resolver: signInResolver }, - }); - const handler = factory({ - logger, - catalogApi: {}, - tokenIssuer: {}, - } as any); - await handler.refresh!(mockRequest, mockResponse); - - expect(mockRequest.header).toHaveBeenCalledWith(OAUTH2_PROXY_JWT_HEADER); - expect(mockJwtDecode).toHaveBeenCalledWith('token'); - expect(mockResponse.json).toHaveBeenCalled(); - }); - }); -}); diff --git a/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts b/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts index 3ac7d09000..5d75167e84 100644 --- a/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts +++ b/plugins/auth-backend/src/providers/oauth2-proxy/provider.ts @@ -14,164 +14,13 @@ * limitations under the License. */ -import express from 'express'; -import { AuthenticationError } from '@backstage/errors'; -import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; -import { - AuthHandler, - SignInResolver, - AuthProviderRouteHandlers, - AuthResponse, - AuthResolverContext, - AuthHandlerResult, -} from '../types'; -import { decodeJwt } from 'jose'; -import { prepareBackstageIdentityResponse } from '../prepareBackstageIdentityResponse'; +import { createProxyAuthProviderFactory } from '@backstage/plugin-auth-node'; +import { AuthHandler, SignInResolver } from '../types'; import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; -import { IncomingHttpHeaders } from 'http'; - -// NOTE: This may come in handy if you're doing work on this provider: -// -// plugins/auth-backend/examples/docker-compose.oauth2-proxy.yaml -// - -export const OAUTH2_PROXY_JWT_HEADER = 'X-OAUTH2-PROXY-ID-TOKEN'; - -/** - * JWT header extraction result, containing the raw value and the parsed JWT - * payload. - * - * @public - */ -export type OAuth2ProxyResult = { - /** - * The parsed payload of the `accessToken`. The token is only parsed, not verified. - * - * @deprecated Access through the `headers` instead. This will be removed in a future release. - */ - fullProfile: JWTPayload; - - /** - * The token received via the X-OAUTH2-PROXY-ID-TOKEN header. Will be an empty string - * if the header is not set. Note the this is typically an OpenID Connect token. - * - * @deprecated Access through the `headers` instead. This will be removed in a future release. - */ - accessToken: string; - - /** - * The headers of the incoming request from the OAuth2 proxy. This will include - * both the headers set by the client as well as the ones added by the OAuth2 proxy. - * You should only trust the headers that are injected by the OAuth2 proxy. - * - * Useful headers to use to complete the sign-in are for example `x-forwarded-user` - * and `x-forwarded-email`. See the OAuth2 proxy documentation for more information - * about the available headers and how to enable them. In particular it is possible - * to forward access and identity tokens, which can be user for additional verification - * and lookups. - */ - headers: IncomingHttpHeaders; - - /** - * Provides convenient access to the request headers. - * - * This call is simply forwarded to `req.get(name)`. - */ - getHeader(name: string): string | undefined; -}; - -interface Options { - resolverContext: AuthResolverContext; - signInResolver: SignInResolver>; - authHandler: AuthHandler>; -} - -export class Oauth2ProxyAuthProvider - implements AuthProviderRouteHandlers -{ - private readonly resolverContext: AuthResolverContext; - private readonly signInResolver: SignInResolver< - OAuth2ProxyResult - >; - private readonly authHandler: AuthHandler>; - - constructor(options: Options) { - this.resolverContext = options.resolverContext; - this.signInResolver = options.signInResolver; - this.authHandler = options.authHandler; - } - - frameHandler(): Promise { - return Promise.resolve(undefined); - } - - async refresh(req: express.Request, res: express.Response): Promise { - try { - // TODO(Rugvip): This parsing was deprecated in 1.2 and should be removed in a future release. - const authHeader = req.header(OAUTH2_PROXY_JWT_HEADER); - const jwt = getBearerTokenFromAuthorizationHeader(authHeader); - const decodedJWT = jwt && (decodeJwt(jwt) as unknown as JWTPayload); - - const result = { - fullProfile: decodedJWT || ({} as JWTPayload), - accessToken: jwt || '', - headers: req.headers, - getHeader(name: string) { - if (name.toLocaleLowerCase('en-US') === 'set-cookie') { - throw new Error('Access Set-Cookie via the headers object instead'); - } - return req.get(name); - }, - }; - - const response = await this.handleResult(result); - res.json(response); - } catch (e) { - throw new AuthenticationError('Refresh failed', e); - } - } - - start(): Promise { - return Promise.resolve(undefined); - } - - private async handleResult( - result: OAuth2ProxyResult, - ): Promise> { - const { profile } = await this.authHandler(result, this.resolverContext); - - const backstageSignInResult = await this.signInResolver( - { - result, - profile, - }, - this.resolverContext, - ); - - return { - providerInfo: { - accessToken: result.accessToken, - }, - backstageIdentity: prepareBackstageIdentityResponse( - backstageSignInResult, - ), - profile, - }; - } -} - -async function defaultAuthHandler( - result: OAuth2ProxyResult, -): Promise { - return { - profile: { - email: result.getHeader('x-forwarded-email'), - displayName: - result.getHeader('x-forwarded-preferred-username') || - result.getHeader('x-forwarded-user'), - }, - }; -} +import { + type OAuth2ProxyResult, + oauth2ProxyAuthenticator, +} from '@backstage/plugin-auth-backend-module-oauth2-proxy-provider'; /** * Auth provider integration for oauth2-proxy auth @@ -179,7 +28,7 @@ async function defaultAuthHandler( * @public */ export const oauth2Proxy = createAuthProviderIntegration({ - create(options: { + create(options: { /** * Configure an auth handler to generate a profile for the user. * @@ -187,7 +36,7 @@ export const oauth2Proxy = createAuthProviderIntegration({ * header as the display name, falling back to `X-Forwarded-User`, and the value of * the `X-Forwarded-Email` header as the email address. */ - authHandler?: AuthHandler>; + authHandler?: AuthHandler; /** * Configure sign-in for this provider, without it the provider can not be used to sign users in. @@ -196,17 +45,13 @@ export const oauth2Proxy = createAuthProviderIntegration({ /** * Maps an auth result to a Backstage identity for the user. */ - resolver: SignInResolver>; + resolver: SignInResolver; }; }) { - return ({ resolverContext }) => { - const signInResolver = options.signIn.resolver; - const authHandler = options.authHandler; - return new Oauth2ProxyAuthProvider({ - resolverContext, - signInResolver, - authHandler: authHandler ?? defaultAuthHandler, - }); - }; + return createProxyAuthProviderFactory({ + authenticator: oauth2ProxyAuthenticator, + profileTransform: options?.authHandler, + signInResolver: options?.signIn?.resolver, + }); }, }); diff --git a/plugins/auth-backend/src/providers/okta/provider.test.ts b/plugins/auth-backend/src/providers/okta/provider.test.ts deleted file mode 100644 index 588b00be02..0000000000 --- a/plugins/auth-backend/src/providers/okta/provider.test.ts +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { OktaAuthProvider } from './provider'; -import * as helpers from '../../lib/passport/PassportStrategyHelper'; -import { OAuthResult } from '../../lib/oauth'; -import { AuthResolverContext, OAuthStartResponse } from '../types'; - -jest.mock('../../lib/passport/PassportStrategyHelper', () => { - return { - executeFrameHandlerStrategy: jest.fn(), - executeRefreshTokenStrategy: jest.fn(), - executeFetchUserProfileStrategy: jest.fn(), - executeRedirectStrategy: jest.fn(), - }; -}); - -const mockFrameHandler = jest.spyOn( - helpers, - 'executeFrameHandlerStrategy', -) as unknown as jest.MockedFunction< - () => Promise<{ result: OAuthResult; privateInfo: any }> ->; - -const mockRedirectStrategy = jest.spyOn( - helpers, - 'executeRedirectStrategy', -) as unknown as jest.MockedFunction<() => Promise>; - -describe('createOktaProvider', () => { - it('should auth', async () => { - const provider = new OktaAuthProvider({ - resolverContext: {} as AuthResolverContext, - authHandler: async ({ fullProfile }) => ({ - profile: { - email: fullProfile.emails![0]!.value, - displayName: fullProfile.displayName, - }, - }), - audience: 'http://example.com', - clientId: 'mock', - clientSecret: 'mock', - callbackUrl: 'mock', - }); - - mockFrameHandler.mockResolvedValueOnce({ - result: { - fullProfile: { - emails: [ - { - type: 'work', - value: 'conrad@example.com', - }, - ], - displayName: 'Conrad', - name: { - familyName: 'Ribas', - givenName: 'Francisco', - }, - id: 'conrad', - provider: 'okta', - photos: [ - { - value: 'some-data', - }, - ], - }, - params: { - id_token: 'idToken', - scope: 'scope', - expires_in: 123, - }, - accessToken: 'accessToken', - }, - privateInfo: { - refreshToken: 'wacka', - }, - }); - const { response } = await provider.handler({} as any); - expect(response).toEqual({ - providerInfo: { - accessToken: 'accessToken', - expiresInSeconds: 123, - idToken: 'idToken', - scope: 'scope', - }, - profile: { - email: 'conrad@example.com', - displayName: 'Conrad', - }, - }); - }); - - it('should pass a custom scope to start and refresh requests', async () => { - const additionalScopes = 'groups'; - const reqScope = 'openid profile email offline_access'; - const combinedScope = `${reqScope} ${additionalScopes}`; - const provider = new OktaAuthProvider({ - resolverContext: {} as AuthResolverContext, - authHandler: async ({ fullProfile }) => ({ - profile: { - email: fullProfile.emails![0]!.value, - displayName: fullProfile.displayName, - }, - }), - audience: 'http://example.com', - clientId: 'mock', - clientSecret: 'mock', - callbackUrl: 'mock', - additionalScopes, - }); - - mockRedirectStrategy.mockResolvedValueOnce({ - url: 'http://example.com/', - }); - - const req: any = { - state: { - nonce: 'nonce', - env: 'development', - }, - scope: reqScope, - }; - - await provider.start(req); - const mockCallScope = (mockRedirectStrategy.mock.calls[0] as any)?.[2] - ?.scope; - expect(mockCallScope).toBe(combinedScope); - }); -}); diff --git a/plugins/auth-backend/src/providers/okta/provider.ts b/plugins/auth-backend/src/providers/okta/provider.ts index 6b27fbb612..4c8d5c37d7 100644 --- a/plugins/auth-backend/src/providers/okta/provider.ts +++ b/plugins/auth-backend/src/providers/okta/provider.ts @@ -14,195 +14,16 @@ * limitations under the License. */ -import express from 'express'; -import { - OAuthAdapter, - OAuthProviderOptions, - OAuthHandlers, - OAuthResponse, - OAuthEnvironmentHandler, - OAuthStartRequest, - encodeState, - OAuthRefreshRequest, - OAuthResult, -} from '../../lib/oauth'; -import { Strategy as OktaStrategy } from '@davidzemon/passport-okta-oauth'; -import passport from 'passport'; -import { - executeFrameHandlerStrategy, - executeRedirectStrategy, - executeRefreshTokenStrategy, - makeProfileInfo, - executeFetchUserProfileStrategy, - PassportDoneCallback, -} from '../../lib/passport'; -import { - AuthHandler, - OAuthStartResponse, - SignInResolver, - AuthResolverContext, -} from '../types'; +import { AuthHandler, SignInResolver } from '../types'; +import { OAuthResult } from '../../lib/oauth'; + import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; +import { createOAuthProviderFactory } from '@backstage/plugin-auth-node'; import { - commonByEmailLocalPartResolver, - commonByEmailResolver, -} from '../resolvers'; -import { StateStore } from 'passport-oauth2'; - -type PrivateInfo = { - refreshToken: string; -}; - -export type OktaAuthProviderOptions = OAuthProviderOptions & { - audience: string; - authServerId?: string; - idp?: string; - signInResolver?: SignInResolver; - authHandler: AuthHandler; - resolverContext: AuthResolverContext; - additionalScopes?: string; -}; - -export class OktaAuthProvider implements OAuthHandlers { - private readonly strategy: any; - private readonly signInResolver?: SignInResolver; - private readonly authHandler: AuthHandler; - private readonly resolverContext: AuthResolverContext; - private readonly additionalScopes: string; - - /** - * Due to passport-okta-oauth forcing options.state = true, - * passport-oauth2 requires express-session to be installed - * so that the 'state' parameter of the oauth2 flow can be stored. - * This implementation of StateStore matches the NullStore found within - * passport-oauth2, which is the StateStore implementation used when options.state = false, - * allowing us to avoid using express-session in order to integrate with Okta. - */ - private store: StateStore = { - store(_req: express.Request, cb: any) { - cb(null, null); - }, - verify(_req: express.Request, _state: string, cb: any) { - cb(null, true); - }, - }; - - constructor(options: OktaAuthProviderOptions) { - this.signInResolver = options.signInResolver; - this.authHandler = options.authHandler; - this.resolverContext = options.resolverContext; - this.additionalScopes = options.additionalScopes || ''; - - this.strategy = new OktaStrategy( - { - clientID: options.clientId, - clientSecret: options.clientSecret, - callbackURL: options.callbackUrl, - audience: options.audience, - authServerID: options.authServerId, - idp: options.idp, - passReqToCallback: false, - store: this.store, - response_type: 'code', - }, - ( - accessToken: any, - refreshToken: any, - params: any, - fullProfile: passport.Profile, - done: PassportDoneCallback, - ) => { - done( - undefined, - { - accessToken, - refreshToken, - params, - fullProfile, - }, - { - refreshToken, - }, - ); - }, - ); - } - - private combineScopeStrings(scopesA: string, scopesB: string) { - const scopesAArray = scopesA.split(' '); - const scopesBArray = scopesB.split(' '); - const combinedScopes = new Set([...scopesAArray, ...scopesBArray]); - return Array.from(combinedScopes).join(' '); - } - - async start(req: OAuthStartRequest): Promise { - const scope = this.combineScopeStrings(req.scope, this.additionalScopes); - return await executeRedirectStrategy(req, this.strategy, { - accessType: 'offline', - prompt: 'consent', - scope: scope, - state: encodeState(req.state), - }); - } - - async handler(req: express.Request) { - const { result, privateInfo } = await executeFrameHandlerStrategy< - OAuthResult, - PrivateInfo - >(req, this.strategy); - - return { - response: await this.handleResult(result), - refreshToken: privateInfo.refreshToken, - }; - } - - async refresh(req: OAuthRefreshRequest) { - const scope = this.combineScopeStrings(req.scope, this.additionalScopes); - const { accessToken, refreshToken, params } = - await executeRefreshTokenStrategy(this.strategy, req.refreshToken, scope); - - const fullProfile = await executeFetchUserProfileStrategy( - this.strategy, - accessToken, - ); - - return { - response: await this.handleResult({ - fullProfile, - params, - accessToken, - }), - refreshToken, - }; - } - - private async handleResult(result: OAuthResult) { - const { profile } = await this.authHandler(result, this.resolverContext); - - const response: OAuthResponse = { - providerInfo: { - idToken: result.params.id_token, - accessToken: result.accessToken, - scope: result.params.scope, - expiresInSeconds: result.params.expires_in, - }, - profile, - }; - - if (this.signInResolver) { - response.backstageIdentity = await this.signInResolver( - { - result, - profile, - }, - this.resolverContext, - ); - } - - return response; - } -} + adaptLegacyOAuthHandler, + adaptLegacyOAuthSignInResolver, +} from '../../lib/legacy'; +import { oktaAuthenticator } from '@backstage/plugin-auth-backend-module-okta-provider'; /** * Auth provider integration for Okta auth @@ -216,75 +37,20 @@ export const okta = createAuthProviderIntegration({ * into the profile that will be presented to the user. */ authHandler?: AuthHandler; - /** * Configure sign-in for this provider, without it the provider can not be used to sign users in. */ signIn?: { - /** - * Maps an auth result to a Backstage identity for the user. - */ resolver: SignInResolver; }; }) { - return ({ providerId, globalConfig, config, resolverContext }) => - OAuthEnvironmentHandler.mapConfig(config, envConfig => { - const clientId = envConfig.getString('clientId'); - const clientSecret = envConfig.getString('clientSecret'); - const audience = envConfig.getString('audience'); - const authServerId = envConfig.getOptionalString('authServerId'); - const idp = envConfig.getOptionalString('idp'); - const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); - const callbackUrl = - customCallbackUrl || - `${globalConfig.baseUrl}/${providerId}/handler/frame`; - const additionalScopes = - envConfig.getOptionalString('additionalScopes'); - - // This is a safe assumption as `passport-okta-oauth` uses the audience - // as the base for building the authorization, token, and user info URLs. - // https://github.com/fischerdan/passport-okta-oauth/blob/ea9ac42d/lib/passport-okta-oauth/oauth2.js#L12-L14 - if (!audience.startsWith('https://')) { - throw new Error("URL for 'audience' must start with 'https://'."); - } - - const authHandler: AuthHandler = options?.authHandler - ? options.authHandler - : async ({ fullProfile, params }) => ({ - profile: makeProfileInfo(fullProfile, params.id_token), - }); - - const provider = new OktaAuthProvider({ - audience, - authServerId, - idp, - clientId, - clientSecret, - callbackUrl, - authHandler, - signInResolver: options?.signIn?.resolver, - resolverContext, - additionalScopes, - }); - - return OAuthAdapter.fromConfig(globalConfig, provider, { - providerId, - callbackUrl, - }); - }); + return createOAuthProviderFactory({ + authenticator: oktaAuthenticator, + profileTransform: adaptLegacyOAuthHandler(options?.authHandler), + signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver), + }); }, resolvers: { - /** - * Looks up the user by matching their email local part to the entity name. - */ - emailLocalPartMatchingUserEntityName: () => commonByEmailLocalPartResolver, - /** - * Looks up the user by matching their email to the entity email. - */ - emailMatchingUserEntityProfileEmail: () => commonByEmailResolver, - /** - * Looks up the user by matching their email to the `okta.com/email` annotation. - */ emailMatchingUserEntityAnnotation(): SignInResolver { return async (info, ctx) => { const { profile } = info; diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index 35a361c0c5..13c9873318 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-auth-node +## 0.4.2-next.2 + +### Patch Changes + +- a62764b: Updated dependency `passport` to `^0.7.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## 0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## 0.4.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.4.1 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index a111140e57..ebdbe6d368 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.4.1", + "version": "0.4.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -41,7 +41,7 @@ "jose": "^4.6.0", "lodash": "^4.17.21", "node-fetch": "^2.6.7", - "passport": "^0.6.0", + "passport": "^0.7.0", "winston": "^3.2.1", "zod": "^3.21.4", "zod-to-json-schema": "^3.21.4" diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index cda909cf9f..dfdeebb9b5 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,50 @@ # @backstage/plugin-azure-devops-backend +## 0.5.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-azure-devops-common@0.3.2-next.0 + - @backstage/plugin-catalog-common@1.0.18 + +## 0.5.0-next.1 + +### Minor Changes + +- 844969cd97: **BREAKING** New `fromConfig` static method must be used now when creating an instance of the `AzureDevOpsApi` + + Added support for using the `AzureDevOpsCredentialsProvider` + +### Patch Changes + +- 043b724c56: Introduced new `AzureDevOpsAnnotatorProcessor` that adds the needed annotations automatically. Also, moved constants to common package so they can be shared more easily +- Updated dependencies + - @backstage/plugin-azure-devops-common@0.3.2-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-devops-common@0.3.1 + ## 0.4.4 ### Patch Changes diff --git a/plugins/azure-devops-backend/README.md b/plugins/azure-devops-backend/README.md index e892b84dd1..6810112bdb 100644 --- a/plugins/azure-devops-backend/README.md +++ b/plugins/azure-devops-backend/README.md @@ -89,6 +89,29 @@ In your `packages/backend/src/index.ts` make the following changes: backend.start(); ``` +## Processor + +The Azure DevOps backend plugin includes the `AzureDevOpsAnnotatorProcessor` which will automatically add the needed annotations for you. Here's how to install it: + +```diff + import { CatalogBuilder } from '@backstage/plugin-catalog-backend'; + import { ScaffolderEntitiesProcessor } from '@backstage/plugin-catalog-backend-module-scaffolder-entity-model'; + import { Router } from 'express'; + import { PluginEnvironment } from '../types'; ++ import { AzureDevOpsAnnotatorProcessor } from '@backstage/plugin-azure-devops-backend'; + + export default async function createPlugin( + env: PluginEnvironment, + ): Promise { + const builder = await CatalogBuilder.create(env); + builder.addProcessor(new ScaffolderEntitiesProcessor()); ++ builder.addProcessor(AzureDevOpsAnnotatorProcessor.fromConfig(env.config)); + const { processingEngine, router } = await builder.build(); + await processingEngine.start(); + return router; + } +``` + ## Links - [Frontend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/azure-devops) diff --git a/plugins/azure-devops-backend/api-report.md b/plugins/azure-devops-backend/api-report.md index 8c916a1495..ac12f85131 100644 --- a/plugins/azure-devops-backend/api-report.md +++ b/plugins/azure-devops-backend/api-report.md @@ -7,24 +7,53 @@ import { BackendFeature } from '@backstage/backend-plugin-api'; import { Build } from 'azure-devops-node-api/interfaces/BuildInterfaces'; import { BuildDefinitionReference } from 'azure-devops-node-api/interfaces/BuildInterfaces'; import { BuildRun } from '@backstage/plugin-azure-devops-common'; +import { CatalogProcessor } from '@backstage/plugin-catalog-node'; import { Config } from '@backstage/config'; import { DashboardPullRequest } from '@backstage/plugin-azure-devops-common'; +import { Entity } from '@backstage/catalog-model'; import express from 'express'; import { GitRepository } from 'azure-devops-node-api/interfaces/GitInterfaces'; import { GitTag } from '@backstage/plugin-azure-devops-common'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; import { Logger } from 'winston'; import { Project } from '@backstage/plugin-azure-devops-common'; import { PullRequest } from '@backstage/plugin-azure-devops-common'; import { PullRequestOptions } from '@backstage/plugin-azure-devops-common'; import { RepoBuild } from '@backstage/plugin-azure-devops-common'; +import { ScmIntegrationRegistry } from '@backstage/integration'; import { Team } from '@backstage/plugin-azure-devops-common'; import { TeamMember } from '@backstage/plugin-azure-devops-common'; import { UrlReader } from '@backstage/backend-common'; -import { WebApi } from 'azure-devops-node-api'; + +// @public (undocumented) +export class AzureDevOpsAnnotatorProcessor implements CatalogProcessor { + constructor(opts: { + scmIntegrationRegistry: ScmIntegrationRegistry; + kinds?: string[]; + }); + // (undocumented) + static fromConfig( + config: Config, + options?: { + kinds?: string[]; + }, + ): AzureDevOpsAnnotatorProcessor; + // (undocumented) + getProcessorName(): string; + // (undocumented) + preProcessEntity(entity: Entity, location: LocationSpec): Promise; +} // @public (undocumented) export class AzureDevOpsApi { - constructor(logger: Logger, webApi: WebApi, urlReader: UrlReader); + // (undocumented) + static fromConfig( + config: Config, + options: { + logger: Logger; + urlReader: UrlReader; + }, + ): AzureDevOpsApi; // (undocumented) getAllTeams(): Promise; // (undocumented) diff --git a/plugins/azure-devops-backend/config.d.ts b/plugins/azure-devops-backend/config.d.ts index 433e4df22f..86fefeeef9 100644 --- a/plugins/azure-devops-backend/config.d.ts +++ b/plugins/azure-devops-backend/config.d.ts @@ -15,7 +15,9 @@ */ export interface Config { - /** Configuration options for the azure-devops-backend plugin */ + /** + * Configuration options for the azure-devops-backend plugin + */ azureDevOps: { /** * The hostname of the given Azure instance diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index 030ac45088..e7fe43bdc1 100644 --- a/plugins/azure-devops-backend/package.json +++ b/plugins/azure-devops-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-backend", - "version": "0.4.4", + "version": "0.5.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,12 +30,17 @@ "dependencies": { "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", + "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", + "@backstage/integration": "workspace:^", "@backstage/plugin-azure-devops-common": "workspace:^", + "@backstage/plugin-catalog-common": "workspace:^", + "@backstage/plugin-catalog-node": "workspace:^", "@types/express": "^4.17.6", "azure-devops-node-api": "^11.0.1", "express": "^4.17.1", "express-promise-router": "^4.1.0", + "lodash": "^4.17.21", "mime-types": "^2.1.27", "p-limit": "^3.1.0", "winston": "^3.2.1", diff --git a/plugins/azure-devops-backend/src/api/AzureDevOpsApi.test.ts b/plugins/azure-devops-backend/src/api/AzureDevOpsApi.test.ts index dade60f1ed..174c5ff6cd 100644 --- a/plugins/azure-devops-backend/src/api/AzureDevOpsApi.test.ts +++ b/plugins/azure-devops-backend/src/api/AzureDevOpsApi.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Backstage Authors + * 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. @@ -14,560 +14,751 @@ * limitations under the License. */ +jest.mock('azure-devops-node-api', () => ({ + WebApi: jest.fn(), + getHandlerFromToken: jest.fn().mockReturnValue(() => {}), +})); + +import { UrlReader, getVoidLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { AzureDevOpsApi } from './AzureDevOpsApi'; +import { WebApi } from 'azure-devops-node-api'; +import { TeamProjectReference } from 'azure-devops-node-api/interfaces/CoreInterfaces'; +import { GitRepository } from 'azure-devops-node-api/interfaces/TfvcInterfaces'; import { Build, - DefinitionReference, -} from 'azure-devops-node-api/interfaces/BuildInterfaces'; -import { BuildResult, BuildStatus, - GitTag, - PullRequest, - PullRequestStatus, - RepoBuild, -} from '@backstage/plugin-azure-devops-common'; +} from 'azure-devops-node-api/interfaces/BuildInterfaces'; import { GitPullRequest, GitRef, - GitRepository, + PullRequestStatus, } from 'azure-devops-node-api/interfaces/GitInterfaces'; -import { - mappedBuildRun, - mappedGitTag, - mappedPullRequest, - mappedRepoBuild, -} from './AzureDevOpsApi'; - -import { IdentityRef } from 'azure-devops-node-api/interfaces/common/VSSInterfaces'; +import { PullRequestOptions } from '@backstage/plugin-azure-devops-common'; describe('AzureDevOpsApi', () => { - describe('mappedRepoBuild', () => { - describe('mappedRepoBuild happy path', () => { - it('should return RepoBuild from Build', () => { - const inputBuildDefinition: DefinitionReference = { - name: 'My Build Definition', - }; - - const inputLinks: any = { - web: { - href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - }, - }; - - const inputIdentityRef: IdentityRef = { - displayName: 'Jane Doe', - uniqueName: 'DOMAIN\\jdoe', - }; - - const inputBuild: Build = { - id: 1, - buildNumber: 'Build-1', - status: BuildStatus.Completed, - result: BuildResult.Succeeded, - queueTime: new Date('2020-09-12T06:10:23.932Z'), - startTime: new Date('2020-09-12T06:15:23.932Z'), - finishTime: new Date('2020-09-12T06:20:23.932Z'), - sourceBranch: 'refs/heads/develop', - sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', - definition: inputBuildDefinition, - _links: inputLinks, - requestedFor: inputIdentityRef, - }; - - const outputRepoBuild: RepoBuild = { - id: 1, - title: 'My Build Definition - Build-1', - link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - status: BuildStatus.Completed, - result: BuildResult.Succeeded, - queueTime: '2020-09-12T06:10:23.932Z', - startTime: '2020-09-12T06:15:23.932Z', - finishTime: '2020-09-12T06:20:23.932Z', - source: 'refs/heads/develop (f4f78b31)', - uniqueName: 'DOMAIN\\jdoe', - }; - - expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); - }); - }); - - describe('mappedRepoBuild with no Build definition name', () => { - it('should return RepoBuild with only Build Number for title', () => { - const inputLinks: any = { - web: { - href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - }, - }; - - const inputIdentityRef: IdentityRef = { - displayName: 'Jane Doe', - uniqueName: 'DOMAIN\\jdoe', - }; - - const inputBuild: Build = { - id: 1, - buildNumber: 'Build-1', - status: BuildStatus.Completed, - result: BuildResult.Succeeded, - queueTime: new Date('2020-09-12T06:10:23.932Z'), - startTime: new Date('2020-09-12T06:15:23.932Z'), - finishTime: new Date('2020-09-12T06:20:23.932Z'), - sourceBranch: 'refs/heads/develop', - sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', - definition: undefined, - _links: inputLinks, - requestedFor: inputIdentityRef, - }; - - const outputRepoBuild: RepoBuild = { - id: 1, - title: 'Build-1', - link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - status: BuildStatus.Completed, - result: BuildResult.Succeeded, - queueTime: '2020-09-12T06:10:23.932Z', - startTime: '2020-09-12T06:15:23.932Z', - finishTime: '2020-09-12T06:20:23.932Z', - source: 'refs/heads/develop (f4f78b31)', - uniqueName: 'DOMAIN\\jdoe', - }; - - expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); - }); - }); - - describe('mappedRepoBuild with undefined status', () => { - it('should return BuildStatus of None for status', () => { - const inputLinks: any = { - web: { - href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - }, - }; - - const inputIdentityRef: IdentityRef = { - displayName: 'Jane Doe', - uniqueName: 'DOMAIN\\jdoe', - }; - - const inputBuild: Build = { - id: 1, - buildNumber: 'Build-1', - status: undefined, - result: BuildResult.Succeeded, - queueTime: new Date('2020-09-12T06:10:23.932Z'), - startTime: new Date('2020-09-12T06:15:23.932Z'), - finishTime: new Date('2020-09-12T06:20:23.932Z'), - sourceBranch: 'refs/heads/develop', - sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', - definition: undefined, - _links: inputLinks, - requestedFor: inputIdentityRef, - }; - - const outputRepoBuild: RepoBuild = { - id: 1, - title: 'Build-1', - link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - status: BuildStatus.None, - result: BuildResult.Succeeded, - queueTime: '2020-09-12T06:10:23.932Z', - startTime: '2020-09-12T06:15:23.932Z', - finishTime: '2020-09-12T06:20:23.932Z', - source: 'refs/heads/develop (f4f78b31)', - uniqueName: 'DOMAIN\\jdoe', - }; - - expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); - }); - }); - - describe('mappedRepoBuild with undefined result', () => { - it('should return BuildResult of None for result', () => { - const inputLinks: any = { - web: { - href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - }, - }; - - const inputIdentityRef: IdentityRef = { - displayName: 'Jane Doe', - uniqueName: 'DOMAIN\\jdoe', - }; - - const inputBuild: Build = { - id: 1, - buildNumber: 'Build-1', - status: BuildStatus.InProgress, - result: undefined, - queueTime: new Date('2020-09-12T06:10:23.932Z'), - startTime: new Date('2020-09-12T06:15:23.932Z'), - finishTime: new Date('2020-09-12T06:20:23.932Z'), - sourceBranch: 'refs/heads/develop', - sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', - definition: undefined, - _links: inputLinks, - requestedFor: inputIdentityRef, - }; - - const outputRepoBuild: RepoBuild = { - id: 1, - title: 'Build-1', - link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - status: BuildStatus.InProgress, - result: BuildResult.None, - queueTime: '2020-09-12T06:10:23.932Z', - startTime: '2020-09-12T06:15:23.932Z', - finishTime: '2020-09-12T06:20:23.932Z', - source: 'refs/heads/develop (f4f78b31)', - uniqueName: 'DOMAIN\\jdoe', - }; - - expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); - }); - }); - - describe('mappedRepoBuild with undefined link', () => { - it('should return empty string for link', () => { - const inputIdentityRef: IdentityRef = { - displayName: 'Jane Doe', - uniqueName: 'DOMAIN\\jdoe', - }; - - const inputBuild: Build = { - id: 1, - buildNumber: 'Build-1', - status: BuildStatus.InProgress, - result: undefined, - queueTime: new Date('2020-09-12T06:10:23.932Z'), - startTime: new Date('2020-09-12T06:15:23.932Z'), - finishTime: new Date('2020-09-12T06:20:23.932Z'), - sourceBranch: 'refs/heads/develop', - sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', - definition: undefined, - _links: undefined, - requestedFor: inputIdentityRef, - }; - - const outputRepoBuild: RepoBuild = { - id: 1, - title: 'Build-1', - link: '', - status: BuildStatus.InProgress, - result: BuildResult.None, - queueTime: '2020-09-12T06:10:23.932Z', - startTime: '2020-09-12T06:15:23.932Z', - finishTime: '2020-09-12T06:20:23.932Z', - source: 'refs/heads/develop (f4f78b31)', - uniqueName: 'DOMAIN\\jdoe', - }; - - expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); - }); - }); + beforeEach(() => { + jest.clearAllMocks(); }); - describe('mappedGitTag', () => { - describe('mappedGitTag happy path', () => { - it('should return GitTag from GitRef', () => { - const inputIdentityRef: IdentityRef = { - displayName: 'Jane Doe', - }; - const inputGitRef: GitRef = { - name: 'refs/tags/v1.1.2', - creator: inputIdentityRef, - objectId: '1111aaaa2222bbbb3333cccc4444dddd5555eeee', - peeledObjectId: '1234567890abcdef1234567890abcdef12345678', - }; - const inputLinkBaseUrl = - 'https://host.com/myOrg/_git/super-feature-repo?version=GT'; - const inputCommitBaseUrl = - 'https://host.com/myOrg/_git/super-feature-repo/commit'; - const outputGitTag: GitTag = { - name: 'v1.1.2', - createdBy: 'Jane Doe', - commitLink: - 'https://host.com/myOrg/_git/super-feature-repo/commit/1234567890abcdef1234567890abcdef12345678', - objectId: '1111aaaa2222bbbb3333cccc4444dddd5555eeee', - peeledObjectId: '1234567890abcdef1234567890abcdef12345678', - link: 'https://host.com/myOrg/_git/super-feature-repo?version=GTv1.1.2', - }; - expect( - mappedGitTag(inputGitRef, inputLinkBaseUrl, inputCommitBaseUrl), - ).toEqual(outputGitTag); - }); - }); + const mockConfig = new ConfigReader({ + azureDevOps: { + host: 'dev.azure.com', + token: 'token', + organization: 'org', + }, + integrations: { + azure: [ + { + host: 'dev.azure.com', + credentials: [ + { + personalAccessToken: 'pat', + }, + ], + }, + ], + }, }); - describe('mappedPullRequest', () => { - describe('mappedPullRequest happy path', () => { - it('should return PullRequest from GitPullRequest', () => { - const inputGitRepository: GitRepository = { - name: 'super-feature-repo', - }; + const mockLogger = getVoidLogger(); - const inputIdentityRef: IdentityRef = { - displayName: 'Jane Doe', - uniqueName: 'DOMAIN\\jdoe', - }; + const mockUrlReader: UrlReader = { + readUrl: url => + Promise.resolve({ + buffer: async () => Buffer.from(url), + etag: 'buffer', + stream: jest.fn(), + }), + readTree: jest.fn(), + search: jest.fn(), + }; - const inputPullRequest: GitPullRequest = { - pullRequestId: 7181, - repository: inputGitRepository, - title: 'My Awesome New Feature', - createdBy: inputIdentityRef, - creationDate: new Date('2020-09-12T06:10:23.932Z'), - sourceRefName: 'refs/heads/topic/super-awesome-feature', - targetRefName: 'refs/heads/main', - status: PullRequestStatus.Active, - isDraft: false, - }; + it('should get projects', async () => { + const mockProjects: TeamProjectReference[] = [ + { + id: 'one', + name: 'one', + description: 'one', + }, + { + id: 'two', + name: 'two', + description: 'two', + }, + { + id: 'three', + name: 'three', + description: 'three', + }, + ]; - const inputBaseUrl = - 'https://host.com/myOrg/_git/super-feature-repo/pullrequest'; + const mockCoreApiClient = { + getProjects: jest.fn().mockResolvedValue(mockProjects), + }; - const outputPullRequest: PullRequest = { - pullRequestId: 7181, - repoName: 'super-feature-repo', - title: 'My Awesome New Feature', - uniqueName: 'DOMAIN\\jdoe', - createdBy: 'Jane Doe', - creationDate: '2020-09-12T06:10:23.932Z', - sourceRefName: 'refs/heads/topic/super-awesome-feature', - targetRefName: 'refs/heads/main', - status: PullRequestStatus.Active, - isDraft: false, - link: 'https://host.com/myOrg/_git/super-feature-repo/pullrequest/7181', - }; + const mockCoreApi = { + getCoreApi: jest.fn().mockResolvedValue(mockCoreApiClient), + }; - expect(mappedPullRequest(inputPullRequest, inputBaseUrl)).toEqual( - outputPullRequest, - ); - }); + (WebApi as unknown as jest.Mock).mockImplementation(() => mockCoreApi); + + const api = AzureDevOpsApi.fromConfig(mockConfig, { + logger: mockLogger, + urlReader: mockUrlReader, }); + + const result = await api.getProjects(); + + expect(result).toEqual([ + { + id: 'one', + name: 'one', + description: 'one', + }, + { + id: 'three', + name: 'three', + description: 'three', + }, + { + id: 'two', + name: 'two', + description: 'two', + }, + ]); }); - describe('mappedBuildRun', () => { - describe('mappedBuildRun happy path', () => { - it('should return RepoBuild from Build', () => { - const inputBuildDefinition: DefinitionReference = { - name: 'My Build Definition', - }; + it('should get git repository', async () => { + const mockGitRepository: GitRepository = { + id: 'repo', + }; - const inputLinks: any = { - web: { - href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - }, - }; + const mockGitClient = { + getRepository: jest.fn().mockResolvedValue(mockGitRepository), + }; + const mockGitApi = { + getGitApi: jest.fn().mockReturnValue(mockGitClient), + }; - const inputIdentityRef: IdentityRef = { - displayName: 'Jane Doe', - uniqueName: 'DOMAIN\\jdoe', - }; + (WebApi as unknown as jest.Mock).mockImplementation(() => mockGitApi); - const inputBuild: Build = { - id: 1, - buildNumber: 'Build-1', - status: BuildStatus.Completed, - result: BuildResult.Succeeded, - queueTime: new Date('2020-09-12T06:10:23.932Z'), - startTime: new Date('2020-09-12T06:15:23.932Z'), - finishTime: new Date('2020-09-12T06:20:23.932Z'), - sourceBranch: 'refs/heads/develop', - sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', - definition: inputBuildDefinition, - _links: inputLinks, - requestedFor: inputIdentityRef, - }; - - const outputRepoBuild: RepoBuild = { - id: 1, - title: 'My Build Definition - Build-1', - link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - status: BuildStatus.Completed, - result: BuildResult.Succeeded, - queueTime: '2020-09-12T06:10:23.932Z', - startTime: '2020-09-12T06:15:23.932Z', - finishTime: '2020-09-12T06:20:23.932Z', - source: 'refs/heads/develop (f4f78b31)', - uniqueName: 'DOMAIN\\jdoe', - }; - - expect(mappedBuildRun(inputBuild)).toEqual(outputRepoBuild); - }); + const api = AzureDevOpsApi.fromConfig(mockConfig, { + logger: mockLogger, + urlReader: mockUrlReader, }); - describe('mappedBuildRun with no Build definition name', () => { - it('should return RepoBuild with only Build Number for title', () => { - const inputLinks: any = { - web: { - href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - }, - }; + const result = await api.getGitRepository('project', 'repo'); - const inputIdentityRef: IdentityRef = { - displayName: 'Jane Doe', - uniqueName: 'DOMAIN\\jdoe', - }; + expect(result).toEqual({ id: 'repo' }); + }); - const inputBuild: Build = { - id: 1, - buildNumber: 'Build-1', - status: BuildStatus.Completed, - result: BuildResult.Succeeded, - queueTime: new Date('2020-09-12T06:10:23.932Z'), - startTime: new Date('2020-09-12T06:15:23.932Z'), - finishTime: new Date('2020-09-12T06:20:23.932Z'), - sourceBranch: 'refs/heads/develop', - sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', - definition: undefined, - _links: inputLinks, - requestedFor: inputIdentityRef, - }; + it('should get build list', async () => { + const mockBuilds: Build[] = [ + { + id: 1, + }, + { + id: 2, + }, + { + id: 3, + }, + ]; - const outputRepoBuild: RepoBuild = { - id: 1, - title: 'Build-1', - link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - status: BuildStatus.Completed, - result: BuildResult.Succeeded, - queueTime: '2020-09-12T06:10:23.932Z', - startTime: '2020-09-12T06:15:23.932Z', - finishTime: '2020-09-12T06:20:23.932Z', - source: 'refs/heads/develop (f4f78b31)', - uniqueName: 'DOMAIN\\jdoe', - }; + const mockBuildClient = { + getBuilds: jest.fn().mockResolvedValue(mockBuilds), + }; + const mockBuildApi = { + getBuildApi: jest.fn().mockReturnValue(mockBuildClient), + }; - expect(mappedBuildRun(inputBuild)).toEqual(outputRepoBuild); - }); + (WebApi as unknown as jest.Mock).mockImplementation(() => mockBuildApi); + + const api = AzureDevOpsApi.fromConfig(mockConfig, { + logger: mockLogger, + urlReader: mockUrlReader, }); - describe('mappedBuildRun with undefined status', () => { - it('should return BuildStatus of None for status', () => { - const inputLinks: any = { - web: { - href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - }, - }; + const result = await api.getBuildList('project', 'repo', 10); - const inputIdentityRef: IdentityRef = { - displayName: 'Jane Doe', - uniqueName: 'DOMAIN\\jdoe', - }; + expect(result).toEqual([{ id: 1 }, { id: 2 }, { id: 3 }]); + }); - const inputBuild: Build = { - id: 1, - buildNumber: 'Build-1', - status: undefined, - result: BuildResult.Succeeded, - queueTime: new Date('2020-09-12T06:10:23.932Z'), - startTime: new Date('2020-09-12T06:15:23.932Z'), - finishTime: new Date('2020-09-12T06:20:23.932Z'), - sourceBranch: 'refs/heads/develop', - sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', - definition: undefined, - _links: inputLinks, - requestedFor: inputIdentityRef, - }; + it('should get repo builds', async () => { + const mockGitRepository: GitRepository = { + id: 'repo', + }; - const outputRepoBuild: RepoBuild = { - id: 1, - title: 'Build-1', - link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - status: BuildStatus.None, - result: BuildResult.Succeeded, - queueTime: '2020-09-12T06:10:23.932Z', - startTime: '2020-09-12T06:15:23.932Z', - finishTime: '2020-09-12T06:20:23.932Z', - source: 'refs/heads/develop (f4f78b31)', - uniqueName: 'DOMAIN\\jdoe', - }; + const mockBuilds: Build[] = [ + { + id: 1, + buildNumber: 'Build-1', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'main', + sourceVersion: 'abcd', + }, + { + id: 2, + buildNumber: 'Build-2', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'main', + sourceVersion: 'abcd', + }, + { + id: 3, + buildNumber: 'Build-3', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'main', + sourceVersion: 'abcd', + }, + ]; - expect(mappedBuildRun(inputBuild)).toEqual(outputRepoBuild); - }); + const mockBuildClient = { + getBuilds: jest.fn().mockResolvedValue(mockBuilds), + }; + const mockGitClient = { + getRepository: jest.fn().mockResolvedValue(mockGitRepository), + }; + const mockApi = { + getGitApi: jest.fn().mockReturnValue(mockGitClient), + getBuildApi: jest.fn().mockReturnValue(mockBuildClient), + }; + + (WebApi as unknown as jest.Mock).mockImplementation(() => mockApi); + + const api = AzureDevOpsApi.fromConfig(mockConfig, { + logger: mockLogger, + urlReader: mockUrlReader, }); - describe('mappedBuildRun with undefined result', () => { - it('should return BuildResult of None for result', () => { - const inputLinks: any = { - web: { - href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - }, - }; + const result = await api.getRepoBuilds('project', 'repo', 10); - const inputIdentityRef: IdentityRef = { - displayName: 'Jane Doe', - uniqueName: 'DOMAIN\\jdoe', - }; + expect(result).toEqual([ + { + id: 1, + title: 'Build-1', + link: '', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'main (abcd)', + uniqueName: 'N/A', + }, + { + id: 2, + title: 'Build-2', + link: '', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'main (abcd)', + uniqueName: 'N/A', + }, + { + id: 3, + title: 'Build-3', + link: '', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'main (abcd)', + uniqueName: 'N/A', + }, + ]); + }); - const inputBuild: Build = { - id: 1, - buildNumber: 'Build-1', - status: BuildStatus.InProgress, - result: undefined, - queueTime: new Date('2020-09-12T06:10:23.932Z'), - startTime: new Date('2020-09-12T06:15:23.932Z'), - finishTime: new Date('2020-09-12T06:20:23.932Z'), - sourceBranch: 'refs/heads/develop', - sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', - definition: undefined, - _links: inputLinks, - requestedFor: inputIdentityRef, - }; + it('should get git tags', async () => { + const mockGitRepository: GitRepository = { + id: 'repo', + }; - const outputRepoBuild: RepoBuild = { - id: 1, - title: 'Build-1', - link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', - status: BuildStatus.InProgress, - result: BuildResult.None, - queueTime: '2020-09-12T06:10:23.932Z', - startTime: '2020-09-12T06:15:23.932Z', - finishTime: '2020-09-12T06:20:23.932Z', - source: 'refs/heads/develop (f4f78b31)', - uniqueName: 'DOMAIN\\jdoe', - }; + const mockGitRefs: GitRef[] = [ + { + objectId: '1.0', + peeledObjectId: '1.0', + name: 'v1.0', + }, + { + objectId: '2.0', + peeledObjectId: '2.0', + name: 'v2.0', + }, + { + objectId: '3.0', + peeledObjectId: '3.0', + name: 'v3.0', + }, + ]; - expect(mappedBuildRun(inputBuild)).toEqual(outputRepoBuild); - }); + const mockGitClient = { + getRepository: jest.fn().mockResolvedValue(mockGitRepository), + getRefs: jest.fn().mockResolvedValue(mockGitRefs), + }; + const mockApi = { + getGitApi: jest.fn().mockReturnValue(mockGitClient), + serverUrl: 'serverUrl', + }; + + (WebApi as unknown as jest.Mock).mockImplementation(() => mockApi); + + const api = AzureDevOpsApi.fromConfig(mockConfig, { + logger: mockLogger, + urlReader: mockUrlReader, }); - describe('mappedBuildRun with undefined link', () => { - it('should return empty string for link', () => { - const inputIdentityRef: IdentityRef = { - displayName: 'Jane Doe', - uniqueName: 'DOMAIN\\jdoe', - }; + const result = await api.getGitTags('project', 'repo'); - const inputBuild: Build = { - id: 1, - buildNumber: 'Build-1', - status: BuildStatus.InProgress, - result: undefined, - queueTime: new Date('2020-09-12T06:10:23.932Z'), - startTime: new Date('2020-09-12T06:15:23.932Z'), - finishTime: new Date('2020-09-12T06:20:23.932Z'), - sourceBranch: 'refs/heads/develop', - sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', - definition: undefined, - _links: undefined, - requestedFor: inputIdentityRef, - }; + expect(result).toEqual([ + { + objectId: '1.0', + peeledObjectId: '1.0', + name: 'v1.0', + commitLink: 'serverUrl/project/_git/repo/commit/1.0', + createdBy: 'N/A', + link: 'serverUrl/project/_git/repo?version=GTv1.0', + }, + { + objectId: '2.0', + peeledObjectId: '2.0', + name: 'v2.0', + commitLink: 'serverUrl/project/_git/repo/commit/2.0', + createdBy: 'N/A', + link: 'serverUrl/project/_git/repo?version=GTv2.0', + }, + { + objectId: '3.0', + peeledObjectId: '3.0', + name: 'v3.0', + commitLink: 'serverUrl/project/_git/repo/commit/3.0', + createdBy: 'N/A', + link: 'serverUrl/project/_git/repo?version=GTv3.0', + }, + ]); + }); - const outputRepoBuild: RepoBuild = { - id: 1, - title: 'Build-1', - link: '', - status: BuildStatus.InProgress, - result: BuildResult.None, - queueTime: '2020-09-12T06:10:23.932Z', - startTime: '2020-09-12T06:15:23.932Z', - finishTime: '2020-09-12T06:20:23.932Z', - source: 'refs/heads/develop (f4f78b31)', - uniqueName: 'DOMAIN\\jdoe', - }; + it('should get pull requests', async () => { + const mockGitRepository: GitRepository = { + id: 'repo', + name: 'repo', + }; - expect(mappedBuildRun(inputBuild)).toEqual(outputRepoBuild); - }); + const mockGitPullRequests: GitPullRequest[] = [ + { + pullRequestId: 1, + repository: mockGitRepository, + title: 'PR1', + creationDate: new Date('2020-09-12T06:10:23.932Z'), + sourceRefName: 'refs/heads/topic/pr1', + targetRefName: 'refs/heads/main', + status: PullRequestStatus.Active, + isDraft: false, + }, + { + pullRequestId: 2, + repository: mockGitRepository, + title: 'PR2', + creationDate: new Date('2020-09-12T06:10:23.932Z'), + sourceRefName: 'refs/heads/topic/pr2', + targetRefName: 'refs/heads/main', + status: PullRequestStatus.Active, + isDraft: false, + }, + { + pullRequestId: 3, + repository: mockGitRepository, + title: 'PR3', + creationDate: new Date('2020-09-12T06:10:23.932Z'), + sourceRefName: 'refs/heads/topic/pr3', + targetRefName: 'refs/heads/main', + status: PullRequestStatus.Active, + isDraft: false, + }, + ]; + + const mockGitClient = { + getRepository: jest.fn().mockResolvedValue(mockGitRepository), + getPullRequests: jest.fn().mockResolvedValue(mockGitPullRequests), + }; + const mockApi = { + getGitApi: jest.fn().mockReturnValue(mockGitClient), + serverUrl: 'serverUrl', + }; + + (WebApi as unknown as jest.Mock).mockImplementation(() => mockApi); + + const api = AzureDevOpsApi.fromConfig(mockConfig, { + logger: mockLogger, + urlReader: mockUrlReader, }); + + const pullRequestOptions: PullRequestOptions = { + top: 10, + status: PullRequestStatus.Active, + }; + + const result = await api.getPullRequests( + 'project', + 'repo', + pullRequestOptions, + ); + + expect(result).toEqual([ + { + pullRequestId: 1, + repoName: 'repo', + title: 'PR1', + uniqueName: 'N/A', + createdBy: 'N/A', + creationDate: '2020-09-12T06:10:23.932Z', + sourceRefName: 'refs/heads/topic/pr1', + targetRefName: 'refs/heads/main', + status: PullRequestStatus.Active, + isDraft: false, + link: 'serverUrl/project/_git/repo/pullrequest/1', + }, + { + pullRequestId: 2, + repoName: 'repo', + title: 'PR2', + uniqueName: 'N/A', + createdBy: 'N/A', + creationDate: '2020-09-12T06:10:23.932Z', + sourceRefName: 'refs/heads/topic/pr2', + targetRefName: 'refs/heads/main', + status: PullRequestStatus.Active, + isDraft: false, + link: 'serverUrl/project/_git/repo/pullrequest/2', + }, + { + pullRequestId: 3, + repoName: 'repo', + title: 'PR3', + uniqueName: 'N/A', + createdBy: 'N/A', + creationDate: '2020-09-12T06:10:23.932Z', + sourceRefName: 'refs/heads/topic/pr3', + targetRefName: 'refs/heads/main', + status: PullRequestStatus.Active, + isDraft: false, + link: 'serverUrl/project/_git/repo/pullrequest/3', + }, + ]); + }); + + it('should get build definitions', async () => { + const mockBuilds: Build[] = [ + { + id: 1, + }, + { + id: 2, + }, + { + id: 3, + }, + ]; + + const mockBuildClient = { + getDefinitions: jest.fn().mockResolvedValue(mockBuilds), + }; + const mockBuildApi = { + getBuildApi: jest.fn().mockReturnValue(mockBuildClient), + }; + + (WebApi as unknown as jest.Mock).mockImplementation(() => mockBuildApi); + + const api = AzureDevOpsApi.fromConfig(mockConfig, { + logger: mockLogger, + urlReader: mockUrlReader, + }); + + const result = await api.getBuildDefinitions('project', 'definition'); + + expect(result).toEqual([{ id: 1 }, { id: 2 }, { id: 3 }]); + }); + + it('should get build builds with repoId', async () => { + const mockBuilds: Build[] = [ + { + id: 1, + }, + { + id: 2, + }, + { + id: 3, + }, + ]; + + const mockBuildClient = { + getBuilds: jest.fn().mockResolvedValue(mockBuilds), + }; + const mockBuildApi = { + getBuildApi: jest.fn().mockReturnValue(mockBuildClient), + }; + + (WebApi as unknown as jest.Mock).mockImplementation(() => mockBuildApi); + + const api = AzureDevOpsApi.fromConfig(mockConfig, { + logger: mockLogger, + urlReader: mockUrlReader, + }); + + const result = await api.getBuilds('project', 10, 'repo', undefined); + + expect(result).toEqual([{ id: 1 }, { id: 2 }, { id: 3 }]); + }); + + it('should get build builds with definitions', async () => { + const mockBuilds: Build[] = [ + { + id: 1, + }, + { + id: 2, + }, + { + id: 3, + }, + ]; + + const mockBuildClient = { + getBuilds: jest.fn().mockResolvedValue(mockBuilds), + }; + const mockBuildApi = { + getBuildApi: jest.fn().mockReturnValue(mockBuildClient), + }; + + (WebApi as unknown as jest.Mock).mockImplementation(() => mockBuildApi); + + const api = AzureDevOpsApi.fromConfig(mockConfig, { + logger: mockLogger, + urlReader: mockUrlReader, + }); + + const result = await api.getBuilds('project', 10, undefined, [1, 2, 3]); + + expect(result).toEqual([{ id: 1 }, { id: 2 }, { id: 3 }]); + }); + + it('should get build runs with repoName', async () => { + const mockGitRepository: GitRepository = { + id: 'repo', + }; + + const mockBuilds: Build[] = [ + { + id: 1, + buildNumber: 'Build-1', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'main', + sourceVersion: 'abcd', + }, + { + id: 2, + buildNumber: 'Build-2', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'main', + sourceVersion: 'abcd', + }, + { + id: 3, + buildNumber: 'Build-3', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'main', + sourceVersion: 'abcd', + }, + ]; + + const mockBuildClient = { + getBuilds: jest.fn().mockResolvedValue(mockBuilds), + }; + const mockGitClient = { + getRepository: jest.fn().mockResolvedValue(mockGitRepository), + }; + const mockApi = { + getGitApi: jest.fn().mockReturnValue(mockGitClient), + getBuildApi: jest.fn().mockReturnValue(mockBuildClient), + }; + + (WebApi as unknown as jest.Mock).mockImplementation(() => mockApi); + + const api = AzureDevOpsApi.fromConfig(mockConfig, { + logger: mockLogger, + urlReader: mockUrlReader, + }); + + const result = await api.getBuildRuns('project', 10, 'repo', undefined); + + expect(result).toEqual([ + { + id: 1, + title: 'Build-1', + link: '', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'main (abcd)', + uniqueName: 'N/A', + }, + { + id: 2, + title: 'Build-2', + link: '', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'main (abcd)', + uniqueName: 'N/A', + }, + { + id: 3, + title: 'Build-3', + link: '', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'main (abcd)', + uniqueName: 'N/A', + }, + ]); + }); + + it('should get build runs with definitionName', async () => { + const mockBuilds: Build[] = [ + { + id: 1, + buildNumber: 'Build-1', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'main', + sourceVersion: 'abcd', + }, + { + id: 2, + buildNumber: 'Build-2', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'main', + sourceVersion: 'abcd', + }, + { + id: 3, + buildNumber: 'Build-3', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'main', + sourceVersion: 'abcd', + }, + ]; + + const mockBuildClient = { + getBuilds: jest.fn().mockResolvedValue(mockBuilds), + getDefinitions: jest.fn().mockResolvedValue(mockBuilds), + }; + + const mockApi = { + getBuildApi: jest.fn().mockReturnValue(mockBuildClient), + }; + + (WebApi as unknown as jest.Mock).mockImplementation(() => mockApi); + + const api = AzureDevOpsApi.fromConfig(mockConfig, { + logger: mockLogger, + urlReader: mockUrlReader, + }); + + const result = await api.getBuildRuns( + 'project', + 10, + undefined, + 'definition', + ); + + expect(result).toEqual([ + { + id: 1, + title: 'Build-1', + link: '', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'main (abcd)', + uniqueName: 'N/A', + }, + { + id: 2, + title: 'Build-2', + link: '', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'main (abcd)', + uniqueName: 'N/A', + }, + { + id: 3, + title: 'Build-3', + link: '', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'main (abcd)', + uniqueName: 'N/A', + }, + ]); }); }); diff --git a/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts b/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts index 87ded2f0e9..6765b54c05 100644 --- a/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts +++ b/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts @@ -19,9 +19,7 @@ import { BuildDefinitionReference, } from 'azure-devops-node-api/interfaces/BuildInterfaces'; import { - BuildResult, BuildRun, - BuildStatus, DashboardPullRequest, GitTag, Policy, @@ -49,23 +47,92 @@ import { import { TeamMember as AdoTeamMember } from 'azure-devops-node-api/interfaces/common/VSSInterfaces'; import { Logger } from 'winston'; import { PolicyEvaluationRecord } from 'azure-devops-node-api/interfaces/PolicyInterfaces'; -import { WebApi } from 'azure-devops-node-api'; +import { + WebApi, + getHandlerFromToken, + getPersonalAccessTokenHandler, +} from 'azure-devops-node-api'; import { TeamProjectReference, WebApiTeam, } from 'azure-devops-node-api/interfaces/CoreInterfaces'; import { UrlReader } from '@backstage/backend-common'; +import { Config } from '@backstage/config'; +import { + AzureDevOpsCredentialsProvider, + DefaultAzureDevOpsCredentialsProvider, + ScmIntegrations, +} from '@backstage/integration'; +import { + mappedBuildRun, + mappedGitTag, + mappedPullRequest, + mappedRepoBuild, +} from './mappers'; /** @public */ export class AzureDevOpsApi { - public constructor( - private readonly logger: Logger, - private readonly webApi: WebApi, - private readonly urlReader: UrlReader, - ) {} + private readonly logger: Logger; + private readonly urlReader: UrlReader; + private readonly config: Config; + private readonly credentialsProvider: AzureDevOpsCredentialsProvider; + + private constructor( + logger: Logger, + urlReader: UrlReader, + config: Config, + credentialsProvider: AzureDevOpsCredentialsProvider, + ) { + this.logger = logger; + this.urlReader = urlReader; + this.config = config; + this.credentialsProvider = credentialsProvider; + } + + static fromConfig( + config: Config, + options: { logger: Logger; urlReader: UrlReader }, + ) { + const scmIntegrations = ScmIntegrations.fromConfig(config); + const credentialsProvider = + DefaultAzureDevOpsCredentialsProvider.fromIntegrations(scmIntegrations); + return new AzureDevOpsApi( + options.logger, + options.urlReader, + config, + credentialsProvider, + ); + } + + private async getWebApi(host?: string, org?: string): Promise { + // If no host or org is provided we fall back to the values from the `azureDevOps` config section + // these may have been setup in the `integrations.azure` config section + // which is why use them here and not just falling back on them entirely + const validHost = host ?? this.config.getString('azureDevOps.host'); + const validOrg = org ?? this.config.getString('azureDevOps.organization'); + const url = `https://${validHost}/${encodeURI(validOrg)}`; + + const credentials = await this.credentialsProvider.getCredentials({ + url, + }); + + let authHandler; + if (!credentials) { + // No credentials found for the provided host and org in the `integrations.azure` config section + // use the fall back personal access token from `azureDevOps.token` + const token = this.config.getString('azureDevOps.token'); + authHandler = getPersonalAccessTokenHandler(token); + } else { + authHandler = getHandlerFromToken(credentials.token); + } + + const webApi = new WebApi(url, authHandler); + return webApi; + } public async getProjects(): Promise { - const client = await this.webApi.getCoreApi(); + const webApi = await this.getWebApi(); + const client = await webApi.getCoreApi(); const projectList: TeamProjectReference[] = await client.getProjects(); const projects: Project[] = projectList.map(project => ({ @@ -87,7 +154,8 @@ export class AzureDevOpsApi { `Calling Azure DevOps REST API, getting Repository ${repoName} for Project ${projectName}`, ); - const client = await this.webApi.getGitApi(); + const webApi = await this.getWebApi(); + const client = await webApi.getGitApi(); return client.getRepository(repoName, projectName); } @@ -100,7 +168,8 @@ export class AzureDevOpsApi { `Calling Azure DevOps REST API, getting up to ${top} Builds for Repository Id ${repoId} for Project ${projectName}`, ); - const client = await this.webApi.getBuildApi(); + const webApi = await this.getWebApi(); + const client = await webApi.getBuildApi(); return client.getBuilds( projectName, undefined, @@ -158,7 +227,8 @@ export class AzureDevOpsApi { ); const gitRepository = await this.getGitRepository(projectName, repoName); - const client = await this.webApi.getGitApi(); + const webApi = await this.getWebApi(); + const client = await webApi.getGitApi(); const tagRefs: GitRef[] = await client.getRefs( gitRepository.id as string, projectName, @@ -169,10 +239,10 @@ export class AzureDevOpsApi { false, true, ); - const linkBaseUrl = `${this.webApi.serverUrl}/${encodeURIComponent( + const linkBaseUrl = `${webApi.serverUrl}/${encodeURIComponent( projectName, )}/_git/${encodeURIComponent(repoName)}?version=GT`; - const commitBaseUrl = `${this.webApi.serverUrl}/${encodeURIComponent( + const commitBaseUrl = `${webApi.serverUrl}/${encodeURIComponent( projectName, )}/_git/${encodeURIComponent(repoName)}/commit`; const gitTags: GitTag[] = tagRefs.map(tagRef => { @@ -192,7 +262,8 @@ export class AzureDevOpsApi { ); const gitRepository = await this.getGitRepository(projectName, repoName); - const client = await this.webApi.getGitApi(); + const webApi = await this.getWebApi(); + const client = await webApi.getGitApi(); const searchCriteria: GitPullRequestSearchCriteria = { status: options.status, }; @@ -204,7 +275,7 @@ export class AzureDevOpsApi { undefined, options.top, ); - const linkBaseUrl = `${this.webApi.serverUrl}/${encodeURIComponent( + const linkBaseUrl = `${webApi.serverUrl}/${encodeURIComponent( projectName, )}/_git/${encodeURIComponent(repoName)}/pullrequest`; const pullRequests: PullRequest[] = gitPullRequests.map(gitPullRequest => { @@ -222,7 +293,8 @@ export class AzureDevOpsApi { `Getting dashboard pull requests for project '${projectName}'.`, ); - const client = await this.webApi.getGitApi(); + const webApi = await this.getWebApi(); + const client = await webApi.getGitApi(); const searchCriteria: GitPullRequestSearchCriteria = { status: options.status, @@ -254,7 +326,7 @@ export class AzureDevOpsApi { return convertDashboardPullRequest( gitPullRequest, - this.webApi.serverUrl, + webApi.serverUrl, policies, ); }), @@ -270,7 +342,8 @@ export class AzureDevOpsApi { `Getting pull request policies for pull request id '${pullRequestId}'.`, ); - const client = await this.webApi.getPolicyApi(); + const webApi = await this.getWebApi(); + const client = await webApi.getPolicyApi(); const artifactId = getArtifactId(projectId, pullRequestId); @@ -285,7 +358,8 @@ export class AzureDevOpsApi { public async getAllTeams(): Promise { this.logger?.debug('Getting all teams.'); - const client = await this.webApi.getCoreApi(); + const webApi = await this.getWebApi(); + const client = await webApi.getCoreApi(); const webApiTeams: WebApiTeam[] = await client.getAllTeams(); const teams: Team[] = webApiTeams.map(team => ({ @@ -307,7 +381,8 @@ export class AzureDevOpsApi { const { projectId, teamId } = options; this.logger?.debug(`Getting team member ids for team '${teamId}'.`); - const client = await this.webApi.getCoreApi(); + const webApi = await this.getWebApi(); + const client = await webApi.getCoreApi(); const teamMembers: AdoTeamMember[] = await client.getTeamMembersWithExtendedProperties(projectId, teamId); @@ -327,7 +402,8 @@ export class AzureDevOpsApi { `Calling Azure DevOps REST API, getting Build Definitions for ${definitionName} in Project ${projectName}`, ); - const client = await this.webApi.getBuildApi(); + const webApi = await this.getWebApi(); + const client = await webApi.getBuildApi(); return client.getDefinitions(projectName, definitionName); } @@ -341,7 +417,8 @@ export class AzureDevOpsApi { `Calling Azure DevOps REST API, getting up to ${top} Builds for Repository Id ${repoId} for Project ${projectName}`, ); - const client = await this.webApi.getBuildApi(); + const webApi = await this.getWebApi(); + const client = await webApi.getBuildApi(); return client.getBuilds( projectName, definitions, @@ -421,75 +498,3 @@ export class AzureDevOpsApi { return { url, content }; } } - -export function mappedRepoBuild(build: Build): RepoBuild { - return { - id: build.id, - title: [build.definition?.name, build.buildNumber] - .filter(Boolean) - .join(' - '), - link: build._links?.web.href ?? '', - status: build.status ?? BuildStatus.None, - result: build.result ?? BuildResult.None, - queueTime: build.queueTime?.toISOString(), - startTime: build.startTime?.toISOString(), - finishTime: build.finishTime?.toISOString(), - source: `${build.sourceBranch} (${build.sourceVersion?.slice(0, 8)})`, - uniqueName: build.requestedFor?.uniqueName ?? 'N/A', - }; -} - -export function mappedGitTag( - gitRef: GitRef, - linkBaseUrl: string, - commitBaseUrl: string, -): GitTag { - return { - objectId: gitRef.objectId, - peeledObjectId: gitRef.peeledObjectId, - name: gitRef.name?.replace('refs/tags/', ''), - createdBy: gitRef.creator?.displayName ?? 'N/A', - link: `${linkBaseUrl}${encodeURIComponent( - gitRef.name?.replace('refs/tags/', '') ?? '', - )}`, - commitLink: `${commitBaseUrl}/${encodeURIComponent( - gitRef.peeledObjectId ?? '', - )}`, - }; -} - -export function mappedPullRequest( - pullRequest: GitPullRequest, - linkBaseUrl: string, -): PullRequest { - return { - pullRequestId: pullRequest.pullRequestId, - repoName: pullRequest.repository?.name, - title: pullRequest.title, - uniqueName: pullRequest.createdBy?.uniqueName ?? 'N/A', - createdBy: pullRequest.createdBy?.displayName ?? 'N/A', - creationDate: pullRequest.creationDate?.toISOString(), - sourceRefName: pullRequest.sourceRefName, - targetRefName: pullRequest.targetRefName, - status: pullRequest.status, - isDraft: pullRequest.isDraft, - link: `${linkBaseUrl}/${pullRequest.pullRequestId}`, - }; -} - -export function mappedBuildRun(build: Build): BuildRun { - return { - id: build.id, - title: [build.definition?.name, build.buildNumber] - .filter(Boolean) - .join(' - '), - link: build._links?.web.href ?? '', - status: build.status ?? BuildStatus.None, - result: build.result ?? BuildResult.None, - queueTime: build.queueTime?.toISOString(), - startTime: build.startTime?.toISOString(), - finishTime: build.finishTime?.toISOString(), - source: `${build.sourceBranch} (${build.sourceVersion?.slice(0, 8)})`, - uniqueName: build.requestedFor?.uniqueName ?? 'N/A', - }; -} diff --git a/plugins/azure-devops-backend/src/api/mappers.test.ts b/plugins/azure-devops-backend/src/api/mappers.test.ts new file mode 100644 index 0000000000..5f7fe5eb28 --- /dev/null +++ b/plugins/azure-devops-backend/src/api/mappers.test.ts @@ -0,0 +1,573 @@ +/* + * 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 { + Build, + DefinitionReference, +} from 'azure-devops-node-api/interfaces/BuildInterfaces'; +import { + BuildResult, + BuildStatus, + GitTag, + PullRequest, + PullRequestStatus, + RepoBuild, +} from '@backstage/plugin-azure-devops-common'; +import { + GitPullRequest, + GitRef, + GitRepository, +} from 'azure-devops-node-api/interfaces/GitInterfaces'; +import { + mappedBuildRun, + mappedGitTag, + mappedPullRequest, + mappedRepoBuild, +} from './mappers'; + +import { IdentityRef } from 'azure-devops-node-api/interfaces/common/VSSInterfaces'; + +describe('mappers', () => { + describe('mappedRepoBuild', () => { + describe('mappedRepoBuild happy path', () => { + it('should return RepoBuild from Build', () => { + const inputBuildDefinition: DefinitionReference = { + name: 'My Build Definition', + }; + + const inputLinks: any = { + web: { + href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + }, + }; + + const inputIdentityRef: IdentityRef = { + displayName: 'Jane Doe', + uniqueName: 'DOMAIN\\jdoe', + }; + + const inputBuild: Build = { + id: 1, + buildNumber: 'Build-1', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'refs/heads/develop', + sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', + definition: inputBuildDefinition, + _links: inputLinks, + requestedFor: inputIdentityRef, + }; + + const outputRepoBuild: RepoBuild = { + id: 1, + title: 'My Build Definition - Build-1', + link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'refs/heads/develop (f4f78b31)', + uniqueName: 'DOMAIN\\jdoe', + }; + + expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); + }); + }); + + describe('mappedRepoBuild with no Build definition name', () => { + it('should return RepoBuild with only Build Number for title', () => { + const inputLinks: any = { + web: { + href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + }, + }; + + const inputIdentityRef: IdentityRef = { + displayName: 'Jane Doe', + uniqueName: 'DOMAIN\\jdoe', + }; + + const inputBuild: Build = { + id: 1, + buildNumber: 'Build-1', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'refs/heads/develop', + sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', + definition: undefined, + _links: inputLinks, + requestedFor: inputIdentityRef, + }; + + const outputRepoBuild: RepoBuild = { + id: 1, + title: 'Build-1', + link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'refs/heads/develop (f4f78b31)', + uniqueName: 'DOMAIN\\jdoe', + }; + + expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); + }); + }); + + describe('mappedRepoBuild with undefined status', () => { + it('should return BuildStatus of None for status', () => { + const inputLinks: any = { + web: { + href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + }, + }; + + const inputIdentityRef: IdentityRef = { + displayName: 'Jane Doe', + uniqueName: 'DOMAIN\\jdoe', + }; + + const inputBuild: Build = { + id: 1, + buildNumber: 'Build-1', + status: undefined, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'refs/heads/develop', + sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', + definition: undefined, + _links: inputLinks, + requestedFor: inputIdentityRef, + }; + + const outputRepoBuild: RepoBuild = { + id: 1, + title: 'Build-1', + link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + status: BuildStatus.None, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'refs/heads/develop (f4f78b31)', + uniqueName: 'DOMAIN\\jdoe', + }; + + expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); + }); + }); + + describe('mappedRepoBuild with undefined result', () => { + it('should return BuildResult of None for result', () => { + const inputLinks: any = { + web: { + href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + }, + }; + + const inputIdentityRef: IdentityRef = { + displayName: 'Jane Doe', + uniqueName: 'DOMAIN\\jdoe', + }; + + const inputBuild: Build = { + id: 1, + buildNumber: 'Build-1', + status: BuildStatus.InProgress, + result: undefined, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'refs/heads/develop', + sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', + definition: undefined, + _links: inputLinks, + requestedFor: inputIdentityRef, + }; + + const outputRepoBuild: RepoBuild = { + id: 1, + title: 'Build-1', + link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + status: BuildStatus.InProgress, + result: BuildResult.None, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'refs/heads/develop (f4f78b31)', + uniqueName: 'DOMAIN\\jdoe', + }; + + expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); + }); + }); + + describe('mappedRepoBuild with undefined link', () => { + it('should return empty string for link', () => { + const inputIdentityRef: IdentityRef = { + displayName: 'Jane Doe', + uniqueName: 'DOMAIN\\jdoe', + }; + + const inputBuild: Build = { + id: 1, + buildNumber: 'Build-1', + status: BuildStatus.InProgress, + result: undefined, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'refs/heads/develop', + sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', + definition: undefined, + _links: undefined, + requestedFor: inputIdentityRef, + }; + + const outputRepoBuild: RepoBuild = { + id: 1, + title: 'Build-1', + link: '', + status: BuildStatus.InProgress, + result: BuildResult.None, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'refs/heads/develop (f4f78b31)', + uniqueName: 'DOMAIN\\jdoe', + }; + + expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); + }); + }); + }); + + describe('mappedGitTag', () => { + describe('mappedGitTag happy path', () => { + it('should return GitTag from GitRef', () => { + const inputIdentityRef: IdentityRef = { + displayName: 'Jane Doe', + }; + const inputGitRef: GitRef = { + name: 'refs/tags/v1.1.2', + creator: inputIdentityRef, + objectId: '1111aaaa2222bbbb3333cccc4444dddd5555eeee', + peeledObjectId: '1234567890abcdef1234567890abcdef12345678', + }; + const inputLinkBaseUrl = + 'https://host.com/myOrg/_git/super-feature-repo?version=GT'; + const inputCommitBaseUrl = + 'https://host.com/myOrg/_git/super-feature-repo/commit'; + const outputGitTag: GitTag = { + name: 'v1.1.2', + createdBy: 'Jane Doe', + commitLink: + 'https://host.com/myOrg/_git/super-feature-repo/commit/1234567890abcdef1234567890abcdef12345678', + objectId: '1111aaaa2222bbbb3333cccc4444dddd5555eeee', + peeledObjectId: '1234567890abcdef1234567890abcdef12345678', + link: 'https://host.com/myOrg/_git/super-feature-repo?version=GTv1.1.2', + }; + expect( + mappedGitTag(inputGitRef, inputLinkBaseUrl, inputCommitBaseUrl), + ).toEqual(outputGitTag); + }); + }); + }); + + describe('mappedPullRequest', () => { + describe('mappedPullRequest happy path', () => { + it('should return PullRequest from GitPullRequest', () => { + const inputGitRepository: GitRepository = { + name: 'super-feature-repo', + }; + + const inputIdentityRef: IdentityRef = { + displayName: 'Jane Doe', + uniqueName: 'DOMAIN\\jdoe', + }; + + const inputPullRequest: GitPullRequest = { + pullRequestId: 7181, + repository: inputGitRepository, + title: 'My Awesome New Feature', + createdBy: inputIdentityRef, + creationDate: new Date('2020-09-12T06:10:23.932Z'), + sourceRefName: 'refs/heads/topic/super-awesome-feature', + targetRefName: 'refs/heads/main', + status: PullRequestStatus.Active, + isDraft: false, + }; + + const inputBaseUrl = + 'https://host.com/myOrg/_git/super-feature-repo/pullrequest'; + + const outputPullRequest: PullRequest = { + pullRequestId: 7181, + repoName: 'super-feature-repo', + title: 'My Awesome New Feature', + uniqueName: 'DOMAIN\\jdoe', + createdBy: 'Jane Doe', + creationDate: '2020-09-12T06:10:23.932Z', + sourceRefName: 'refs/heads/topic/super-awesome-feature', + targetRefName: 'refs/heads/main', + status: PullRequestStatus.Active, + isDraft: false, + link: 'https://host.com/myOrg/_git/super-feature-repo/pullrequest/7181', + }; + + expect(mappedPullRequest(inputPullRequest, inputBaseUrl)).toEqual( + outputPullRequest, + ); + }); + }); + }); + + describe('mappedBuildRun', () => { + describe('mappedBuildRun happy path', () => { + it('should return RepoBuild from Build', () => { + const inputBuildDefinition: DefinitionReference = { + name: 'My Build Definition', + }; + + const inputLinks: any = { + web: { + href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + }, + }; + + const inputIdentityRef: IdentityRef = { + displayName: 'Jane Doe', + uniqueName: 'DOMAIN\\jdoe', + }; + + const inputBuild: Build = { + id: 1, + buildNumber: 'Build-1', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'refs/heads/develop', + sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', + definition: inputBuildDefinition, + _links: inputLinks, + requestedFor: inputIdentityRef, + }; + + const outputRepoBuild: RepoBuild = { + id: 1, + title: 'My Build Definition - Build-1', + link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'refs/heads/develop (f4f78b31)', + uniqueName: 'DOMAIN\\jdoe', + }; + + expect(mappedBuildRun(inputBuild)).toEqual(outputRepoBuild); + }); + }); + + describe('mappedBuildRun with no Build definition name', () => { + it('should return RepoBuild with only Build Number for title', () => { + const inputLinks: any = { + web: { + href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + }, + }; + + const inputIdentityRef: IdentityRef = { + displayName: 'Jane Doe', + uniqueName: 'DOMAIN\\jdoe', + }; + + const inputBuild: Build = { + id: 1, + buildNumber: 'Build-1', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'refs/heads/develop', + sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', + definition: undefined, + _links: inputLinks, + requestedFor: inputIdentityRef, + }; + + const outputRepoBuild: RepoBuild = { + id: 1, + title: 'Build-1', + link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + status: BuildStatus.Completed, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'refs/heads/develop (f4f78b31)', + uniqueName: 'DOMAIN\\jdoe', + }; + + expect(mappedBuildRun(inputBuild)).toEqual(outputRepoBuild); + }); + }); + + describe('mappedBuildRun with undefined status', () => { + it('should return BuildStatus of None for status', () => { + const inputLinks: any = { + web: { + href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + }, + }; + + const inputIdentityRef: IdentityRef = { + displayName: 'Jane Doe', + uniqueName: 'DOMAIN\\jdoe', + }; + + const inputBuild: Build = { + id: 1, + buildNumber: 'Build-1', + status: undefined, + result: BuildResult.Succeeded, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'refs/heads/develop', + sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', + definition: undefined, + _links: inputLinks, + requestedFor: inputIdentityRef, + }; + + const outputRepoBuild: RepoBuild = { + id: 1, + title: 'Build-1', + link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + status: BuildStatus.None, + result: BuildResult.Succeeded, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'refs/heads/develop (f4f78b31)', + uniqueName: 'DOMAIN\\jdoe', + }; + + expect(mappedBuildRun(inputBuild)).toEqual(outputRepoBuild); + }); + }); + + describe('mappedBuildRun with undefined result', () => { + it('should return BuildResult of None for result', () => { + const inputLinks: any = { + web: { + href: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + }, + }; + + const inputIdentityRef: IdentityRef = { + displayName: 'Jane Doe', + uniqueName: 'DOMAIN\\jdoe', + }; + + const inputBuild: Build = { + id: 1, + buildNumber: 'Build-1', + status: BuildStatus.InProgress, + result: undefined, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'refs/heads/develop', + sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', + definition: undefined, + _links: inputLinks, + requestedFor: inputIdentityRef, + }; + + const outputRepoBuild: RepoBuild = { + id: 1, + title: 'Build-1', + link: 'https://host.com/myOrg/0bcc0c0d-2d02/_build/results?buildId=1', + status: BuildStatus.InProgress, + result: BuildResult.None, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'refs/heads/develop (f4f78b31)', + uniqueName: 'DOMAIN\\jdoe', + }; + + expect(mappedBuildRun(inputBuild)).toEqual(outputRepoBuild); + }); + }); + + describe('mappedBuildRun with undefined link', () => { + it('should return empty string for link', () => { + const inputIdentityRef: IdentityRef = { + displayName: 'Jane Doe', + uniqueName: 'DOMAIN\\jdoe', + }; + + const inputBuild: Build = { + id: 1, + buildNumber: 'Build-1', + status: BuildStatus.InProgress, + result: undefined, + queueTime: new Date('2020-09-12T06:10:23.932Z'), + startTime: new Date('2020-09-12T06:15:23.932Z'), + finishTime: new Date('2020-09-12T06:20:23.932Z'), + sourceBranch: 'refs/heads/develop', + sourceVersion: 'f4f78b3100b2923982bdf60c89c57ce6fd2d9a1c', + definition: undefined, + _links: undefined, + requestedFor: inputIdentityRef, + }; + + const outputRepoBuild: RepoBuild = { + id: 1, + title: 'Build-1', + link: '', + status: BuildStatus.InProgress, + result: BuildResult.None, + queueTime: '2020-09-12T06:10:23.932Z', + startTime: '2020-09-12T06:15:23.932Z', + finishTime: '2020-09-12T06:20:23.932Z', + source: 'refs/heads/develop (f4f78b31)', + uniqueName: 'DOMAIN\\jdoe', + }; + + expect(mappedBuildRun(inputBuild)).toEqual(outputRepoBuild); + }); + }); + }); +}); diff --git a/plugins/azure-devops-backend/src/api/mappers.ts b/plugins/azure-devops-backend/src/api/mappers.ts new file mode 100644 index 0000000000..72097a25b8 --- /dev/null +++ b/plugins/azure-devops-backend/src/api/mappers.ts @@ -0,0 +1,101 @@ +/* + * 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. + */ + +import { + RepoBuild, + BuildStatus, + BuildResult, + GitTag, + PullRequest, + BuildRun, +} from '@backstage/plugin-azure-devops-common'; +import { Build } from 'azure-devops-node-api/interfaces/BuildInterfaces'; +import { + GitRef, + GitPullRequest, +} from 'azure-devops-node-api/interfaces/GitInterfaces'; + +export function mappedRepoBuild(build: Build): RepoBuild { + return { + id: build.id, + title: [build.definition?.name, build.buildNumber] + .filter(Boolean) + .join(' - '), + link: build._links?.web.href ?? '', + status: build.status ?? BuildStatus.None, + result: build.result ?? BuildResult.None, + queueTime: build.queueTime?.toISOString(), + startTime: build.startTime?.toISOString(), + finishTime: build.finishTime?.toISOString(), + source: `${build.sourceBranch} (${build.sourceVersion?.slice(0, 8)})`, + uniqueName: build.requestedFor?.uniqueName ?? 'N/A', + }; +} + +export function mappedGitTag( + gitRef: GitRef, + linkBaseUrl: string, + commitBaseUrl: string, +): GitTag { + return { + objectId: gitRef.objectId, + peeledObjectId: gitRef.peeledObjectId, + name: gitRef.name?.replace('refs/tags/', ''), + createdBy: gitRef.creator?.displayName ?? 'N/A', + link: `${linkBaseUrl}${encodeURIComponent( + gitRef.name?.replace('refs/tags/', '') ?? '', + )}`, + commitLink: `${commitBaseUrl}/${encodeURIComponent( + gitRef.peeledObjectId ?? '', + )}`, + }; +} + +export function mappedPullRequest( + pullRequest: GitPullRequest, + linkBaseUrl: string, +): PullRequest { + return { + pullRequestId: pullRequest.pullRequestId, + repoName: pullRequest.repository?.name, + title: pullRequest.title, + uniqueName: pullRequest.createdBy?.uniqueName ?? 'N/A', + createdBy: pullRequest.createdBy?.displayName ?? 'N/A', + creationDate: pullRequest.creationDate?.toISOString(), + sourceRefName: pullRequest.sourceRefName, + targetRefName: pullRequest.targetRefName, + status: pullRequest.status, + isDraft: pullRequest.isDraft, + link: `${linkBaseUrl}/${pullRequest.pullRequestId}`, + }; +} + +export function mappedBuildRun(build: Build): BuildRun { + return { + id: build.id, + title: [build.definition?.name, build.buildNumber] + .filter(Boolean) + .join(' - '), + link: build._links?.web.href ?? '', + status: build.status ?? BuildStatus.None, + result: build.result ?? BuildResult.None, + queueTime: build.queueTime?.toISOString(), + startTime: build.startTime?.toISOString(), + finishTime: build.finishTime?.toISOString(), + source: `${build.sourceBranch} (${build.sourceVersion?.slice(0, 8)})`, + uniqueName: build.requestedFor?.uniqueName ?? 'N/A', + }; +} diff --git a/plugins/azure-devops-backend/src/index.ts b/plugins/azure-devops-backend/src/index.ts index 3c802e7144..61cf7c7a6f 100644 --- a/plugins/azure-devops-backend/src/index.ts +++ b/plugins/azure-devops-backend/src/index.ts @@ -23,3 +23,4 @@ export { AzureDevOpsApi } from './api'; export * from './service/router'; export { azureDevOpsPlugin as default } from './plugin'; +export { AzureDevOpsAnnotatorProcessor } from './processor'; diff --git a/plugins/azure-devops-backend/src/processor/AzureDevOpsAnnotatorProcessor.test.ts b/plugins/azure-devops-backend/src/processor/AzureDevOpsAnnotatorProcessor.test.ts new file mode 100644 index 0000000000..dd83c56f70 --- /dev/null +++ b/plugins/azure-devops-backend/src/processor/AzureDevOpsAnnotatorProcessor.test.ts @@ -0,0 +1,271 @@ +/* + * 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. + */ +import { Entity } from '@backstage/catalog-model'; +import { ConfigReader } from '@backstage/config'; +import { AzureDevOpsAnnotatorProcessor } from './AzureDevOpsAnnotatorProcessor'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; + +describe('AzureDevOpsAnnotatorProcessor', () => { + it('adds annotation', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-component', + }, + }; + const location: LocationSpec = { + type: 'url', + target: + 'https://dev.azure.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml', + }; + + const processor = AzureDevOpsAnnotatorProcessor.fromConfig( + new ConfigReader({}), + ); + + expect(await processor.preProcessEntity(entity, location)).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-component', + annotations: { + 'dev.azure.com/host-org': 'dev.azure.com/organization', + 'dev.azure.com/project-repo': 'project/repository', + }, + }, + }); + }); + + it('adds annotation for Azure DevOps Server url', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-component', + }, + }; + const location: LocationSpec = { + type: 'url', + target: + 'https://example.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml', + }; + + const processor = AzureDevOpsAnnotatorProcessor.fromConfig( + new ConfigReader({ + integrations: { + azure: [ + { + host: 'example.com', + credentials: [ + { + personalAccessToken: 'pat', + }, + ], + }, + ], + }, + }), + ); + + expect(await processor.preProcessEntity(entity, location)).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-component', + annotations: { + 'dev.azure.com/host-org': 'example.com/organization', + 'dev.azure.com/project-repo': 'project/repository', + }, + }, + }); + }); + + it('adds annotation for TFS subpath url', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-component', + }, + }; + const location: LocationSpec = { + type: 'url', + target: + 'https://example.com/tfs/organization/project/_git/repository?path=%2Fcatalog-info.yaml', + }; + + const processor = AzureDevOpsAnnotatorProcessor.fromConfig( + new ConfigReader({ + integrations: { + azure: [ + { + host: 'example.com', + credentials: [ + { + personalAccessToken: 'pat', + }, + ], + }, + ], + }, + }), + ); + + expect(await processor.preProcessEntity(entity, location)).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-component', + annotations: { + 'dev.azure.com/host-org': 'example.com/tfs/organization', + 'dev.azure.com/project-repo': 'project/repository', + }, + }, + }); + }); + + it('does not override existing annotation', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-component', + annotations: { + 'dev.azure.com/host-org': 'myhost/myorg', + 'dev.azure.com/project-repo': 'myproj/myrepo', + }, + }, + }; + const location: LocationSpec = { + type: 'url', + target: + 'https://dev.azure.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml', + }; + + const processor = AzureDevOpsAnnotatorProcessor.fromConfig( + new ConfigReader({}), + ); + + expect(await processor.preProcessEntity(entity, location)).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-component', + annotations: { + 'dev.azure.com/host-org': 'myhost/myorg', + 'dev.azure.com/project-repo': 'myproj/myrepo', + }, + }, + }); + }); + + it('should not add annotation for other providers', async () => { + const entity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-component', + }, + }; + const location: LocationSpec = { + type: 'url', + target: + 'https://not-in-mock-config.example.com/backstage/backstage/-/blob/master/catalog-info.yaml', + }; + + const processor = AzureDevOpsAnnotatorProcessor.fromConfig( + new ConfigReader({}), + ); + + expect(await processor.preProcessEntity(entity, location)).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-component', + }, + }); + }); + + it('should only process applicable kinds', async () => { + const component: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-component', + }, + }; + + const api: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'API', + metadata: { + name: 'my-component', + }, + }; + + const system: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'System', + metadata: { + name: 'my-component', + }, + }; + + const location: LocationSpec = { + type: 'url', + target: + 'https://dev.azure.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml', + }; + + const processor = AzureDevOpsAnnotatorProcessor.fromConfig( + new ConfigReader({}), + { kinds: ['API', 'Component'] }, + ); + + expect(await processor.preProcessEntity(component, location)).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'my-component', + annotations: { + 'dev.azure.com/host-org': 'dev.azure.com/organization', + 'dev.azure.com/project-repo': 'project/repository', + }, + }, + }); + + expect(await processor.preProcessEntity(api, location)).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'API', + metadata: { + name: 'my-component', + annotations: { + 'dev.azure.com/host-org': 'dev.azure.com/organization', + 'dev.azure.com/project-repo': 'project/repository', + }, + }, + }); + + expect(await processor.preProcessEntity(system, location)).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'System', + metadata: { + name: 'my-component', + }, + }); + }); +}); diff --git a/plugins/azure-devops-backend/src/processor/AzureDevOpsAnnotatorProcessor.ts b/plugins/azure-devops-backend/src/processor/AzureDevOpsAnnotatorProcessor.ts new file mode 100644 index 0000000000..c27195b8ac --- /dev/null +++ b/plugins/azure-devops-backend/src/processor/AzureDevOpsAnnotatorProcessor.ts @@ -0,0 +1,127 @@ +/* + * 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. + */ + +import { Entity } from '@backstage/catalog-model'; +import { Config } from '@backstage/config'; +import { + ScmIntegrationRegistry, + ScmIntegrations, +} from '@backstage/integration'; +import { identity, merge, pickBy } from 'lodash'; +import { LocationSpec } from '@backstage/plugin-catalog-common'; +import { CatalogProcessor } from '@backstage/plugin-catalog-node'; +import { + AZURE_DEVOPS_HOST_ORG_ANNOTATION, + AZURE_DEVOPS_REPO_ANNOTATION, +} from '@backstage/plugin-azure-devops-common'; +import { parseAzureDevOpsUrl } from '../utils'; + +/** @public */ +export class AzureDevOpsAnnotatorProcessor implements CatalogProcessor { + constructor( + private readonly opts: { + scmIntegrationRegistry: ScmIntegrationRegistry; + kinds?: string[]; + }, + ) {} + + getProcessorName(): string { + return 'AzureDevOpsAnnotatorProcessor'; + } + + static fromConfig( + config: Config, + options?: { kinds?: string[] }, + ): AzureDevOpsAnnotatorProcessor { + return new AzureDevOpsAnnotatorProcessor({ + scmIntegrationRegistry: ScmIntegrations.fromConfig(config), + kinds: options?.kinds, + }); + } + + async preProcessEntity( + entity: Entity, + location: LocationSpec, + ): Promise { + const applicableKinds = (this.opts.kinds ?? ['Component']).map(k => + k.toLocaleLowerCase('en-US'), + ); + if ( + !applicableKinds.includes(entity.kind.toLocaleLowerCase('en-US')) || + location.type !== 'url' + ) { + return entity; + } + + const scmIntegration = this.opts.scmIntegrationRegistry.byUrl( + location.target, + ); + + if (!scmIntegration) { + return entity; + } + + if (scmIntegration.type !== 'azure') { + return entity; + } + + const { host, org, project, repo } = parseAzureDevOpsUrl(location.target); + + if (!org || !project || !repo) { + return entity; + } + + const hostOrgAnnotation = AZURE_DEVOPS_HOST_ORG_ANNOTATION; + let hostOrgValue = entity.metadata.annotations?.[hostOrgAnnotation]; + if (!hostOrgValue) { + hostOrgValue = `${host}/${org}`; + } + + const projectRepoAnnotation = AZURE_DEVOPS_REPO_ANNOTATION; + let projectRepoValue = entity.metadata.annotations?.[projectRepoAnnotation]; + if (!projectRepoValue) { + projectRepoValue = `${project}/${repo}`; + } + + const result = merge( + { + metadata: { + annotations: pickBy( + { + [hostOrgAnnotation]: hostOrgValue, + }, + identity, + ), + }, + }, + entity, + ); + + return merge( + { + metadata: { + annotations: pickBy( + { + [projectRepoAnnotation]: projectRepoValue, + }, + identity, + ), + }, + }, + result, + ); + } +} diff --git a/plugins/azure-devops-backend/src/processor/index.ts b/plugins/azure-devops-backend/src/processor/index.ts new file mode 100644 index 0000000000..46747c4802 --- /dev/null +++ b/plugins/azure-devops-backend/src/processor/index.ts @@ -0,0 +1,17 @@ +/* + * 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 { AzureDevOpsAnnotatorProcessor } from './AzureDevOpsAnnotatorProcessor'; diff --git a/plugins/azure-devops-backend/src/service/router.ts b/plugins/azure-devops-backend/src/service/router.ts index b6b8a6fdea..9fc762f1a7 100644 --- a/plugins/azure-devops-backend/src/service/router.ts +++ b/plugins/azure-devops-backend/src/service/router.ts @@ -19,7 +19,6 @@ import { PullRequestOptions, PullRequestStatus, } from '@backstage/plugin-azure-devops-common'; -import { WebApi, getPersonalAccessTokenHandler } from 'azure-devops-node-api'; import { AzureDevOpsApi } from '../api'; import { Config } from '@backstage/config'; @@ -43,18 +42,11 @@ export interface RouterOptions { export async function createRouter( options: RouterOptions, ): Promise { - const { logger, reader } = options; - const config = options.config.getConfig('azureDevOps'); - - const token = config.getString('token'); - const host = config.getString('host'); - const organization = config.getString('organization'); - - const authHandler = getPersonalAccessTokenHandler(token); - const webApi = new WebApi(`https://${host}/${organization}`, authHandler); + const { logger, reader, config } = options; const azureDevOpsApi = - options.azureDevOpsApi || new AzureDevOpsApi(logger, webApi, reader); + options.azureDevOpsApi || + AzureDevOpsApi.fromConfig(config, { logger, urlReader: reader }); const pullRequestsDashboardProvider = await PullRequestsDashboardProvider.create(logger, azureDevOpsApi); @@ -195,6 +187,8 @@ export async function createRouter( }); router.get('/readme/:projectName/:repoName', async (req, res) => { + const host = config.getString('azureDevOps.host'); + const organization = config.getString('azureDevOps.organization'); const { projectName, repoName } = req.params; const readme = await azureDevOpsApi.getReadme( host, diff --git a/plugins/azure-devops-backend/src/utils/azure-devops-utils.test.ts b/plugins/azure-devops-backend/src/utils/azure-devops-utils.test.ts index 427980be14..86a06b7b0b 100644 --- a/plugins/azure-devops-backend/src/utils/azure-devops-utils.test.ts +++ b/plugins/azure-devops-backend/src/utils/azure-devops-utils.test.ts @@ -28,6 +28,7 @@ import { getPullRequestLink, replaceReadme, buildEncodedUrl, + parseAzureDevOpsUrl, } from './azure-devops-utils'; import { GitPullRequest } from 'azure-devops-node-api/interfaces/GitInterfaces'; import { UrlReader } from '@backstage/backend-common'; @@ -295,3 +296,38 @@ describe('buildEncodedUrl', () => { ); }); }); + +describe('parseAzureDevOpsUrl', () => { + it('parses Azure DevOps Cloud url', async () => { + const result = parseAzureDevOpsUrl( + 'https://dev.azure.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml', + ); + + expect(result.host).toEqual('dev.azure.com'); + expect(result.org).toEqual('organization'); + expect(result.project).toEqual('project'); + expect(result.repo).toEqual('repository'); + }); + + it('parses Azure DevOps Server url', async () => { + const result = parseAzureDevOpsUrl( + 'https://server.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml', + ); + + expect(result.host).toEqual('server.com'); + expect(result.org).toEqual('organization'); + expect(result.project).toEqual('project'); + expect(result.repo).toEqual('repository'); + }); + + it('parses TFS subpath Url', async () => { + const result = parseAzureDevOpsUrl( + 'https://server.com/tfs/organization/project/_git/repository?path=%2Fcatalog-info.yaml', + ); + + expect(result.host).toEqual('server.com/tfs'); + expect(result.org).toEqual('organization'); + expect(result.project).toEqual('project'); + expect(result.repo).toEqual('repository'); + }); +}); diff --git a/plugins/azure-devops-backend/src/utils/azure-devops-utils.ts b/plugins/azure-devops-backend/src/utils/azure-devops-utils.ts index aa946e7a74..7f5bf39ac4 100644 --- a/plugins/azure-devops-backend/src/utils/azure-devops-utils.ts +++ b/plugins/azure-devops-backend/src/utils/azure-devops-utils.ts @@ -328,3 +328,29 @@ export function extractPartsFromAsset(content: string): { path: path.startsWith('.') ? path.substring(1, path.length) : path, }; } + +export function parseAzureDevOpsUrl(sourceUrl: string) { + const url = new URL(sourceUrl); + + let host = url.host; + let org; + let project; + let repo; + + const parts = url.pathname.split('/').map(part => decodeURIComponent(part)); + if (parts[2] === '_git') { + org = parts[1]; + project = repo = parts[3]; + } else if (parts[3] === '_git') { + org = parts[1]; + project = parts[2]; + repo = parts[4]; + } else if (parts[4] === '_git') { + host = `${host}/${parts[1]}`; + org = parts[2]; + project = parts[3]; + repo = parts[5]; + } + + return { host, org, project, repo }; +} diff --git a/plugins/azure-devops-common/CHANGELOG.md b/plugins/azure-devops-common/CHANGELOG.md index e5637a9ff4..5ad70d8832 100644 --- a/plugins/azure-devops-common/CHANGELOG.md +++ b/plugins/azure-devops-common/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-azure-devops-common +## 0.3.2-next.0 + +### Patch Changes + +- 043b724c56: Introduced new `AzureDevOpsAnnotatorProcessor` that adds the needed annotations automatically. Also, moved constants to common package so they can be shared more easily + ## 0.3.1 ### Patch Changes diff --git a/plugins/azure-devops-common/api-report.md b/plugins/azure-devops-common/api-report.md index ea9f7130c0..262d5c8136 100644 --- a/plugins/azure-devops-common/api-report.md +++ b/plugins/azure-devops-common/api-report.md @@ -3,6 +3,22 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +// @public (undocumented) +export const AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION = + 'dev.azure.com/build-definition'; + +// @public (undocumented) +export const AZURE_DEVOPS_DEFAULT_TOP: number; + +// @public (undocumented) +export const AZURE_DEVOPS_HOST_ORG_ANNOTATION = 'dev.azure.com/host-org'; + +// @public (undocumented) +export const AZURE_DEVOPS_PROJECT_ANNOTATION = 'dev.azure.com/project'; + +// @public (undocumented) +export const AZURE_DEVOPS_REPO_ANNOTATION = 'dev.azure.com/project-repo'; + // @public (undocumented) export enum BuildResult { Canceled = 32, diff --git a/plugins/azure-devops-common/package.json b/plugins/azure-devops-common/package.json index 7648e39539..f2bbe449ff 100644 --- a/plugins/azure-devops-common/package.json +++ b/plugins/azure-devops-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops-common", - "version": "0.3.1", + "version": "0.3.2-next.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops/src/constants.ts b/plugins/azure-devops-common/src/constants.ts similarity index 92% rename from plugins/azure-devops/src/constants.ts rename to plugins/azure-devops-common/src/constants.ts index aba0ec093a..5cc6b54592 100644 --- a/plugins/azure-devops/src/constants.ts +++ b/plugins/azure-devops-common/src/constants.ts @@ -14,9 +14,14 @@ * limitations under the License. */ +/** @public */ export const AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION = 'dev.azure.com/build-definition'; +/** @public */ export const AZURE_DEVOPS_HOST_ORG_ANNOTATION = 'dev.azure.com/host-org'; +/** @public */ export const AZURE_DEVOPS_PROJECT_ANNOTATION = 'dev.azure.com/project'; +/** @public */ export const AZURE_DEVOPS_REPO_ANNOTATION = 'dev.azure.com/project-repo'; +/** @public */ export const AZURE_DEVOPS_DEFAULT_TOP: number = 10; diff --git a/plugins/azure-devops-common/src/index.ts b/plugins/azure-devops-common/src/index.ts index 26a854de89..9a4a007317 100644 --- a/plugins/azure-devops-common/src/index.ts +++ b/plugins/azure-devops-common/src/index.ts @@ -15,3 +15,4 @@ */ export * from './types'; +export * from './constants'; diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index dfe161831b..664b581b0a 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-azure-devops +## 0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-azure-devops-common@0.3.2-next.0 + +## 0.3.10-next.1 + +### Patch Changes + +- 043b724c56: Introduced new `AzureDevOpsAnnotatorProcessor` that adds the needed annotations automatically. Also, moved constants to common package so they can be shared more easily +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-azure-devops-common@0.3.2-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.3.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-azure-devops-common@0.3.1 + ## 0.3.8 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index 94b4d6486f..d57031cd13 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-devops", - "version": "0.3.8", + "version": "0.3.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops/src/hooks/useBuildRuns.ts b/plugins/azure-devops/src/hooks/useBuildRuns.ts index 2b70ea63a5..0c10dc8db8 100644 --- a/plugins/azure-devops/src/hooks/useBuildRuns.ts +++ b/plugins/azure-devops/src/hooks/useBuildRuns.ts @@ -15,11 +15,11 @@ */ import { + AZURE_DEVOPS_DEFAULT_TOP, BuildRun, BuildRunOptions, } from '@backstage/plugin-azure-devops-common'; -import { AZURE_DEVOPS_DEFAULT_TOP } from '../constants'; import { azureDevOpsApiRef } from '../api'; import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; diff --git a/plugins/azure-devops/src/hooks/usePullRequests.ts b/plugins/azure-devops/src/hooks/usePullRequests.ts index de886919eb..1ac6afae24 100644 --- a/plugins/azure-devops/src/hooks/usePullRequests.ts +++ b/plugins/azure-devops/src/hooks/usePullRequests.ts @@ -15,12 +15,12 @@ */ import { + AZURE_DEVOPS_DEFAULT_TOP, PullRequest, PullRequestOptions, PullRequestStatus, } from '@backstage/plugin-azure-devops-common'; -import { AZURE_DEVOPS_DEFAULT_TOP } from '../constants'; import { Entity } from '@backstage/catalog-model'; import { azureDevOpsApiRef } from '../api'; import { useApi } from '@backstage/core-plugin-api'; diff --git a/plugins/azure-devops/src/plugin.ts b/plugins/azure-devops/src/plugin.ts index 4dd423f35a..1e76c9e53a 100644 --- a/plugins/azure-devops/src/plugin.ts +++ b/plugins/azure-devops/src/plugin.ts @@ -14,11 +14,6 @@ * limitations under the License. */ -import { - AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION, - AZURE_DEVOPS_PROJECT_ANNOTATION, - AZURE_DEVOPS_REPO_ANNOTATION, -} from './constants'; import { azurePipelinesEntityContentRouteRef, azurePullRequestDashboardRouteRef, @@ -37,6 +32,11 @@ import { import { AzureDevOpsClient } from './api/AzureDevOpsClient'; import { Entity } from '@backstage/catalog-model'; import { azureDevOpsApiRef } from './api/AzureDevOpsApi'; +import { + AZURE_DEVOPS_REPO_ANNOTATION, + AZURE_DEVOPS_PROJECT_ANNOTATION, + AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION, +} from '@backstage/plugin-azure-devops-common'; /** @public */ export const isAzureDevOpsAvailable = (entity: Entity) => diff --git a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts index 9feec8bf95..dec140706c 100644 --- a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts +++ b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts @@ -14,14 +14,13 @@ * limitations under the License. */ -import { - AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION, - AZURE_DEVOPS_HOST_ORG_ANNOTATION, - AZURE_DEVOPS_PROJECT_ANNOTATION, - AZURE_DEVOPS_REPO_ANNOTATION, -} from '../constants'; - import { Entity } from '@backstage/catalog-model'; +import { + AZURE_DEVOPS_PROJECT_ANNOTATION, + AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION, + AZURE_DEVOPS_REPO_ANNOTATION, + AZURE_DEVOPS_HOST_ORG_ANNOTATION, +} from '@backstage/plugin-azure-devops-common'; export function getAnnotationValuesFromEntity(entity: Entity): { project: string; diff --git a/plugins/azure-sites-backend/CHANGELOG.md b/plugins/azure-sites-backend/CHANGELOG.md index b86436939d..92a1b3fb7b 100644 --- a/plugins/azure-sites-backend/CHANGELOG.md +++ b/plugins/azure-sites-backend/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-azure-sites-backend +## 0.1.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-sites-common@0.1.1 + +## 0.1.18-next.1 + +### Patch Changes + +- 99fb54183b: Updated dependency `@azure/identity` to `^4.0.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-sites-common@0.1.1 + +## 0.1.18-next.0 + +### Patch Changes + +- b7a13edf6d: Updated dependency `@azure/arm-appservice` to `^14.0.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-sites-common@0.1.1 + ## 0.1.17 ### Patch Changes diff --git a/plugins/azure-sites-backend/package.json b/plugins/azure-sites-backend/package.json index f08485055b..e8537b1444 100644 --- a/plugins/azure-sites-backend/package.json +++ b/plugins/azure-sites-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites-backend", - "version": "0.1.17", + "version": "0.1.18-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,9 +32,9 @@ "postpack": "backstage-cli package postpack" }, "dependencies": { - "@azure/arm-appservice": "^13.0.1", + "@azure/arm-appservice": "^14.0.0", "@azure/arm-resourcegraph": "^4.2.1", - "@azure/identity": "^3.2.1", + "@azure/identity": "^4.0.0", "@backstage/backend-common": "workspace:^", "@backstage/config": "workspace:^", "@backstage/plugin-azure-sites-common": "workspace:^", diff --git a/plugins/azure-sites/CHANGELOG.md b/plugins/azure-sites/CHANGELOG.md index 3432c026c9..05fd572694 100644 --- a/plugins/azure-sites/CHANGELOG.md +++ b/plugins/azure-sites/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-azure-sites +## 0.1.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-azure-sites-common@0.1.1 + +## 0.1.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-azure-sites-common@0.1.1 + +## 0.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-azure-sites-common@0.1.1 + ## 0.1.15 ### Patch Changes diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index 7822e0d3e0..0dc57d2c5c 100644 --- a/plugins/azure-sites/package.json +++ b/plugins/azure-sites/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-azure-sites", - "version": "0.1.15", + "version": "0.1.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx b/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx index 16321cd464..44f5f1697d 100644 --- a/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx +++ b/plugins/azure-sites/src/components/AzureSitesOverviewTableComponent/AzureSitesOverviewTable.tsx @@ -39,7 +39,6 @@ import OpenInNewIcon from '@material-ui/icons/OpenInNew'; import { DateTime } from 'luxon'; import { useApi } from '@backstage/core-plugin-api'; import { azureSiteApiRef } from '../../api'; -import { BackstageTheme } from '@backstage/theme'; type States = 'Waiting' | 'Running' | 'Paused' | 'Failed' | 'Stopped'; type Kinds = 'app' | 'functionapp'; @@ -50,7 +49,7 @@ const State = ({ value }: { value: States }) => { common: { black }, status: { ok, error }, }, - } = useTheme(); + } = useTheme(); const colorMap = { Waiting: '#dcbc21', diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index 6d4fb37b15..f384f40148 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-badges-backend +## 0.3.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## 0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.3.4 ### Patch Changes diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index e7f13cf414..74f615a36e 100644 --- a/plugins/badges-backend/package.json +++ b/plugins/badges-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges-backend", "description": "A Backstage backend plugin that generates README badges for your entities", - "version": "0.3.4", + "version": "0.3.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index 58bc0f1e0d..4db9d9b3df 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-badges +## 0.2.52-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.2.52-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.2.52-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.2.50 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index 681f5e5189..297bedda13 100644 --- a/plugins/badges/package.json +++ b/plugins/badges/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-badges", "description": "A Backstage plugin that generates README badges for your entities", - "version": "0.2.50", + "version": "0.2.52-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md index f2fdf4a195..c77f40773d 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-bazaar-backend +## 0.3.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## 0.3.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.3.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.3.5 ### Patch Changes diff --git a/plugins/bazaar-backend/alpha-api-report.md b/plugins/bazaar-backend/api-report-alpha.md similarity index 100% rename from plugins/bazaar-backend/alpha-api-report.md rename to plugins/bazaar-backend/api-report-alpha.md diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index 74bc9b5f0a..a98723d2fc 100644 --- a/plugins/bazaar-backend/package.json +++ b/plugins/bazaar-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar-backend", - "version": "0.3.5", + "version": "0.3.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index c170e0a638..890970ab42 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,53 @@ # @backstage/plugin-bazaar +## 0.2.20-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.2.20-next.2 + +### Patch Changes + +- 5d796829bb: Internalize 'AboutField' to break catalog dependency +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.2.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.16.0-next.1 + +## 0.2.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-catalog@1.16.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.2.18 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index c43db667fa..f0d50a38a0 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.2.18", + "version": "0.2.20-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,7 +34,6 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", - "@backstage/plugin-catalog": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@backstage/theme": "workspace:^", "@date-io/luxon": "1.x", diff --git a/plugins/bazaar/src/components/CardContentFields/AboutField.tsx b/plugins/bazaar/src/components/CardContentFields/AboutField.tsx new file mode 100644 index 0000000000..e8c49bf4d7 --- /dev/null +++ b/plugins/bazaar/src/components/CardContentFields/AboutField.tsx @@ -0,0 +1,72 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { useElementFilter } from '@backstage/core-plugin-api'; +import { Grid, makeStyles, Typography } from '@material-ui/core'; +import React from 'react'; + +const useStyles = makeStyles(theme => ({ + value: { + fontWeight: 'bold', + overflow: 'hidden', + lineHeight: '24px', + wordBreak: 'break-word', + }, + label: { + color: theme.palette.text.secondary, + textTransform: 'uppercase', + fontSize: '10px', + fontWeight: 'bold', + letterSpacing: 0.5, + overflow: 'hidden', + whiteSpace: 'nowrap', + }, +})); + +/** + * Props for {@link AboutField}. + */ +export interface AboutFieldProps { + label: string; + value?: string; + gridSizes?: Record; + children?: React.ReactNode; +} + +export function AboutField(props: AboutFieldProps) { + const { label, value, gridSizes, children } = props; + const classes = useStyles(); + + const childElements = useElementFilter(children, c => c.getElements()); + + // Content is either children or a string prop `value` + const content = + childElements.length > 0 ? ( + childElements + ) : ( + + {value || `unknown`} + + ); + return ( + + + {label} + + {content} + + ); +} diff --git a/plugins/bazaar/src/components/CardContentFields/CardContentFields.tsx b/plugins/bazaar/src/components/CardContentFields/CardContentFields.tsx index 82ab9df89d..f252efebee 100644 --- a/plugins/bazaar/src/components/CardContentFields/CardContentFields.tsx +++ b/plugins/bazaar/src/components/CardContentFields/CardContentFields.tsx @@ -25,8 +25,8 @@ import { import { parseEntityRef } from '@backstage/catalog-model'; import { Avatar, Link } from '@backstage/core-components'; import { useRouteRef } from '@backstage/core-plugin-api'; -import { AboutField } from '@backstage/plugin-catalog'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; +import { AboutField } from './AboutField'; import { StatusTag } from '../StatusTag'; import { Member, BazaarProject } from '../../types'; diff --git a/plugins/bitbucket-cloud-common/CHANGELOG.md b/plugins/bitbucket-cloud-common/CHANGELOG.md index 347b8c8977..12d38ed830 100644 --- a/plugins/bitbucket-cloud-common/CHANGELOG.md +++ b/plugins/bitbucket-cloud-common/CHANGELOG.md @@ -1,5 +1,20 @@ # @backstage/plugin-bitbucket-cloud-common +## 0.2.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + +## 0.2.15-next.0 + +### Patch Changes + +- acf93904e7: Updated dependency `ts-morph` to `^20.0.0`. +- Updated dependencies + - @backstage/integration@1.8.0-next.0 + ## 0.2.14 ### Patch Changes diff --git a/plugins/bitbucket-cloud-common/package.json b/plugins/bitbucket-cloud-common/package.json index fe4f51c957..5525510d5e 100644 --- a/plugins/bitbucket-cloud-common/package.json +++ b/plugins/bitbucket-cloud-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitbucket-cloud-common", "description": "Common functionalities for bitbucket-cloud plugins", - "version": "0.2.14", + "version": "0.2.15-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index 9e0b617eee..0dc0ea417d 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-bitrise +## 0.1.55-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.1.55-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.1.55-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.1.53 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index 7617a2b9b1..f5a2ad5158 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitrise", "description": "A Backstage plugin that integrates towards Bitrise", - "version": "0.1.53", + "version": "0.1.55-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index 157d9ac2e8..b2be9f907b 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,60 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.3.2-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + +## 0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.3.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-kubernetes-common@0.7.2-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + ## 0.3.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/alpha-api-report.md b/plugins/catalog-backend-module-aws/api-report-alpha.md similarity index 100% rename from plugins/catalog-backend-module-aws/alpha-api-report.md rename to plugins/catalog-backend-module-aws/api-report-alpha.md diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 8a7d792a12..88da2472a4 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-aws", "description": "A Backstage catalog backend module that helps integrate towards AWS", - "version": "0.3.1", + "version": "0.3.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.ts b/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.ts index 521d61d3d8..e7816ae12f 100644 --- a/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.ts +++ b/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.ts @@ -29,7 +29,7 @@ import { AwsS3EntityProvider } from '../providers'; */ export const catalogModuleAwsS3EntityProvider = createBackendModule({ pluginId: 'catalog', - moduleId: 'awsS3EntityProvider', + moduleId: 'aws-s3-entity-provider', register(env) { env.registerInit({ deps: { diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index 1cd4019d69..c2df3d355d 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,54 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.1.27-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## 0.1.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.1.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + ## 0.1.26 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/alpha-api-report.md b/plugins/catalog-backend-module-azure/api-report-alpha.md similarity index 100% rename from plugins/catalog-backend-module-azure/alpha-api-report.md rename to plugins/catalog-backend-module-azure/api-report-alpha.md diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index 93abf22151..31778ef43d 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-azure", "description": "A Backstage catalog backend module that helps integrate towards Azure", - "version": "0.1.26", + "version": "0.1.27-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.ts b/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.ts index 804c0d4712..b9c55041b3 100644 --- a/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.ts +++ b/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.ts @@ -29,7 +29,7 @@ import { AzureDevOpsEntityProvider } from '../providers'; */ export const catalogModuleAzureDevOpsEntityProvider = createBackendModule({ pluginId: 'catalog', - moduleId: 'azureDevOpsEntityProvider', + moduleId: 'azure-dev-ops-entity-provider', register(env) { env.registerInit({ deps: { diff --git a/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md b/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md index 31ebb1edb0..274b0a243d 100644 --- a/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-catalog-backend-module-backstage-openapi +## 0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-openapi-utils@0.1.1-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## 0.1.1-next.1 + +### Patch Changes + +- eb44e92898: Support authenticated backends +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-openapi-utils@0.1.1-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-openapi-utils@0.1.1-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.1.0 ### Minor Changes diff --git a/plugins/catalog-backend-module-backstage-openapi/package.json b/plugins/catalog-backend-module-backstage-openapi/package.json index ad6c2d01b5..6d2b058182 100644 --- a/plugins/catalog-backend-module-backstage-openapi/package.json +++ b/plugins/catalog-backend-module-backstage-openapi/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-backstage-openapi", - "version": "0.1.0", + "version": "0.1.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-backstage-openapi/src/InternalOpenApiDocumentationProvider.ts b/plugins/catalog-backend-module-backstage-openapi/src/InternalOpenApiDocumentationProvider.ts index 33c461d95a..a8782e5eea 100644 --- a/plugins/catalog-backend-module-backstage-openapi/src/InternalOpenApiDocumentationProvider.ts +++ b/plugins/catalog-backend-module-backstage-openapi/src/InternalOpenApiDocumentationProvider.ts @@ -25,6 +25,7 @@ import { EntityProviderConnection, } from '@backstage/plugin-catalog-node'; import { merge, isErrorResult } from 'openapi-merge'; +import { TokenManager } from '@backstage/backend-common'; import { getOpenApiSpecRoute } from '@backstage/backend-openapi-utils'; import type { OpenAPIObject, @@ -107,17 +108,25 @@ const loadSpecs = async ({ discovery, plugins, logger, + tokenManager, }: { baseUrl: string; plugins: string[]; discovery: DiscoveryService; logger: LoggerService; + tokenManager: TokenManager; }) => { const specs: OpenAPIObject[] = []; for (const pluginId of plugins) { const url = await discovery.getExternalBaseUrl(pluginId); const openApiUrl = getOpenApiSpecRoute(url); - const response = await fetch(openApiUrl); + const { token } = await tokenManager.getToken(); + const response = await fetch(openApiUrl, { + method: 'GET', + headers: { + Authorization: `Bearer ${token}`, + }, + }); if (response.ok) { const spec = await response.json(); addTagsToSpec(spec, pluginId); @@ -144,6 +153,7 @@ export class InternalOpenApiDocumentationProvider implements EntityProvider { public readonly config: Config, public readonly discovery: DiscoveryService, public readonly logger: LoggerService, + public readonly tokenManager: TokenManager, taskRunner: TaskRunner, ) { this.scheduleFn = this.createScheduleFn(taskRunner); @@ -155,6 +165,7 @@ export class InternalOpenApiDocumentationProvider implements EntityProvider { discovery: DiscoveryService; logger: LoggerService; schedule: PluginTaskScheduler; + tokenManager: TokenManager; }, ) { const taskRunner = options.schedule.createScheduledTaskRunner({ @@ -169,6 +180,7 @@ export class InternalOpenApiDocumentationProvider implements EntityProvider { config, options.discovery, options.logger, + options.tokenManager, taskRunner, ); } @@ -231,6 +243,7 @@ export class InternalOpenApiDocumentationProvider implements EntityProvider { await loadSpecs({ baseUrl: this.config.getString('backend.baseUrl'), discovery: this.discovery, + tokenManager: this.tokenManager, plugins: pluginsToMerge, logger, }), diff --git a/plugins/catalog-backend-module-backstage-openapi/src/index.ts b/plugins/catalog-backend-module-backstage-openapi/src/index.ts index 226442666c..ac425afaf2 100644 --- a/plugins/catalog-backend-module-backstage-openapi/src/index.ts +++ b/plugins/catalog-backend-module-backstage-openapi/src/index.ts @@ -44,13 +44,22 @@ export const catalogModuleInternalOpenApiSpec = createBackendModule({ discovery: coreServices.discovery, scheduler: coreServices.scheduler, logger: coreServices.logger, + tokenManager: coreServices.tokenManager, }, - async init({ catalog, config, discovery, scheduler, logger }) { + async init({ + catalog, + config, + discovery, + scheduler, + logger, + tokenManager, + }) { catalog.addEntityProvider( InternalOpenApiDocumentationProvider.fromConfig(config, { discovery, schedule: scheduler, logger, + tokenManager, }), ); }, diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index 75da10526b..933646cc0b 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,57 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.1.23-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.15-next.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-events-node@0.2.17-next.2 + +## 0.1.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.15-next.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## 0.1.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.15-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-events-node@0.2.17-next.0 + ## 0.1.22 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/alpha-api-report.md b/plugins/catalog-backend-module-bitbucket-cloud/api-report-alpha.md similarity index 100% rename from plugins/catalog-backend-module-bitbucket-cloud/alpha-api-report.md rename to plugins/catalog-backend-module-bitbucket-cloud/api-report-alpha.md diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 5d296a3f4f..15c9af2e10 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", - "version": "0.1.22", + "version": "0.1.23-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.ts index e5e1ad1609..39265dc1a5 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.ts +++ b/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.ts @@ -31,7 +31,7 @@ import { BitbucketCloudEntityProvider } from '../providers/BitbucketCloudEntityP */ export const catalogModuleBitbucketCloudEntityProvider = createBackendModule({ pluginId: 'catalog', - moduleId: 'bitbucketCloudEntityProvider', + moduleId: 'bitbucket-cloud-entity-provider', register(env) { env.registerInit({ deps: { diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index b09d8db65c..b91d501796 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.1.21-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + +## 0.1.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.1.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.1.20 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/alpha-api-report.md b/plugins/catalog-backend-module-bitbucket-server/api-report-alpha.md similarity index 100% rename from plugins/catalog-backend-module-bitbucket-server/alpha-api-report.md rename to plugins/catalog-backend-module-bitbucket-server/api-report-alpha.md diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index d671ea8da0..743c99dba3 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-server", - "version": "0.1.20", + "version": "0.1.21-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.ts b/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.ts index ef71df9b06..dd2a423cdc 100644 --- a/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.ts +++ b/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.ts @@ -27,7 +27,7 @@ import { BitbucketServerEntityProvider } from '../providers'; */ export const catalogModuleBitbucketServerEntityProvider = createBackendModule({ pluginId: 'catalog', - moduleId: 'bitbucketServerEntityProvider', + moduleId: 'bitbucket-server-entity-provider', register(env) { env.registerInit({ deps: { diff --git a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md index 96983f5347..0f03b82750 100644 --- a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/plugin-catalog-backend-module-bitbucket +## 0.2.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.15-next.1 + +## 0.2.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.15-next.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.2.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.15-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.2.22 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket/package.json b/plugins/catalog-backend-module-bitbucket/package.json index 186b2aa111..44b17b1059 100644 --- a/plugins/catalog-backend-module-bitbucket/package.json +++ b/plugins/catalog-backend-module-bitbucket/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket", - "version": "0.2.22", + "version": "0.2.23-next.2", "deprecated": true, "main": "src/index.ts", "types": "src/index.ts", diff --git a/plugins/catalog-backend-module-gcp/CHANGELOG.md b/plugins/catalog-backend-module-gcp/CHANGELOG.md index e11852f811..2154ebcc71 100644 --- a/plugins/catalog-backend-module-gcp/CHANGELOG.md +++ b/plugins/catalog-backend-module-gcp/CHANGELOG.md @@ -1,5 +1,46 @@ # @backstage/plugin-catalog-backend-module-gcp +## 0.1.8-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + +## 0.1.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.1.8-next.0 + +### Patch Changes + +- 42c1aee741: Updated dependency `@google-cloud/container` to `^5.0.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-kubernetes-common@0.7.2-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + ## 0.1.7 ### Patch Changes diff --git a/plugins/catalog-backend-module-gcp/alpha-api-report.md b/plugins/catalog-backend-module-gcp/api-report-alpha.md similarity index 100% rename from plugins/catalog-backend-module-gcp/alpha-api-report.md rename to plugins/catalog-backend-module-gcp/api-report-alpha.md diff --git a/plugins/catalog-backend-module-gcp/package.json b/plugins/catalog-backend-module-gcp/package.json index 4a66efe77d..d788957128 100644 --- a/plugins/catalog-backend-module-gcp/package.json +++ b/plugins/catalog-backend-module-gcp/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gcp", "description": "A Backstage catalog backend module that helps integrate towards GCP", - "version": "0.1.7", + "version": "0.1.8-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -52,7 +52,7 @@ "@backstage/config": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", "@backstage/plugin-kubernetes-common": "workspace:^", - "@google-cloud/container": "^4.15.0", + "@google-cloud/container": "^5.0.0", "winston": "^3.2.1" }, "devDependencies": { diff --git a/plugins/catalog-backend-module-gcp/src/module/catalogModuleGcpGkeEntityProvider.ts b/plugins/catalog-backend-module-gcp/src/module/catalogModuleGcpGkeEntityProvider.ts index 7f93bddbfe..acc216e1f6 100644 --- a/plugins/catalog-backend-module-gcp/src/module/catalogModuleGcpGkeEntityProvider.ts +++ b/plugins/catalog-backend-module-gcp/src/module/catalogModuleGcpGkeEntityProvider.ts @@ -29,7 +29,7 @@ import { GkeEntityProvider } from '../providers/GkeEntityProvider'; */ export const catalogModuleGcpGkeEntityProvider = createBackendModule({ pluginId: 'catalog', - moduleId: 'gcpGkeEntityProvider', + moduleId: 'gcp-gke-entity-provider', register(env) { env.registerInit({ deps: { diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index f6b06b1907..3bd9863e48 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.1.24-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + +## 0.1.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.1.24-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.1.23 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/alpha-api-report.md b/plugins/catalog-backend-module-gerrit/api-report-alpha.md similarity index 100% rename from plugins/catalog-backend-module-gerrit/alpha-api-report.md rename to plugins/catalog-backend-module-gerrit/api-report-alpha.md diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index 21aac3b4eb..57d53211de 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gerrit", - "version": "0.1.23", + "version": "0.1.24-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.ts b/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.ts index bb29ce6eef..af870d095f 100644 --- a/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.ts +++ b/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.ts @@ -27,7 +27,7 @@ import { GerritEntityProvider } from '../providers/GerritEntityProvider'; */ export const catalogModuleGerritEntityProvider = createBackendModule({ pluginId: 'catalog', - moduleId: 'gerritEntityProvider', + moduleId: 'gerrit-entity-provider', register(env) { env.registerInit({ deps: { diff --git a/plugins/catalog-backend-module-github-org/CHANGELOG.md b/plugins/catalog-backend-module-github-org/CHANGELOG.md index cb5d4d244f..5cb7ba5a44 100644 --- a/plugins/catalog-backend-module-github-org/CHANGELOG.md +++ b/plugins/catalog-backend-module-github-org/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-catalog-backend-module-github-org +## 0.1.2-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-catalog-backend-module-github@0.4.6-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/config@1.1.1 + +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-backend-module-github@0.4.6-next.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-backend-module-github@0.4.6-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + ## 0.1.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-github-org/package.json b/plugins/catalog-backend-module-github-org/package.json index 974c9ab88b..6c16a3bc68 100644 --- a/plugins/catalog-backend-module-github-org/package.json +++ b/plugins/catalog-backend-module-github-org/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-github-org", "description": "The github-org backend module for the catalog plugin.", - "version": "0.1.1", + "version": "0.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-github-org/src/module.ts b/plugins/catalog-backend-module-github-org/src/module.ts index e510464bb7..d666f78bde 100644 --- a/plugins/catalog-backend-module-github-org/src/module.ts +++ b/plugins/catalog-backend-module-github-org/src/module.ts @@ -68,7 +68,7 @@ export const githubOrgEntityProviderTransformsExtensionPoint = */ export const catalogModuleGithubOrgEntityProvider = createBackendModule({ pluginId: 'catalog', - moduleId: 'githubOrgEntityProvider', + moduleId: 'github-org-entity-provider', register(env) { let userTransformer: UserTransformer | undefined; let teamTransformer: TeamTransformer | undefined; diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index 4c7499adf4..ceaefdcf45 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,57 @@ # @backstage/plugin-catalog-backend-module-github +## 0.4.6-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/plugin-catalog-backend@1.16.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-events-node@0.2.17-next.2 + +## 0.4.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.15.1-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## 0.4.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-backend@1.15.1-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-events-node@0.2.17-next.0 + ## 0.4.5 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/alpha-api-report.md b/plugins/catalog-backend-module-github/api-report-alpha.md similarity index 100% rename from plugins/catalog-backend-module-github/alpha-api-report.md rename to plugins/catalog-backend-module-github/api-report-alpha.md diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 4b0041b4b3..c0618db04a 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-github", "description": "A Backstage catalog backend module that helps integrate towards GitHub", - "version": "0.4.5", + "version": "0.4.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-github/src/module/catalogModuleGithubEntityProvider.ts b/plugins/catalog-backend-module-github/src/module/catalogModuleGithubEntityProvider.ts index 8e052bd0a0..bfa8cf2a4e 100644 --- a/plugins/catalog-backend-module-github/src/module/catalogModuleGithubEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/module/catalogModuleGithubEntityProvider.ts @@ -29,7 +29,7 @@ import { GithubEntityProvider } from '../providers/GithubEntityProvider'; */ export const catalogModuleGithubEntityProvider = createBackendModule({ pluginId: 'catalog', - moduleId: 'githubEntityProvider', + moduleId: 'github-entity-provider', register(env) { env.registerInit({ deps: { diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index 0ac72ea311..0c9320a93b 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.3.5-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/integration@1.8.0-next.1 + +## 0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + ## 0.3.4 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/alpha-api-report.md b/plugins/catalog-backend-module-gitlab/api-report-alpha.md similarity index 100% rename from plugins/catalog-backend-module-gitlab/alpha-api-report.md rename to plugins/catalog-backend-module-gitlab/api-report-alpha.md diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 64de0c743e..6a21d7305c 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", "description": "A Backstage catalog backend module that helps integrate towards GitLab", - "version": "0.3.4", + "version": "0.3.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.ts b/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.ts index d192e8f3a5..9979d0862e 100644 --- a/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.ts +++ b/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.ts @@ -29,7 +29,7 @@ import { GitlabDiscoveryEntityProvider } from '../providers'; */ export const catalogModuleGitlabDiscoveryEntityProvider = createBackendModule({ pluginId: 'catalog', - moduleId: 'gitlabDiscoveryEntityProvider', + moduleId: 'gitlab-discovery-entity-provider', register(env) { env.registerInit({ deps: { diff --git a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md index 32e02759c8..19c5f4f4d2 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md +++ b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md @@ -1,5 +1,55 @@ # @backstage/plugin-catalog-backend-module-incremental-ingestion +## 0.4.12-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/plugin-catalog-backend@1.16.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-events-node@0.2.17-next.2 + - @backstage/plugin-permission-common@0.7.10 + +## 0.4.12-next.1 + +### Patch Changes + +- 43b2eb8f70: Ensure that cursors always come back as JSON on sqlite too +- Updated dependencies + - @backstage/plugin-catalog-backend@1.15.1-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + - @backstage/plugin-permission-common@0.7.10 + +## 0.4.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-backend@1.15.1-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-events-node@0.2.17-next.0 + - @backstage/plugin-permission-common@0.7.10 + ## 0.4.11 ### Patch Changes diff --git a/plugins/catalog-backend-module-incremental-ingestion/alpha-api-report.md b/plugins/catalog-backend-module-incremental-ingestion/api-report-alpha.md similarity index 100% rename from plugins/catalog-backend-module-incremental-ingestion/alpha-api-report.md rename to plugins/catalog-backend-module-incremental-ingestion/api-report-alpha.md diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 60294ed1e8..2bb3a44ddd 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-incremental-ingestion", "description": "An entity provider for streaming large asset sources into the catalog", - "version": "0.4.11", + "version": "0.4.12-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/database/IncrementalIngestionDatabaseManager.test.ts b/plugins/catalog-backend-module-incremental-ingestion/src/database/IncrementalIngestionDatabaseManager.test.ts new file mode 100644 index 0000000000..a8862cfc2a --- /dev/null +++ b/plugins/catalog-backend-module-incremental-ingestion/src/database/IncrementalIngestionDatabaseManager.test.ts @@ -0,0 +1,79 @@ +/* + * 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. + */ + +import { TestDatabases } from '@backstage/backend-test-utils'; +import { IncrementalIngestionDatabaseManager } from './IncrementalIngestionDatabaseManager'; +import { v4 as uuid } from 'uuid'; + +const migrationsDir = `${__dirname}/../../migrations`; + +jest.setTimeout(60_000); + +describe('IncrementalIngestionDatabaseManager', () => { + const databases = TestDatabases.create({ + ids: ['POSTGRES_13', 'POSTGRES_9', 'SQLITE_3'], + }); + + it.each(databases.eachSupportedId())( + 'stores and retrieves marks, %p', + async databaseId => { + const knex = await databases.init(databaseId); + await knex.migrate.latest({ directory: migrationsDir }); + + const manager = new IncrementalIngestionDatabaseManager({ client: knex }); + const { ingestionId } = (await manager.createProviderIngestionRecord( + 'myProvider', + ))!; + + const cursorId = uuid(); + + await manager.createMark({ + record: { + id: cursorId, + ingestion_id: ingestionId, + sequence: 1, + cursor: { data: 1 }, + }, + }); + + await expect(manager.getFirstMark(ingestionId)).resolves.toEqual({ + created_at: expect.anything(), + cursor: { data: 1 }, + id: cursorId, + ingestion_id: ingestionId, + sequence: 1, + }); + + await expect(manager.getLastMark(ingestionId)).resolves.toEqual({ + created_at: expect.anything(), + cursor: { data: 1 }, + id: cursorId, + ingestion_id: ingestionId, + sequence: 1, + }); + + await expect(manager.getAllMarks(ingestionId)).resolves.toEqual([ + { + created_at: expect.anything(), + cursor: { data: 1 }, + id: cursorId, + ingestion_id: ingestionId, + sequence: 1, + }, + ]); + }, + ); +}); diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/database/IncrementalIngestionDatabaseManager.ts b/plugins/catalog-backend-module-incremental-ingestion/src/database/IncrementalIngestionDatabaseManager.ts index 527d345706..e47954f47e 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/database/IncrementalIngestionDatabaseManager.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/database/IncrementalIngestionDatabaseManager.ts @@ -542,7 +542,7 @@ export class IncrementalIngestionDatabaseManager { .where('ingestion_id', ingestionId) .orderBy('sequence', 'desc') .first(); - return mark; + return this.#decodeMark(this.client, mark); }); } @@ -557,7 +557,7 @@ export class IncrementalIngestionDatabaseManager { .where('ingestion_id', ingestionId) .orderBy('sequence', 'asc') .first(); - return mark; + return this.#decodeMark(this.client, mark); }); } @@ -566,7 +566,7 @@ export class IncrementalIngestionDatabaseManager { const marks = await tx('ingestion_marks') .where('ingestion_id', ingestionId) .orderBy('sequence', 'desc'); - return marks; + return marks.map(m => this.#decodeMark(this.client, m)); }); } @@ -580,6 +580,19 @@ export class IncrementalIngestionDatabaseManager { await tx('ingestion_marks').insert(record); }); } + + // Handles the fact that sqlite does not support json columns; they just + // persist the stringified data instead + #decodeMark(knex: Knex, record: T): T { + if (record && knex.client.config.client.includes('sqlite3')) { + return { + ...record, + cursor: JSON.parse(record.cursor as string), + }; + } + return record; + } + /** * Performs an upsert to the `ingestion_mark_entities` table for all deferred entities. * @param markId - string diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/database/tables.ts b/plugins/catalog-backend-module-incremental-ingestion/src/database/tables.ts index 00d40fb4a1..e1a47c040c 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/database/tables.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/database/tables.ts @@ -89,7 +89,7 @@ export interface MarkRecord { id: string; sequence: number; ingestion_id: string; - cursor: string; + cursor: unknown; created_at: string; } diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.test.ts b/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.test.ts index 7d76ddf480..316a4be7eb 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.test.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.test.ts @@ -48,7 +48,7 @@ describe('catalogModuleIncrementalIngestionEntityProvider', () => { catalogModuleIncrementalIngestionEntityProvider(), createBackendModule({ pluginId: 'catalog', - moduleId: 'incrementalTest', + moduleId: 'incremental-test', register(env) { env.registerInit({ deps: { extension: incrementalIngestionProvidersExtensionPoint }, diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.ts b/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.ts index 4e94088ef6..adb5ab6a04 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/module/catalogModuleIncrementalIngestionEntityProvider.ts @@ -49,7 +49,7 @@ export interface IncrementalIngestionProviderExtensionPoint { * ```ts * backend.add(createBackendModule({ * pluginId: 'catalog', - * moduleId: 'myIncrementalProvider', + * moduleId: 'my-incremental-provider', * register(env) { * env.registerInit({ * deps: { @@ -85,7 +85,7 @@ export const incrementalIngestionProvidersExtensionPoint = export const catalogModuleIncrementalIngestionEntityProvider = createBackendModule({ pluginId: 'catalog', - moduleId: 'incrementalIngestionEntityProvider', + moduleId: 'incremental-ingestion-entity-provider', register(env) { const addedProviders = new Array<{ provider: IncrementalEntityProvider; diff --git a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts index c24deb6adb..5af31482a6 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/src/run.ts +++ b/plugins/catalog-backend-module-incremental-ingestion/src/run.ts @@ -67,7 +67,7 @@ async function main() { backend.add( createBackendModule({ pluginId: 'catalog', - moduleId: 'incrementalTestProvider', + moduleId: 'incremental-test-provider', register(reg) { reg.registerInit({ deps: { extension: incrementalIngestionProvidersExtensionPoint }, diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index fa8edc3237..966ff2c58e 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.5.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## 0.5.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.5.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + ## 0.5.22 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 5bbff95359..cf57d50b54 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-ldap", "description": "A Backstage catalog backend module that helps integrate towards LDAP", - "version": "0.5.22", + "version": "0.5.23-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index 987868a96e..82b11514ab 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.5.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## 0.5.15-next.1 + +### Patch Changes + +- 99fb54183b: Updated dependency `@azure/identity` to `^4.0.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.5.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + ## 0.5.14 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/alpha-api-report.md b/plugins/catalog-backend-module-msgraph/api-report-alpha.md similarity index 100% rename from plugins/catalog-backend-module-msgraph/alpha-api-report.md rename to plugins/catalog-backend-module-msgraph/api-report-alpha.md diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 97e17d73c1..643dd45c40 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", - "version": "0.5.14", + "version": "0.5.15-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,7 +45,7 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@azure/identity": "^3.2.1", + "@azure/identity": "^4.0.0", "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/backend-tasks": "workspace:^", diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index 750e55e315..2458e33db7 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.1.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/plugin-catalog-backend@1.16.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## 0.1.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.15.1-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.1.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-backend@1.15.1-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + ## 0.1.24 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index 22e42ee9ea..4345352936 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-openapi", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", - "version": "0.1.24", + "version": "0.1.25-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md index d0d5aa5b86..ef386630cf 100644 --- a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md +++ b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-catalog-backend-module-puppetdb +## 0.1.13-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## 0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.1.12 ### Patch Changes diff --git a/plugins/catalog-backend-module-puppetdb/alpha-api-report.md b/plugins/catalog-backend-module-puppetdb/api-report-alpha.md similarity index 100% rename from plugins/catalog-backend-module-puppetdb/alpha-api-report.md rename to plugins/catalog-backend-module-puppetdb/api-report-alpha.md diff --git a/plugins/catalog-backend-module-puppetdb/package.json b/plugins/catalog-backend-module-puppetdb/package.json index 423d92017f..22e971fba8 100644 --- a/plugins/catalog-backend-module-puppetdb/package.json +++ b/plugins/catalog-backend-module-puppetdb/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-puppetdb", "description": "A Backstage catalog backend module that helps integrate towards PuppetDB", - "version": "0.1.12", + "version": "0.1.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.ts b/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.ts index 5546b5283b..aad28eb47a 100644 --- a/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.ts +++ b/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.ts @@ -29,7 +29,7 @@ import { PuppetDbEntityProvider } from '../providers/PuppetDbEntityProvider'; */ export const catalogModulePuppetDbEntityProvider = createBackendModule({ pluginId: 'catalog', - moduleId: 'puppetDbEntityProvider', + moduleId: 'puppetdb-entity-provider', register(env) { env.registerInit({ deps: { diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md index 351f161f0e..327b06a061 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md +++ b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-catalog-backend-module-scaffolder-entity-model +## 0.1.5-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-scaffolder-common@1.4.3 + +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-scaffolder-common@1.4.3 + +## 0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-scaffolder-common@1.4.3 + ## 0.1.4 ### Patch Changes diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/package.json b/plugins/catalog-backend-module-scaffolder-entity-model/package.json index 99116282bf..99522b8ed4 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/package.json +++ b/plugins/catalog-backend-module-scaffolder-entity-model/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-scaffolder-entity-model", "description": "Adds support for the scaffolder specific entity model (e.g. the Template kind) to the catalog backend plugin.", - "version": "0.1.4", + "version": "0.1.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/src/module.ts b/plugins/catalog-backend-module-scaffolder-entity-model/src/module.ts index 8ed763d32c..c11bc7f7d2 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/src/module.ts +++ b/plugins/catalog-backend-module-scaffolder-entity-model/src/module.ts @@ -16,7 +16,7 @@ import { createBackendModule } from '@backstage/backend-plugin-api'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; -import { ScaffolderEntitiesProcessor } from '@backstage/plugin-catalog-backend-module-scaffolder-entity-model'; +import { ScaffolderEntitiesProcessor } from './processor'; /** * Registers support for the scaffolder specific entity model (e.g. the Template @@ -26,7 +26,7 @@ import { ScaffolderEntitiesProcessor } from '@backstage/plugin-catalog-backend-m */ export const catalogModuleScaffolderEntityModel = createBackendModule({ pluginId: 'catalog', - moduleId: 'scaffolderEntityModel', + moduleId: 'scaffolder-entity-model', register(env) { env.registerInit({ deps: { diff --git a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md index e4ecafebb8..4fb935f6c5 100644 --- a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md +++ b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-catalog-backend-module-unprocessed +## 0.3.5-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + +## 0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.3.4 ### Patch Changes diff --git a/plugins/catalog-backend-module-unprocessed/package.json b/plugins/catalog-backend-module-unprocessed/package.json index fd1bad3bfa..6cdb7ccdb3 100644 --- a/plugins/catalog-backend-module-unprocessed/package.json +++ b/plugins/catalog-backend-module-unprocessed/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-unprocessed", "description": "Backstage Catalog module to view unprocessed entities", - "version": "0.3.4", + "version": "0.3.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-unprocessed/src/module.ts b/plugins/catalog-backend-module-unprocessed/src/module.ts index 1db4fd70b0..8c724d432d 100644 --- a/plugins/catalog-backend-module-unprocessed/src/module.ts +++ b/plugins/catalog-backend-module-unprocessed/src/module.ts @@ -27,7 +27,7 @@ import { UnprocessedEntitiesModule } from './UnprocessedEntitiesModule'; */ export const catalogModuleUnprocessedEntities = createBackendModule({ pluginId: 'catalog', - moduleId: 'catalogModuleUnprocessedEntities', + moduleId: 'catalog-module-unprocessed-entities', register(env) { env.registerInit({ deps: { diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 3b8d814181..ba71758d45 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,82 @@ # @backstage/plugin-catalog-backend +## 1.16.0-next.2 + +### Minor Changes + +- 7804597: Permission rules can now be added for the Catalog plugin through the `CatalogPermissionExtensionPoint` interface. + +### Patch Changes + +- 50ee804: Wrap single `pipelineLoop` of TaskPipeline in a span for better traces +- a168507: Deprecated `EntitiesSearchFilter` and `EntityFilter`, which can now be imported from `@backstage/plugin-catalog-node` instead +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.2 + - @backstage/backend-openapi-utils@0.1.1-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-events-node@0.2.17-next.2 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## 1.15.1-next.1 + +### Patch Changes + +- 38340678c3: Update the OpenAPI spec to support the use of `openapi-generator`. +- 7123c58b3d: Updated dependency `@types/glob` to `^8.0.0`. +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-openapi-utils@0.1.1-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.1 + +## 1.15.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-openapi-utils@0.1.1-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/plugin-search-backend-module-catalog@0.1.12-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-events-node@0.2.17-next.0 + - @backstage/plugin-permission-common@0.7.10 + ## 1.15.0 ### Minor Changes diff --git a/plugins/catalog-backend/alpha-api-report.md b/plugins/catalog-backend/api-report-alpha.md similarity index 97% rename from plugins/catalog-backend/alpha-api-report.md rename to plugins/catalog-backend/api-report-alpha.md index 1682d1cbae..51a2ec6114 100644 --- a/plugins/catalog-backend/alpha-api-report.md +++ b/plugins/catalog-backend/api-report-alpha.md @@ -6,6 +6,7 @@ import { BackendFeature } from '@backstage/backend-plugin-api'; import { ConditionalPolicyDecision } from '@backstage/plugin-permission-common'; import { Conditions } from '@backstage/plugin-permission-node'; +import { EntitiesSearchFilter } from '@backstage/plugin-catalog-node'; import { Entity } from '@backstage/catalog-model'; import { PermissionCondition } from '@backstage/plugin-permission-common'; import { PermissionCriteria } from '@backstage/plugin-permission-common'; @@ -90,12 +91,6 @@ export const createCatalogPermissionRule: < rule: PermissionRule, ) => PermissionRule; -// @public -export type EntitiesSearchFilter = { - key: string; - values?: string[]; -}; - // @alpha export const permissionRules: { hasAnnotation: PermissionRule< diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 1aed0ea8b0..8b7565bd1f 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -28,7 +28,9 @@ import { Config } from '@backstage/config'; import { DefaultCatalogCollatorFactory as DefaultCatalogCollatorFactory_2 } from '@backstage/plugin-search-backend-module-catalog'; import type { DefaultCatalogCollatorFactoryOptions as DefaultCatalogCollatorFactoryOptions_2 } from '@backstage/plugin-search-backend-module-catalog'; import { DeferredEntity as DeferredEntity_2 } from '@backstage/plugin-catalog-node'; +import { EntitiesSearchFilter as EntitiesSearchFilter_2 } from '@backstage/plugin-catalog-node'; import { Entity } from '@backstage/catalog-model'; +import { EntityFilter as EntityFilter_2 } from '@backstage/plugin-catalog-node'; import { EntityPolicy } from '@backstage/catalog-model'; import { EntityProvider as EntityProvider_2 } from '@backstage/plugin-catalog-node'; import { EntityProviderConnection as EntityProviderConnection_2 } from '@backstage/plugin-catalog-node'; @@ -191,7 +193,7 @@ export type CatalogEnvironment = { // @public export type CatalogPermissionRuleInput< TParams extends PermissionRuleParams = PermissionRuleParams, -> = PermissionRule; +> = PermissionRule; // @public export interface CatalogProcessingEngine { @@ -313,24 +315,11 @@ export type DefaultCatalogCollatorFactoryOptions = // @public @deprecated (undocumented) export type DeferredEntity = DeferredEntity_2; -// @public -export type EntitiesSearchFilter = { - key: string; - values?: string[]; -}; +// @public @deprecated (undocumented) +export type EntitiesSearchFilter = EntitiesSearchFilter_2; -// @public -export type EntityFilter = - | { - allOf: EntityFilter[]; - } - | { - anyOf: EntityFilter[]; - } - | { - not: EntityFilter; - } - | EntitiesSearchFilter; +// @public @deprecated (undocumented) +export type EntityFilter = EntityFilter_2; // @public @deprecated (undocumented) export type EntityProvider = EntityProvider_2; diff --git a/plugins/catalog-backend/optic.yml b/plugins/catalog-backend/optic.yml index 8b0c050516..dbbdefcf68 100644 --- a/plugins/catalog-backend/optic.yml +++ b/plugins/catalog-backend/optic.yml @@ -12,4 +12,4 @@ capture: # ℹ️ Requests should be sent to the Optic proxy, the address of which is injected into 'run.command's env as OPTIC_PROXY (or the value of 'run.proxy_variable'). run: # 🔧 Specify a command that will generate traffic - command: yarn backstage-cli package test --no-watch src/service/router.test.ts src/service/createRouter.test.ts + command: yarn backstage-cli package test --no-watch "src/service/router.test.ts" "src/service/createRouter.test.ts" diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 9c46bb2b2a..8525cc4834 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend", "description": "The Backstage backend plugin that provides the Backstage catalog", - "version": "1.15.0", + "version": "1.16.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -90,6 +90,7 @@ "@backstage/plugin-permission-common": "workspace:^", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", + "@types/glob": "^8.0.0", "@types/lodash": "^4.14.151", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", diff --git a/plugins/catalog-backend/src/alpha.ts b/plugins/catalog-backend/src/alpha.ts index 06c9571bfa..f85ef02c80 100644 --- a/plugins/catalog-backend/src/alpha.ts +++ b/plugins/catalog-backend/src/alpha.ts @@ -14,11 +14,5 @@ * limitations under the License. */ -// TODO(Rugvip): Re-exported for alpha types as the API report will otherwise -// produce warnings due to the indirect dependency. Would be nice to avoid. -import type { EntitiesSearchFilter } from './catalog/types'; - -export type { /** @alpha */ EntitiesSearchFilter }; - export * from './permissions'; export { catalogPlugin as default } from './service/CatalogPlugin'; diff --git a/plugins/catalog-backend/src/catalog/types.ts b/plugins/catalog-backend/src/catalog/types.ts index 156b8aa64d..e9f5f154c2 100644 --- a/plugins/catalog-backend/src/catalog/types.ts +++ b/plugins/catalog-backend/src/catalog/types.ts @@ -15,19 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; - -/** - * A filter expression for entities. - * - * Any (at least one) of the outer sets must match, within which all of the - * individual filters must match. - * @public - */ -export type EntityFilter = - | { allOf: EntityFilter[] } - | { anyOf: EntityFilter[] } - | { not: EntityFilter } - | EntitiesSearchFilter; +import { EntityFilter } from '@backstage/plugin-catalog-node'; /** * A pagination rule for entities. @@ -46,27 +34,6 @@ export type EntityOrder = { order: 'asc' | 'desc'; }; -/** - * Matches rows in the search table. - * @public - */ -export type EntitiesSearchFilter = { - /** - * The key to match on. - * - * Matches are always case insensitive. - */ - key: string; - - /** - * Match on plain equality of values. - * - * Match on values that are equal to any of the given array items. Matches are - * always case insensitive. - */ - values?: string[]; -}; - export type PageInfo = | { hasNextPage: false; diff --git a/plugins/catalog-backend/src/deprecated.ts b/plugins/catalog-backend/src/deprecated.ts index f3c199cbd3..2201bbbab4 100644 --- a/plugins/catalog-backend/src/deprecated.ts +++ b/plugins/catalog-backend/src/deprecated.ts @@ -18,6 +18,8 @@ import { locationSpecToMetadataName as _locationSpecToMetadataName, locationSpecToLocationEntity as _locationSpecToLocationEntity, processingResult as _processingResult, + type EntitiesSearchFilter as _EntitiesSearchFilter, + type EntityFilter as _EntityFilter, type DeferredEntity as _DeferredEntity, type EntityRelationSpec as _EntityRelationSpec, type CatalogProcessor as _CatalogProcessor, @@ -53,6 +55,16 @@ export const locationSpecToLocationEntity = _locationSpecToLocationEntity; * @deprecated import from `@backstage/plugin-catalog-node` instead */ export const processingResult = _processingResult; +/** + * @public + * @deprecated import from `@backstage/plugin-catalog-node` instead + */ +export type EntitiesSearchFilter = _EntitiesSearchFilter; +/** + * @public + * @deprecated import from `@backstage/plugin-catalog-node` instead + */ +export type EntityFilter = _EntityFilter; /** * @public * @deprecated import from `@backstage/plugin-catalog-node` instead diff --git a/plugins/catalog-backend/src/index.ts b/plugins/catalog-backend/src/index.ts index 55c1c672d3..d2f20d24d8 100644 --- a/plugins/catalog-backend/src/index.ts +++ b/plugins/catalog-backend/src/index.ts @@ -20,7 +20,6 @@ * @packageDocumentation */ -export * from './catalog'; export * from './ingestion'; export * from './modules'; export * from './processing'; diff --git a/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts b/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts index 8ebad5521c..568aae4838 100644 --- a/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts +++ b/plugins/catalog-backend/src/permissions/rules/isEntityKind.ts @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common/alpha'; import { z } from 'zod'; -import { EntitiesSearchFilter } from '../../catalog/types'; import { createCatalogPermissionRule } from './util'; /** @@ -36,7 +36,7 @@ export const isEntityKind = createCatalogPermissionRule({ const resourceKind = resource.kind.toLocaleLowerCase('en-US'); return kinds.some(kind => kind.toLocaleLowerCase('en-US') === resourceKind); }, - toQuery({ kinds }): EntitiesSearchFilter { + toQuery({ kinds }) { return { key: 'kind', values: kinds.map(kind => kind.toLocaleLowerCase('en-US')), diff --git a/plugins/catalog-backend/src/permissions/rules/util.ts b/plugins/catalog-backend/src/permissions/rules/util.ts index 466f5ce70b..c3e642490c 100644 --- a/plugins/catalog-backend/src/permissions/rules/util.ts +++ b/plugins/catalog-backend/src/permissions/rules/util.ts @@ -16,12 +16,12 @@ import { Entity } from '@backstage/catalog-model'; import { RESOURCE_TYPE_CATALOG_ENTITY } from '@backstage/plugin-catalog-common/alpha'; +import { EntitiesSearchFilter } from '@backstage/plugin-catalog-node'; import { PermissionRuleParams } from '@backstage/plugin-permission-common'; import { makeCreatePermissionRule, PermissionRule, } from '@backstage/plugin-permission-node'; -import { EntitiesSearchFilter } from '../../catalog/types'; /** * Convenience type for {@link @backstage/plugin-permission-node#PermissionRule} diff --git a/plugins/catalog-backend/src/processing/TaskPipeline.ts b/plugins/catalog-backend/src/processing/TaskPipeline.ts index 44030be9e0..b808e41ce4 100644 --- a/plugins/catalog-backend/src/processing/TaskPipeline.ts +++ b/plugins/catalog-backend/src/processing/TaskPipeline.ts @@ -14,7 +14,11 @@ * limitations under the License. */ +import { TRACER_ID, withActiveSpan } from '../util/opentelemetry'; +import { trace } from '@opentelemetry/api'; + const DEFAULT_POLLING_INTERVAL_MS = 1000; +const tracer = trace.getTracer(TRACER_ID); type Options = { /** @@ -86,33 +90,35 @@ export function startTaskPipeline(options: Options) { async function pipelineLoop() { while (!abortSignal.aborted) { if (state.inFlightCount <= lowWatermark) { - const loadCount = highWatermark - state.inFlightCount; - const loadedItems = await Promise.resolve() - .then(() => loadTasks(loadCount)) - .catch(() => { - // Silently swallow errors and go back to sleep to try again; we - // delegate to the loadTasks function itself to catch errors and log - // if it so desires - return []; - }); - if (loadedItems.length && !abortSignal.aborted) { - state.inFlightCount += loadedItems.length; - for (const item of loadedItems) { - Promise.resolve() - .then(() => processTask(item)) - .catch(() => { - // Silently swallow errors and go back to sleep to try again; we - // delegate to the processTask function itself to catch errors - // and log if it so desires - }) - .finally(() => { - state.inFlightCount -= 1; - barrier.release(); - }); + await withActiveSpan(tracer, 'TaskPipelineLoop', async span => { + const loadCount = highWatermark - state.inFlightCount; + const loadedItems = await Promise.resolve() + .then(() => loadTasks(loadCount)) + .catch(() => { + // Silently swallow errors and go back to sleep to try again; we + // delegate to the loadTasks function itself to catch errors and log + // if it so desires + return []; + }); + span.setAttribute('itemCount', loadedItems.length); + if (loadedItems.length && !abortSignal.aborted) { + state.inFlightCount += loadedItems.length; + for (const item of loadedItems) { + Promise.resolve() + .then(() => processTask(item)) + .catch(() => { + // Silently swallow errors and go back to sleep to try again; we + // delegate to the processTask function itself to catch errors + // and log if it so desires + }) + .finally(() => { + state.inFlightCount -= 1; + barrier.release(); + }); + } } - } + }); } - await barrier.wait(); } } diff --git a/plugins/catalog-backend/src/schema/openapi.generated.ts b/plugins/catalog-backend/src/schema/openapi.generated.ts index a31615dfc6..fe64c75373 100644 --- a/plugins/catalog-backend/src/schema/openapi.generated.ts +++ b/plugins/catalog-backend/src/schema/openapi.generated.ts @@ -36,6 +36,9 @@ export const spec = { { url: '/', }, + { + url: 'catalog', + }, ], components: { examples: {}, @@ -105,6 +108,7 @@ export const spec = { description: 'Restrict to just these fields in the response.', required: false, allowReserved: true, + explode: false, schema: { type: 'array', items: { @@ -248,12 +252,13 @@ export const spec = { }, }, required: ['error', 'response'], + additionalProperties: {}, }, JsonObject: { type: 'object', properties: {}, description: 'A type representing all allowed JSON object values.', - additionalProperties: true, + additionalProperties: {}, }, MapStringString: { type: 'object', @@ -291,70 +296,62 @@ export const spec = { additionalProperties: false, }, EntityMeta: { - allOf: [ - { - $ref: '#/components/schemas/JsonObject', - }, - { - type: 'object', - properties: { - links: { - type: 'array', - items: { - $ref: '#/components/schemas/EntityLink', - }, - description: - 'A list of external hyperlinks related to the entity.', - }, - tags: { - type: 'array', - items: { - type: 'string', - }, - description: - 'A list of single-valued strings, to for example classify catalog entities in\nvarious ways.', - }, - annotations: { - $ref: '#/components/schemas/MapStringString', - }, - labels: { - $ref: '#/components/schemas/MapStringString', - }, - description: { - type: 'string', - description: - 'A short (typically relatively few words, on one line) description of the\nentity.', - }, - title: { - type: 'string', - description: - 'A display name of the entity, to be presented in user interfaces instead\nof the `name` property above, when available.\nThis field is sometimes useful when the `name` is cumbersome or ends up\nbeing perceived as overly technical. The title generally does not have\nas stringent format requirements on it, so it may contain special\ncharacters and be more explanatory. Do keep it very short though, and\navoid situations where a title can be confused with the name of another\nentity, or where two entities share a title.\nNote that this is only for display purposes, and may be ignored by some\nparts of the code. Entity references still always make use of the `name`\nproperty, not the title.', - }, - namespace: { - type: 'string', - description: 'The namespace that the entity belongs to.', - }, - name: { - type: 'string', - description: - 'The name of the entity.\nMust be unique within the catalog at any given point in time, for any\ngiven namespace + kind pair. This value is part of the technical\nidentifier of the entity, and as such it will appear in URLs, database\ntables, entity references, and similar. It is subject to restrictions\nregarding what characters are allowed.\nIf you want to use a different, more human readable string with fewer\nrestrictions on it in user interfaces, see the `title` field below.', - }, - etag: { - type: 'string', - description: - 'An opaque string that changes for each update operation to any part of\nthe entity, including metadata.\nThis field can not be set by the user at creation time, and the server\nwill reject an attempt to do so. The field will be populated in read\noperations. The field can (optionally) be specified when performing\nupdate or delete operations, and the server will then reject the\noperation if it does not match the current stored value.', - }, - uid: { - type: 'string', - description: - 'A globally unique ID for the entity.\nThis field can not be set by the user at creation time, and the server\nwill reject an attempt to do so. The field will be populated in read\noperations. The field can (optionally) be specified when performing\nupdate or delete operations, but the server is free to reject requests\nthat do so in such a way that it breaks semantics.', - }, + type: 'object', + properties: { + links: { + type: 'array', + items: { + $ref: '#/components/schemas/EntityLink', }, - required: ['name'], + description: 'A list of external hyperlinks related to the entity.', }, - ], + tags: { + type: 'array', + items: { + type: 'string', + }, + description: + 'A list of single-valued strings, to for example classify catalog entities in\nvarious ways.', + }, + annotations: { + $ref: '#/components/schemas/MapStringString', + }, + labels: { + $ref: '#/components/schemas/MapStringString', + }, + description: { + type: 'string', + description: + 'A short (typically relatively few words, on one line) description of the\nentity.', + }, + title: { + type: 'string', + description: + 'A display name of the entity, to be presented in user interfaces instead\nof the `name` property above, when available.\nThis field is sometimes useful when the `name` is cumbersome or ends up\nbeing perceived as overly technical. The title generally does not have\nas stringent format requirements on it, so it may contain special\ncharacters and be more explanatory. Do keep it very short though, and\navoid situations where a title can be confused with the name of another\nentity, or where two entities share a title.\nNote that this is only for display purposes, and may be ignored by some\nparts of the code. Entity references still always make use of the `name`\nproperty, not the title.', + }, + namespace: { + type: 'string', + description: 'The namespace that the entity belongs to.', + }, + name: { + type: 'string', + description: + 'The name of the entity.\nMust be unique within the catalog at any given point in time, for any\ngiven namespace + kind pair. This value is part of the technical\nidentifier of the entity, and as such it will appear in URLs, database\ntables, entity references, and similar. It is subject to restrictions\nregarding what characters are allowed.\nIf you want to use a different, more human readable string with fewer\nrestrictions on it in user interfaces, see the `title` field below.', + }, + etag: { + type: 'string', + description: + 'An opaque string that changes for each update operation to any part of\nthe entity, including metadata.\nThis field can not be set by the user at creation time, and the server\nwill reject an attempt to do so. The field will be populated in read\noperations. The field can (optionally) be specified when performing\nupdate or delete operations, and the server will then reject the\noperation if it does not match the current stored value.', + }, + uid: { + type: 'string', + description: + 'A globally unique ID for the entity.\nThis field can not be set by the user at creation time, and the server\nwill reject an attempt to do so. The field will be populated in read\noperations. The field can (optionally) be specified when performing\nupdate or delete operations, but the server is free to reject requests\nthat do so in such a way that it breaks semantics.', + }, + }, + required: ['name'], description: 'Metadata fields common to all versions/kinds of entity.', - additionalProperties: true, + additionalProperties: {}, }, EntityRelation: { type: 'object', @@ -403,7 +400,6 @@ export const spec = { required: ['metadata', 'kind', 'apiVersion'], description: "The parts of the format that's common to all versions/kinds of entity.", - additionalProperties: true, }, NullableEntity: { type: 'object', @@ -435,7 +431,6 @@ export const spec = { required: ['metadata', 'kind', 'apiVersion'], description: "The parts of the format that's common to all versions/kinds of entity.", - additionalProperties: true, nullable: true, }, EntityAncestryResponse: { @@ -472,11 +467,7 @@ export const spec = { items: { type: 'array', items: { - anyOf: [ - { - $ref: '#/components/schemas/NullableEntity', - }, - ], + $ref: '#/components/schemas/NullableEntity', }, description: 'The list of entities, in the same order as the refs in the request. Entries\nthat are null signify that no entity existed with that ref.', @@ -495,6 +486,7 @@ export const spec = { type: 'number', }, }, + required: ['value', 'count'], additionalProperties: false, }, EntityFacetsResponse: { @@ -782,6 +774,7 @@ export const spec = { }, }, }, + required: ['items', 'totalItems', 'pageInfo'], additionalProperties: false, }, }, @@ -1076,11 +1069,6 @@ export const spec = { JWT: [], }, ], - parameters: [ - { - $ref: '#/components/parameters/fields', - }, - ], requestBody: { required: false, content: { @@ -1257,8 +1245,8 @@ export const spec = { operationId: 'CreateLocation', description: 'Create a location for a given target.', responses: { - '200': { - description: 'Ok', + '201': { + description: 'Created', content: { 'application/json': { schema: { @@ -1282,38 +1270,6 @@ export const spec = { }, }, }, - '201': { - description: '201 response', - content: { - 'application/json': { - schema: { - type: 'object', - properties: { - location: { - type: 'object', - properties: { - id: { - type: 'string', - }, - type: { - type: 'string', - }, - target: { - type: 'string', - }, - }, - required: ['id', 'type', 'target'], - }, - entities: { - type: 'array', - items: {}, - }, - }, - required: ['location', 'entities'], - }, - }, - }, - }, '400': { $ref: '#/components/responses/ErrorResponse', }, @@ -1524,7 +1480,7 @@ export const spec = { description: 'Ok', }, '400': { - description: '400 response', + description: 'Validation errors.', content: { 'application/json; charset=utf-8': { schema: { @@ -1543,6 +1499,7 @@ export const spec = { }, }, required: ['name', 'message'], + additionalProperties: {}, }, }, }, @@ -1571,7 +1528,7 @@ export const spec = { }, entity: { type: 'object', - additionalProperties: true, + additionalProperties: {}, }, }, required: ['location', 'entity'], diff --git a/plugins/catalog-backend/src/schema/openapi.yaml b/plugins/catalog-backend/src/schema/openapi.yaml index 3375f7fe15..d3ef718286 100644 --- a/plugins/catalog-backend/src/schema/openapi.yaml +++ b/plugins/catalog-backend/src/schema/openapi.yaml @@ -9,6 +9,7 @@ info: contact: {} servers: - url: / + - url: catalog components: examples: {} headers: {} @@ -65,6 +66,7 @@ components: description: Restrict to just these fields in the response. required: false allowReserved: true + explode: false schema: type: array items: @@ -180,11 +182,12 @@ components: required: - error - response + additionalProperties: {} JsonObject: type: object properties: {} description: A type representing all allowed JSON object values. - additionalProperties: true + additionalProperties: {} MapStringString: type: object properties: {} @@ -211,82 +214,80 @@ components: description: A link to external information that is related to the entity. additionalProperties: false EntityMeta: - allOf: - - $ref: '#/components/schemas/JsonObject' - - type: object - properties: - links: - type: array - items: - $ref: '#/components/schemas/EntityLink' - description: A list of external hyperlinks related to the entity. - tags: - type: array - items: - type: string - description: |- - A list of single-valued strings, to for example classify catalog entities in - various ways. - annotations: - $ref: '#/components/schemas/MapStringString' - labels: - $ref: '#/components/schemas/MapStringString' - description: - type: string - description: |- - A short (typically relatively few words, on one line) description of the - entity. - title: - type: string - description: |- - A display name of the entity, to be presented in user interfaces instead - of the `name` property above, when available. - This field is sometimes useful when the `name` is cumbersome or ends up - being perceived as overly technical. The title generally does not have - as stringent format requirements on it, so it may contain special - characters and be more explanatory. Do keep it very short though, and - avoid situations where a title can be confused with the name of another - entity, or where two entities share a title. - Note that this is only for display purposes, and may be ignored by some - parts of the code. Entity references still always make use of the `name` - property, not the title. - namespace: - type: string - description: The namespace that the entity belongs to. - name: - type: string - description: |- - The name of the entity. - Must be unique within the catalog at any given point in time, for any - given namespace + kind pair. This value is part of the technical - identifier of the entity, and as such it will appear in URLs, database - tables, entity references, and similar. It is subject to restrictions - regarding what characters are allowed. - If you want to use a different, more human readable string with fewer - restrictions on it in user interfaces, see the `title` field below. - etag: - type: string - description: |- - An opaque string that changes for each update operation to any part of - the entity, including metadata. - This field can not be set by the user at creation time, and the server - will reject an attempt to do so. The field will be populated in read - operations. The field can (optionally) be specified when performing - update or delete operations, and the server will then reject the - operation if it does not match the current stored value. - uid: - type: string - description: |- - A globally unique ID for the entity. - This field can not be set by the user at creation time, and the server - will reject an attempt to do so. The field will be populated in read - operations. The field can (optionally) be specified when performing - update or delete operations, but the server is free to reject requests - that do so in such a way that it breaks semantics. - required: - - name + type: object + properties: + links: + type: array + items: + $ref: '#/components/schemas/EntityLink' + description: A list of external hyperlinks related to the entity. + tags: + type: array + items: + type: string + description: |- + A list of single-valued strings, to for example classify catalog entities in + various ways. + annotations: + $ref: '#/components/schemas/MapStringString' + labels: + $ref: '#/components/schemas/MapStringString' + description: + type: string + description: |- + A short (typically relatively few words, on one line) description of the + entity. + title: + type: string + description: |- + A display name of the entity, to be presented in user interfaces instead + of the `name` property above, when available. + This field is sometimes useful when the `name` is cumbersome or ends up + being perceived as overly technical. The title generally does not have + as stringent format requirements on it, so it may contain special + characters and be more explanatory. Do keep it very short though, and + avoid situations where a title can be confused with the name of another + entity, or where two entities share a title. + Note that this is only for display purposes, and may be ignored by some + parts of the code. Entity references still always make use of the `name` + property, not the title. + namespace: + type: string + description: The namespace that the entity belongs to. + name: + type: string + description: |- + The name of the entity. + Must be unique within the catalog at any given point in time, for any + given namespace + kind pair. This value is part of the technical + identifier of the entity, and as such it will appear in URLs, database + tables, entity references, and similar. It is subject to restrictions + regarding what characters are allowed. + If you want to use a different, more human readable string with fewer + restrictions on it in user interfaces, see the `title` field below. + etag: + type: string + description: |- + An opaque string that changes for each update operation to any part of + the entity, including metadata. + This field can not be set by the user at creation time, and the server + will reject an attempt to do so. The field will be populated in read + operations. The field can (optionally) be specified when performing + update or delete operations, and the server will then reject the + operation if it does not match the current stored value. + uid: + type: string + description: |- + A globally unique ID for the entity. + This field can not be set by the user at creation time, and the server + will reject an attempt to do so. The field will be populated in read + operations. The field can (optionally) be specified when performing + update or delete operations, but the server is free to reject requests + that do so in such a way that it breaks semantics. + required: + - name description: Metadata fields common to all versions/kinds of entity. - additionalProperties: true + additionalProperties: {} EntityRelation: type: object properties: @@ -326,7 +327,6 @@ components: - kind - apiVersion description: The parts of the format that's common to all versions/kinds of entity. - additionalProperties: true NullableEntity: type: object properties: @@ -352,7 +352,6 @@ components: - kind - apiVersion description: The parts of the format that's common to all versions/kinds of entity. - additionalProperties: true nullable: true EntityAncestryResponse: type: object @@ -383,8 +382,7 @@ components: items: type: array items: - anyOf: - - $ref: '#/components/schemas/NullableEntity' + $ref: '#/components/schemas/NullableEntity' description: |- The list of entities, in the same order as the refs in the request. Entries that are null signify that no entity existed with that ref. @@ -398,6 +396,9 @@ components: type: string count: type: number + required: + - value + - count additionalProperties: false EntityFacetsResponse: type: object @@ -660,6 +661,10 @@ components: prevCursor: type: string description: The cursor for the previous batch of entities. + required: + - items + - totalItems + - pageInfo additionalProperties: false securitySchemes: JWT: @@ -829,8 +834,6 @@ paths: security: - {} - JWT: [] - parameters: - - $ref: '#/components/parameters/fields' requestBody: required: false content: @@ -942,8 +945,8 @@ paths: operationId: CreateLocation description: Create a location for a given target. responses: - '200': - description: Ok + '201': + description: Created content: application/json: schema: @@ -960,32 +963,6 @@ paths: required: - entities - location - '201': - description: 201 response - content: - application/json: - schema: - type: object - properties: - location: - type: object - properties: - id: - type: string - type: - type: string - target: - type: string - required: - - id - - type - - target - entities: - type: array - items: {} - required: - - location - - entities '400': $ref: '#/components/responses/ErrorResponse' default: @@ -1120,7 +1097,7 @@ paths: '200': description: Ok '400': - description: 400 response + description: Validation errors. content: application/json; charset=utf-8: schema: @@ -1138,6 +1115,7 @@ paths: required: - name - message + additionalProperties: {} required: - errors security: @@ -1155,7 +1133,7 @@ paths: type: string entity: type: object - additionalProperties: true + additionalProperties: {} required: - location - entity diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts index 2ee47dae19..ce9221e16e 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.test.ts @@ -20,8 +20,9 @@ import { createConditionTransformer } from '@backstage/plugin-permission-node'; import { isEntityKind } from '../permissions/rules/isEntityKind'; import { CatalogPermissionRule } from '../permissions/rules'; import { AuthorizedEntitiesCatalog } from './AuthorizedEntitiesCatalog'; -import { Cursor, EntityFilter, QueryEntitiesResponse } from '../catalog/types'; +import { Cursor, QueryEntitiesResponse } from '../catalog/types'; import { Entity } from '@backstage/catalog-model'; +import { EntityFilter } from '@backstage/plugin-catalog-node'; describe('AuthorizedEntitiesCatalog', () => { const fakeCatalog = { diff --git a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts index 0ce1ee87e7..6a04c4d7a1 100644 --- a/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/AuthorizedEntitiesCatalog.ts @@ -35,12 +35,12 @@ import { EntityAncestryResponse, EntityFacetsRequest, EntityFacetsResponse, - EntityFilter, QueryEntitiesRequest, QueryEntitiesResponse, } from '../catalog/types'; import { basicEntityFilter } from './request/basicEntityFilter'; import { isQueryEntitiesCursorRequest } from './util'; +import { EntityFilter } from '@backstage/plugin-catalog-node'; export class AuthorizedEntitiesCatalog implements EntitiesCatalog { constructor( diff --git a/plugins/catalog-backend/src/service/CatalogBuilder.ts b/plugins/catalog-backend/src/service/CatalogBuilder.ts index 5cf76ee1ac..f8ed166118 100644 --- a/plugins/catalog-backend/src/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/CatalogBuilder.ts @@ -37,6 +37,7 @@ import lodash, { keyBy } from 'lodash'; import { CatalogProcessor, CatalogProcessorParser, + EntitiesSearchFilter, EntityProvider, ScmLocationAnalyzer, } from '@backstage/plugin-catalog-node'; @@ -79,7 +80,6 @@ import { Config, readDurationFromConfig } from '@backstage/config'; import { Logger } from 'winston'; import { connectEntityProviders } from '../processing/connectEntityProviders'; import { PermissionRuleParams } from '@backstage/plugin-permission-common'; -import { EntitiesSearchFilter } from '../catalog/types'; import { permissionRules as catalogPermissionRules } from '../permissions/rules'; import { PermissionRule } from '@backstage/plugin-permission-node'; import { diff --git a/plugins/catalog-backend/src/service/CatalogPlugin.ts b/plugins/catalog-backend/src/service/CatalogPlugin.ts index fa53ef510b..0800d41340 100644 --- a/plugins/catalog-backend/src/service/CatalogPlugin.ts +++ b/plugins/catalog-backend/src/service/CatalogPlugin.ts @@ -17,12 +17,14 @@ import { createBackendPlugin, coreServices, } from '@backstage/backend-plugin-api'; -import { CatalogBuilder } from './CatalogBuilder'; +import { CatalogBuilder, CatalogPermissionRuleInput } from './CatalogBuilder'; import { CatalogAnalysisExtensionPoint, catalogAnalysisExtensionPoint, CatalogProcessingExtensionPoint, catalogProcessingExtensionPoint, + CatalogPermissionExtensionPoint, + catalogPermissionExtensionPoint, } from '@backstage/plugin-catalog-node/alpha'; import { CatalogProcessor, @@ -86,6 +88,24 @@ class CatalogAnalysisExtensionPointImpl } } +class CatalogPermissionExtensionPointImpl + implements CatalogPermissionExtensionPoint +{ + #permissionRules = new Array(); + + addPermissionRules( + ...rules: Array< + CatalogPermissionRuleInput | Array + > + ): void { + this.#permissionRules.push(...rules.flat()); + } + + get permissionRules() { + return this.#permissionRules; + } +} + /** * Catalog plugin * @alpha @@ -106,6 +126,12 @@ export const catalogPlugin = createBackendPlugin({ analysisExtensions, ); + const permissionExtensions = new CatalogPermissionExtensionPointImpl(); + env.registerExtensionPoint( + catalogPermissionExtensionPoint, + permissionExtensions, + ); + env.registerInit({ deps: { logger: coreServices.logger, @@ -142,6 +168,7 @@ export const catalogPlugin = createBackendPlugin({ ([key, resolver]) => builder.setPlaceholderResolver(key, resolver), ); builder.addLocationAnalyzers(...analysisExtensions.locationAnalyzers); + builder.addPermissionRules(...permissionExtensions.permissionRules); const { processingEngine, router } = await builder.build(); diff --git a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts index 24f0432419..0245fe1d4e 100644 --- a/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/DefaultEntitiesCatalog.ts @@ -31,11 +31,9 @@ import { EntitiesCatalog, EntitiesRequest, EntitiesResponse, - EntitiesSearchFilter, EntityAncestryResponse, EntityFacetsRequest, EntityFacetsResponse, - EntityFilter, EntityPagination, QueryEntitiesRequest, QueryEntitiesResponse, @@ -55,6 +53,10 @@ import { isQueryEntitiesCursorRequest, isQueryEntitiesInitialRequest, } from './util'; +import { + EntitiesSearchFilter, + EntityFilter, +} from '@backstage/plugin-catalog-node'; const defaultSortField: EntityOrder = { field: 'metadata.uid', diff --git a/plugins/catalog-backend/src/service/createRouter.test.ts b/plugins/catalog-backend/src/service/createRouter.test.ts index 700e35edc1..05ebf6e1a9 100644 --- a/plugins/catalog-backend/src/service/createRouter.test.ts +++ b/plugins/catalog-backend/src/service/createRouter.test.ts @@ -198,6 +198,45 @@ describe('createRouter readonly disabled', () => { }); }); + it('parses encoded params request', async () => { + entitiesCatalog.queryEntities.mockResolvedValueOnce({ + items: [], + pageInfo: {}, + totalItems: 0, + }); + const response = await request(app).get( + `/entities/by-query?filter=${encodeURIComponent( + 'a=1,a=2,b=3', + )}&filter=c=4&orderField=${encodeURIComponent( + 'metadata.name,asc', + )}&orderField=metadata.uid,desc`, + ); + + expect(response.status).toEqual(200); + expect(entitiesCatalog.queryEntities).toHaveBeenCalledTimes(1); + expect(entitiesCatalog.queryEntities).toHaveBeenCalledWith({ + filter: { + anyOf: [ + { + allOf: [ + { key: 'a', values: ['1', '2'] }, + { key: 'b', values: ['3'] }, + ], + }, + { allOf: [{ key: 'c', values: ['4'] }] }, + ], + }, + orderFields: [ + { field: 'metadata.name', order: 'asc' }, + { field: 'metadata.uid', order: 'desc' }, + ], + fullTextFilter: { + fields: undefined, + term: '', + }, + }); + }); + it('parses cursor request', async () => { const items: Entity[] = [ { apiVersion: 'a', kind: 'b', metadata: { name: 'n' } }, diff --git a/plugins/catalog-backend/src/service/request/basicEntityFilter.ts b/plugins/catalog-backend/src/service/request/basicEntityFilter.ts index 36448e0304..43824160a2 100644 --- a/plugins/catalog-backend/src/service/request/basicEntityFilter.ts +++ b/plugins/catalog-backend/src/service/request/basicEntityFilter.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -import { EntitiesSearchFilter, EntityFilter } from '../../catalog'; +import { + EntitiesSearchFilter, + EntityFilter, +} from '@backstage/plugin-catalog-node'; /** * Forms a full EntityFilter based on a single key-value(s) object. diff --git a/plugins/catalog-backend/src/service/request/parseEntityFilterParams.ts b/plugins/catalog-backend/src/service/request/parseEntityFilterParams.ts index 767a36ce71..cfd9aa0aa5 100644 --- a/plugins/catalog-backend/src/service/request/parseEntityFilterParams.ts +++ b/plugins/catalog-backend/src/service/request/parseEntityFilterParams.ts @@ -15,8 +15,11 @@ */ import { InputError } from '@backstage/errors'; -import { EntitiesSearchFilter, EntityFilter } from '../../catalog'; import { parseStringsParam } from './common'; +import { + EntitiesSearchFilter, + EntityFilter, +} from '@backstage/plugin-catalog-node'; /** * Parses the filtering part of a query, like diff --git a/plugins/catalog-backend/src/service/util.ts b/plugins/catalog-backend/src/service/util.ts index 699bca2fc9..af1279a59a 100644 --- a/plugins/catalog-backend/src/service/util.ts +++ b/plugins/catalog-backend/src/service/util.ts @@ -20,11 +20,11 @@ import lodash from 'lodash'; import { z } from 'zod'; import { Cursor, - EntityFilter, QueryEntitiesCursorRequest, QueryEntitiesInitialRequest, QueryEntitiesRequest, } from '../catalog/types'; +import { EntityFilter } from '@backstage/plugin-catalog-node'; export async function requireRequestBody(req: Request): Promise { const contentType = req.header('content-type'); diff --git a/plugins/catalog-backend/src/tests/performance/stitchingPerformance.test.ts b/plugins/catalog-backend/src/tests/performance/stitchingPerformance.test.ts index ad659ce845..7902a5e230 100644 --- a/plugins/catalog-backend/src/tests/performance/stitchingPerformance.test.ts +++ b/plugins/catalog-backend/src/tests/performance/stitchingPerformance.test.ts @@ -188,8 +188,8 @@ describePerformanceTest('stitchingPerformance', () => { factory: () => ({ getClient: async () => knex }), }), createBackendModule({ - moduleId: 'syntheticLoadEntities', pluginId: 'catalog', + moduleId: 'synthetic-load-entities', register(reg) { reg.registerInit({ deps: { @@ -245,8 +245,8 @@ describePerformanceTest('stitchingPerformance', () => { factory: () => ({ getClient: async () => knex }), }), createBackendModule({ - moduleId: 'syntheticLoadEntities', pluginId: 'catalog', + moduleId: 'synthetic-load-entities', register(reg) { reg.registerInit({ deps: { diff --git a/plugins/catalog-common/alpha-api-report.md b/plugins/catalog-common/api-report-alpha.md similarity index 100% rename from plugins/catalog-common/alpha-api-report.md rename to plugins/catalog-common/api-report-alpha.md diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index a7fe02e56c..9e22aeb07e 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-catalog-graph +## 0.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/types@1.1.1 + +## 0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + +## 0.3.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/types@1.1.1 + ## 0.3.0 ### Minor Changes diff --git a/plugins/catalog-graph/README.md b/plugins/catalog-graph/README.md index 010a129b0f..f00d11810f 100644 --- a/plugins/catalog-graph/README.md +++ b/plugins/catalog-graph/README.md @@ -90,7 +90,7 @@ To use the catalog graph plugin, you have to add some things to your Backstage a Copy the default implementation `DefaultRenderNode.tsx` and add more classes to the styles: ```typescript -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ node: { … diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 4d3cbf4c3a..940a9d2092 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.3.0", + "version": "0.3.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graphql/CHANGELOG.md b/plugins/catalog-graphql/CHANGELOG.md deleted file mode 100644 index 6c0ef16769..0000000000 --- a/plugins/catalog-graphql/CHANGELOG.md +++ /dev/null @@ -1,711 +0,0 @@ -# @backstage/plugin-catalog-graphql - -## 0.4.1 - -### Patch Changes - -- 6c2b872153: Add official support for React 18. -- Updated dependencies - - @backstage/catalog-model@1.4.3 - - @backstage/config@1.1.1 - - @backstage/types@1.1.1 - -## 0.4.1-next.0 - -### Patch Changes - -- 6c2b872153: Add official support for React 18. -- Updated dependencies - - @backstage/catalog-model@1.4.3 - - @backstage/config@1.1.1 - - @backstage/types@1.1.1 - -## 0.4.0 - -### Minor Changes - -- 9def1e95ab: This package has been deprecated, consider using [@frontside/backstage-plugin-graphql-backend](https://www.npmjs.com/package/@frontside/backstage-plugin-graphql-backend) instead. - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.4.3 - - @backstage/config@1.1.1 - - @backstage/types@1.1.1 - -## 0.3.24-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.4.3-next.0 - - @backstage/config@1.1.1-next.0 - - @backstage/types@1.1.1 - -## 0.3.23 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.1.0 - - @backstage/catalog-model@1.4.2 - - @backstage/types@1.1.1 - -## 0.3.23-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.4.2-next.2 - - @backstage/config@1.1.0-next.2 - - @backstage/types@1.1.1-next.0 - -## 0.3.23-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.1.0-next.1 - - @backstage/catalog-model@1.4.2-next.1 - - @backstage/types@1.1.0 - -## 0.3.23-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.1.0-next.0 - - @backstage/catalog-model@1.4.2-next.0 - - @backstage/types@1.1.0 - -## 0.3.22 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.4.1 - - @backstage/config@1.0.8 - - @backstage/types@1.1.0 - -## 0.3.22-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.4.1-next.0 - - @backstage/config@1.0.8 - - @backstage/types@1.1.0 - -## 0.3.21 - -### Patch Changes - -- Updated dependencies - - @backstage/types@1.1.0 - - @backstage/catalog-model@1.4.0 - - @backstage/config@1.0.8 - -## 0.3.21-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.4.0-next.1 - - @backstage/config@1.0.7 - - @backstage/types@1.0.2 - -## 0.3.21-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.4.0-next.0 - - @backstage/config@1.0.7 - - @backstage/types@1.0.2 - -## 0.3.20 - -### Patch Changes - -- e47e69eadf0: Updated dependency `@apollo/server` to `^4.0.0`. -- e0c6e8b9c3c: Update peer dependencies -- Updated dependencies - - @backstage/catalog-model@1.3.0 - - @backstage/config@1.0.7 - - @backstage/types@1.0.2 - -## 0.3.20-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.3.0-next.0 - - @backstage/config@1.0.7 - - @backstage/types@1.0.2 - -## 0.3.20-next.1 - -### Patch Changes - -- e0c6e8b9c3c: Update peer dependencies -- Updated dependencies - - @backstage/catalog-model@1.2.1 - - @backstage/config@1.0.7 - - @backstage/types@1.0.2 - -## 0.3.20-next.0 - -### Patch Changes - -- e47e69eadf0: Updated dependency `@apollo/server` to `^4.0.0`. -- Updated dependencies - - @backstage/config@1.0.7 - - @backstage/catalog-model@1.2.1 - - @backstage/types@1.0.2 - -## 0.3.19 - -### Patch Changes - -- b990021ddeb: Updated dependency `@graphql-codegen/cli` to `^3.0.0`. - Updated dependency `@graphql-codegen/graphql-modules-preset` to `^3.0.0`. - Updated dependency `@graphql-codegen/typescript` to `^3.0.0`. - Updated dependency `@graphql-codegen/typescript-resolvers` to `^3.0.0`. -- 52b0022dab7: Updated dependency `msw` to `^1.0.0`. -- Updated dependencies - - @backstage/catalog-model@1.2.1 - - @backstage/config@1.0.7 - - @backstage/types@1.0.2 - -## 0.3.19-next.1 - -### Patch Changes - -- b990021ddeb: Updated dependency `@graphql-codegen/cli` to `^3.0.0`. - Updated dependency `@graphql-codegen/graphql-modules-preset` to `^3.0.0`. - Updated dependency `@graphql-codegen/typescript` to `^3.0.0`. - Updated dependency `@graphql-codegen/typescript-resolvers` to `^3.0.0`. -- 52b0022dab7: Updated dependency `msw` to `^1.0.0`. -- Updated dependencies - - @backstage/config@1.0.7-next.0 - - @backstage/catalog-model@1.2.1-next.1 - - @backstage/types@1.0.2 - -## 0.3.19-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.2.1-next.0 - - @backstage/config@1.0.6 - - @backstage/types@1.0.2 - -## 0.3.18 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.2.0 - - @backstage/config@1.0.6 - - @backstage/types@1.0.2 - -## 0.3.18-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.2.0-next.1 - - @backstage/config@1.0.6 - - @backstage/types@1.0.2 - -## 0.3.18-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.1.6-next.0 - -## 0.3.17 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.1.5 - - @backstage/config@1.0.6 - - @backstage/types@1.0.2 - -## 0.3.17-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.0.6-next.0 - - @backstage/catalog-model@1.1.5-next.1 - - @backstage/types@1.0.2 - -## 0.3.17-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.1.5-next.0 - - @backstage/config@1.0.5 - - @backstage/types@1.0.2 - -## 0.3.16 - -### Patch Changes - -- 3280711113: Updated dependency `msw` to `^0.49.0`. -- Updated dependencies - - @backstage/types@1.0.2 - - @backstage/catalog-model@1.1.4 - - @backstage/config@1.0.5 - -## 0.3.16-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/types@1.0.2-next.1 - - @backstage/config@1.0.5-next.1 - - @backstage/catalog-model@1.1.4-next.1 - -## 0.3.16-next.0 - -### Patch Changes - -- 3280711113: Updated dependency `msw` to `^0.49.0`. -- Updated dependencies - - @backstage/types@1.0.2-next.0 - - @backstage/catalog-model@1.1.4-next.0 - - @backstage/config@1.0.5-next.0 - -## 0.3.15 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.1.3 - - @backstage/types@1.0.1 - - @backstage/config@1.0.4 - -## 0.3.15-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.1.3-next.0 - - @backstage/types@1.0.1-next.0 - - @backstage/config@1.0.4-next.0 - -## 0.3.14 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.1.2 - - @backstage/config@1.0.3 - - @backstage/types@1.0.0 - -## 0.3.14-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.1.2-next.2 - - @backstage/config@1.0.3-next.2 - - @backstage/types@1.0.0 - -## 0.3.14-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.1.2-next.1 - - @backstage/config@1.0.3-next.1 - - @backstage/types@1.0.0 - -## 0.3.14-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.1.2-next.0 - - @backstage/config@1.0.3-next.0 - - @backstage/types@1.0.0 - -## 0.3.13 - -### Patch Changes - -- d669d89206: Minor API signatures cleanup -- 667d917488: Updated dependency `msw` to `^0.47.0`. -- 87ec2ba4d6: Updated dependency `msw` to `^0.46.0`. -- bf5e9030eb: Updated dependency `msw` to `^0.45.0`. -- Updated dependencies - - @backstage/catalog-model@1.1.1 - - @backstage/config@1.0.2 - -## 0.3.13-next.3 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.1.1-next.0 - - @backstage/config@1.0.2-next.0 - -## 0.3.13-next.2 - -### Patch Changes - -- 667d917488: Updated dependency `msw` to `^0.47.0`. -- 87ec2ba4d6: Updated dependency `msw` to `^0.46.0`. - -## 0.3.13-next.1 - -### Patch Changes - -- d669d89206: Minor API signatures cleanup - -## 0.3.13-next.0 - -### Patch Changes - -- bf5e9030eb: Updated dependency `msw` to `^0.45.0`. - -## 0.3.12 - -### Patch Changes - -- fa3eeee92d: Updated dependency `@graphql-tools/schema` to `^9.0.0`. - -## 0.3.11 - -### Patch Changes - -- a70869e775: Updated dependency `msw` to `^0.43.0`. -- 8006d0f9bf: Updated dependency `msw` to `^0.44.0`. -- Updated dependencies - - @backstage/catalog-model@1.1.0 - -## 0.3.11-next.1 - -### Patch Changes - -- a70869e775: Updated dependency `msw` to `^0.43.0`. -- Updated dependencies - - @backstage/catalog-model@1.1.0-next.3 - -## 0.3.11-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.1.0-next.0 - -## 0.3.10 - -### Patch Changes - -- 8f7b1835df: Updated dependency `msw` to `^0.41.0`. -- Updated dependencies - - @backstage/catalog-model@1.0.3 - -## 0.3.10-next.0 - -### Patch Changes - -- 8f7b1835df: Updated dependency `msw` to `^0.41.0`. -- Updated dependencies - - @backstage/catalog-model@1.0.3-next.0 - -## 0.3.9 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.0.1 - - @backstage/catalog-model@1.0.2 - -## 0.3.9-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.0.1-next.0 - - @backstage/catalog-model@1.0.2-next.0 - -## 0.3.8 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.0.1 - -## 0.3.8-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@1.0.1-next.0 - -## 0.3.7 - -### Patch Changes - -- 02ad19d189: Do not use `metadata.generation` from entity data -- Updated dependencies - - @backstage/catalog-model@1.0.0 - - @backstage/config@1.0.0 - - @backstage/types@1.0.0 - -## 0.3.6 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@0.13.0 - -## 0.3.6-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@0.13.0-next.0 - -## 0.3.5 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@0.12.0 - -## 0.3.4 - -### Patch Changes - -- 68913af4ff: chore(deps): bump `graphql-modules` from 1.4.4 to 2.0.0 -- Updated dependencies - - @backstage/catalog-model@0.11.0 - -## 0.3.3 - -### Patch Changes - -- Fix for the previous release with missing type declarations. -- Updated dependencies - - @backstage/catalog-model@0.10.1 - - @backstage/config@0.1.15 - - @backstage/types@0.1.3 - -## 0.3.2 - -### Patch Changes - -- 1ed305728b: Bump `node-fetch` to version 2.6.7 and `cross-fetch` to version 3.1.5 -- c77c5c7eb6: Added `backstage.role` to `package.json` -- Updated dependencies - - @backstage/catalog-model@0.10.0 - - @backstage/config@0.1.14 - - @backstage/types@0.1.2 - -## 0.3.1 - -### Patch Changes - -- Updated dependencies - - @backstage/config@0.1.13 - - @backstage/catalog-model@0.9.10 - -## 0.3.1-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/config@0.1.13-next.0 - - @backstage/catalog-model@0.9.10-next.0 - -## 0.3.0 - -### Minor Changes - -- 0fb17da164: chore: bumping dependencies in the GraphQL modules and bringing them up to date with the latest `graphql-modules` library - -### Patch Changes - -- cf01627a33: Bump graphql versions -- Updated dependencies - - @backstage/config@0.1.12 - - @backstage/catalog-model@0.9.9 - -## 0.2.14 - -### Patch Changes - -- 6b500622d5: Move to using node-fetch internally instead of cross-fetch - -## 0.2.13 - -### Patch Changes - -- 10615525f3: Switch to use the json and observable types from `@backstage/types` -- Updated dependencies - - @backstage/config@0.1.11 - - @backstage/catalog-model@0.9.6 - -## 0.2.12 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.9.0 - - @backstage/config@0.1.8 - -## 0.2.11 - -### Patch Changes - -- Updated dependencies - - @backstage/catalog-model@0.9.0 - - @backstage/backend-common@0.8.5 - -## 0.2.10 - -### Patch Changes - -- Updated dependencies [add62a455] -- Updated dependencies [704875e26] - - @backstage/catalog-model@0.8.0 - -## 0.2.9 - -### Patch Changes - -- 3be844496: chore: bump `ts-node` versions to 9.1.1 -- Updated dependencies [22fd8ce2a] -- Updated dependencies [10c008a3a] -- Updated dependencies [f9fb4a205] -- Updated dependencies [16be1d093] - - @backstage/backend-common@0.8.0 - - @backstage/catalog-model@0.7.9 - -## 0.2.8 - -### Patch Changes - -- Updated dependencies [e0bfd3d44] -- Updated dependencies [38ca05168] -- Updated dependencies [d8b81fd28] - - @backstage/backend-common@0.7.0 - - @backstage/catalog-model@0.7.8 - - @backstage/config@0.1.5 - -## 0.2.7 - -### Patch Changes - -- Updated dependencies [8686eb38c] -- Updated dependencies [0434853a5] -- Updated dependencies [8686eb38c] - - @backstage/backend-common@0.6.0 - - @backstage/config@0.1.4 - -## 0.2.6 - -### Patch Changes - -- Updated dependencies [def2307f3] -- Updated dependencies [0b135e7e0] -- Updated dependencies [294a70cab] -- Updated dependencies [0ea032763] -- Updated dependencies [5345a1f98] -- Updated dependencies [09a370426] -- Updated dependencies [a93f42213] - - @backstage/catalog-model@0.7.0 - - @backstage/backend-common@0.5.0 - -## 0.2.5 - -### Patch Changes - -- Updated dependencies [c911061b7] -- Updated dependencies [1d1c2860f] -- Updated dependencies [0e6298f7e] -- Updated dependencies [4eafdec4a] -- Updated dependencies [ac3560b42] - - @backstage/catalog-model@0.6.0 - - @backstage/backend-common@0.4.1 - -## 0.2.4 - -### Patch Changes - -- Updated dependencies [38e24db00] -- Updated dependencies [e3bd9fc2f] -- Updated dependencies [12bbd748c] -- Updated dependencies [83b6e0c1f] -- Updated dependencies [e3bd9fc2f] - - @backstage/backend-common@0.4.0 - - @backstage/config@0.1.2 - - @backstage/catalog-model@0.5.0 - -## 0.2.3 - -### Patch Changes - -- Updated dependencies [612368274] -- Updated dependencies [08835a61d] -- Updated dependencies [a9fd599f7] -- Updated dependencies [bcc211a08] - - @backstage/backend-common@0.3.3 - - @backstage/catalog-model@0.4.0 - -## 0.2.2 - -### Patch Changes - -- Updated dependencies [1166fcc36] -- Updated dependencies [bff3305aa] -- Updated dependencies [1185919f3] -- Updated dependencies [b47dce06f] - - @backstage/catalog-model@0.3.0 - - @backstage/backend-common@0.3.1 - -## 0.2.1 - -### Patch Changes - -- Updated dependencies [1722cb53c] -- Updated dependencies [1722cb53c] -- Updated dependencies [7b37e6834] -- Updated dependencies [8e2effb53] - - @backstage/backend-common@0.3.0 - -## 0.2.0 - -### Minor Changes - -- 28edd7d29: Create backend plugin through CLI - -### Patch Changes - -- Updated dependencies [3a4236570] -- Updated dependencies [e0be86b6f] -- Updated dependencies [f70a52868] -- Updated dependencies [12b5fe940] -- Updated dependencies [5249594c5] -- Updated dependencies [56e4eb589] -- Updated dependencies [e37c0a005] -- Updated dependencies [a768a07fb] -- Updated dependencies [f00ca3cb8] -- Updated dependencies [6579769df] -- Updated dependencies [5adfc005e] -- Updated dependencies [8c2b76e45] -- Updated dependencies [440a17b39] -- Updated dependencies [fa56f4615] -- Updated dependencies [8afce088a] -- Updated dependencies [b3d57961c] -- Updated dependencies [7bbeb049f] - - @backstage/catalog-model@0.2.0 - - @backstage/backend-common@0.2.0 diff --git a/plugins/catalog-graphql/README.md b/plugins/catalog-graphql/README.md deleted file mode 100644 index 021d0d1b20..0000000000 --- a/plugins/catalog-graphql/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Catalog GraphQL Plugin - -This package has been deprecated, consider using [@frontside/backstage-plugin-graphql-backend](https://www.npmjs.com/package/@frontside/backstage-plugin-graphql-backend) instead. diff --git a/plugins/catalog-graphql/api-report.md b/plugins/catalog-graphql/api-report.md deleted file mode 100644 index f03ed94af5..0000000000 --- a/plugins/catalog-graphql/api-report.md +++ /dev/null @@ -1,20 +0,0 @@ -## API Report File for "@backstage/plugin-catalog-graphql" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { Config } from '@backstage/config'; -import { Logger } from 'winston'; -import { Module } from 'graphql-modules'; - -// @public (undocumented) -export function createModule(options: ModuleOptions): Promise; - -// @public (undocumented) -export interface ModuleOptions { - // (undocumented) - config: Config; - // (undocumented) - logger: Logger; -} -``` diff --git a/plugins/catalog-graphql/catalog-info.yaml b/plugins/catalog-graphql/catalog-info.yaml deleted file mode 100644 index 202acc8c95..0000000000 --- a/plugins/catalog-graphql/catalog-info.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: backstage-plugin-catalog-graphql - title: '@backstage/plugin-catalog-graphql' - description: An experimental Backstage catalog GraphQL module -spec: - lifecycle: experimental - type: backstage-backend-plugin - owner: catalog-maintainers diff --git a/plugins/catalog-graphql/codegen.yml b/plugins/catalog-graphql/codegen.yml deleted file mode 100644 index d71c9a7017..0000000000 --- a/plugins/catalog-graphql/codegen.yml +++ /dev/null @@ -1,14 +0,0 @@ -overwrite: true -generates: - ./src/graphql/types.ts: - schema: ./src/schema.js - plugins: - - typescript - - typescript-resolvers - hooks: - afterOneFileWrite: - - eslint --fix - config: - allowParentTypeOverride: true - useIndexSignature: true - defaultMapper: Partial<{T}> diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json deleted file mode 100644 index aa4200ccae..0000000000 --- a/plugins/catalog-graphql/package.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "name": "@backstage/plugin-catalog-graphql", - "description": "Deprecated, consider using @frontside/backstage-plugin-graphql-backend instead", - "version": "0.4.1", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", - "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" - }, - "backstage": { - "role": "backend-plugin" - }, - "homepage": "https://backstage.io", - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "plugins/catalog-graphql" - }, - "keywords": [ - "backstage", - "graphql" - ], - "scripts": { - "start": "backstage-cli package start", - "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", - "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack", - "generate:types": "graphql-codegen", - "clean": "backstage-cli package clean" - }, - "dependencies": { - "@apollo/client": "^3.0.0", - "@apollo/server": "^4.0.0", - "@backstage/catalog-model": "workspace:^", - "@backstage/config": "workspace:^", - "@backstage/types": "workspace:^", - "graphql": "^16.0.0", - "graphql-modules": "^2.0.0", - "graphql-tag": "^2.11.0", - "graphql-type-json": "^0.3.2", - "node-fetch": "^2.6.7", - "winston": "^3.2.1" - }, - "peerDependencies": { - "react": "^16.13.1 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", - "react-router-dom": "6.0.0-beta.0 || ^6.3.0" - }, - "devDependencies": { - "@backstage/cli": "workspace:^", - "@backstage/test-utils": "workspace:^", - "@graphql-codegen/cli": "^3.0.0", - "@graphql-codegen/graphql-modules-preset": "^3.0.0", - "@graphql-codegen/typescript": "^3.0.0", - "@graphql-codegen/typescript-resolvers": "^3.0.0", - "@graphql-tools/schema": "^9.0.0", - "@types/react": "^16.13.1 || ^17.0.0", - "msw": "^1.0.0" - }, - "files": [ - "dist" - ] -} diff --git a/plugins/catalog-graphql/src/graphql/module.test.ts b/plugins/catalog-graphql/src/graphql/module.test.ts deleted file mode 100644 index d4589a2625..0000000000 --- a/plugins/catalog-graphql/src/graphql/module.test.ts +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { createModule } from './module'; -import { makeExecutableSchema } from '@graphql-tools/schema'; -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import { ConfigReader } from '@backstage/config'; -import { ReaderEntity } from '../service/client'; -import { createLogger } from 'winston'; -import { setupRequestMockHandlers } from '@backstage/test-utils'; -import { gql } from '@apollo/client'; -import { Module, createApplication, testkit } from 'graphql-modules'; - -describe('Catalog Module', () => { - const worker = setupServer(); - const mockCatalogBaseUrl = 'http://im.mock'; - const mockConfig = new ConfigReader({ - backend: { - baseUrl: mockCatalogBaseUrl, - }, - }); - - const createMockApplication = (module: Module) => { - const application = createApplication({ - modules: [module], - schemaBuilder(input) { - return makeExecutableSchema({ - ...input, - inheritResolversFromInterfaces: true, - }); - }, - }); - - return application; - }; - - setupRequestMockHandlers(worker); - - describe('Default Entity', () => { - beforeEach(() => { - const mockResponse: ReaderEntity[] = [ - { - apiVersion: 'something', - kind: 'Component', - metadata: { - annotations: {}, - etag: '123', - labels: {}, - name: 'Ben', - namespace: 'Blames', - uid: '123', - }, - spec: { - type: 'thing', - lifecycle: 'something', - owner: 'auser', - }, - }, - ]; - - worker.use( - rest.get(`${mockCatalogBaseUrl}/api/catalog/entities`, (_, res, ctx) => - res(ctx.status(200), ctx.json(mockResponse)), - ), - ); - }); - - it('should call the catalog client when requesting entities', async () => { - const app = createMockApplication( - await createModule({ - config: mockConfig, - logger: createLogger(), - }), - ); - - const result = await testkit.execute(app, { - document: gql` - query { - catalog { - list { - kind - apiVersion - metadata { - name - } - } - } - } - `, - }); - - const [catalogItem] = result.data?.catalog.list; - expect(catalogItem.kind).toBe('Component'); - expect(catalogItem.apiVersion).toBe('something'); - expect(catalogItem.metadata.name).toBe('Ben'); - }); - - it('Defaults to empty annotations when none are provided', async () => { - const mockResponse: ReaderEntity[] = [ - { - apiVersion: 'something', - kind: 'Component', - metadata: { - annotations: null as any, - etag: '123', - labels: {}, - name: 'Ben', - namespace: 'Blames', - uid: '123', - }, - spec: { - type: 'thing', - lifecycle: 'something', - owner: 'auser', - }, - }, - ]; - worker.use( - rest.get(`${mockCatalogBaseUrl}/api/catalog/entities`, (_, res, ctx) => - res(ctx.status(200), ctx.json(mockResponse)), - ), - ); - - const app = createMockApplication( - await createModule({ - config: mockConfig, - logger: createLogger(), - }), - ); - - const result = await testkit.execute(app, { - document: gql` - query { - catalog { - list { - metadata { - annotations - } - } - } - } - `, - }); - - const [catalogItem] = result.data?.catalog.list; - expect(catalogItem.metadata.annotations).toEqual({}); - }); - - it('Defaults to empty labels when none are provided', async () => { - const mockResponse: ReaderEntity[] = [ - { - apiVersion: 'something', - kind: 'Component', - metadata: { - annotations: {}, - etag: '123', - labels: null as any, - name: 'Ben', - namespace: 'Blames', - uid: '123', - }, - spec: { - type: 'thing', - lifecycle: 'something', - owner: 'auser', - }, - }, - ]; - worker.use( - rest.get(`${mockCatalogBaseUrl}/api/catalog/entities`, (_, res, ctx) => - res(ctx.status(200), ctx.json(mockResponse)), - ), - ); - - const app = createMockApplication( - await createModule({ - config: mockConfig, - logger: createLogger(), - }), - ); - - const result = await testkit.execute(app, { - document: gql` - query { - catalog { - list { - metadata { - labels - } - } - } - } - `, - }); - - const [catalogItem] = result.data?.catalog.list; - expect(catalogItem.metadata.labels).toEqual({}); - }); - it('Returns the correct record from the annotation dictionary', async () => { - const mockResponse: ReaderEntity[] = [ - { - apiVersion: 'something', - kind: 'Component', - metadata: { - annotations: { lob: 'bloben' }, - etag: '123', - labels: {}, - name: 'Ben', - namespace: 'Blames', - uid: '123', - }, - spec: { - type: 'thing', - lifecycle: 'something', - owner: 'auser', - }, - }, - ]; - worker.use( - rest.get(`${mockCatalogBaseUrl}/api/catalog/entities`, (_, res, ctx) => - res(ctx.status(200), ctx.json(mockResponse)), - ), - ); - - const app = createMockApplication( - await createModule({ - config: mockConfig, - logger: createLogger(), - }), - ); - - const result = await testkit.execute(app, { - document: gql` - query { - catalog { - list { - metadata { - test: annotation(name: "lob") - } - } - } - } - `, - }); - - const [catalogItem] = result.data?.catalog.list; - expect(catalogItem.metadata.test).toEqual('bloben'); - }); - it('Returns the correct record from the labels dictionary', async () => { - const mockResponse: ReaderEntity[] = [ - { - apiVersion: 'something', - kind: 'Component', - metadata: { - annotations: {}, - etag: '123', - labels: { lob2: 'bloben' }, - name: 'Ben', - namespace: 'Blames', - uid: '123', - }, - spec: { - type: 'thing', - lifecycle: 'something', - owner: 'auser', - }, - }, - ]; - worker.use( - rest.get(`${mockCatalogBaseUrl}/api/catalog/entities`, (_, res, ctx) => - res(ctx.status(200), ctx.json(mockResponse)), - ), - ); - - const app = createMockApplication( - await createModule({ - config: mockConfig, - logger: createLogger(), - }), - ); - - const result = await testkit.execute(app, { - document: gql` - query { - catalog { - list { - metadata { - test: label(name: "lob2") - } - } - } - } - `, - }); - - const [catalogItem] = result.data?.catalog.list; - expect(catalogItem.metadata.test).toEqual('bloben'); - }); - }); -}); diff --git a/plugins/catalog-graphql/src/graphql/module.ts b/plugins/catalog-graphql/src/graphql/module.ts deleted file mode 100644 index e27adbbaf1..0000000000 --- a/plugins/catalog-graphql/src/graphql/module.ts +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Logger } from 'winston'; -import { - createModule as createGraphQLModule, - Module, - gql, -} from 'graphql-modules'; -import { Resolvers, CatalogQuery } from './types'; -import { Config } from '@backstage/config'; -import { CatalogClient } from '../service/client'; -import GraphQLJSON, { GraphQLJSONObject } from 'graphql-type-json'; -import { Entity } from '@backstage/catalog-model'; -import typeDefs from '../schema'; - -/** @public */ -export interface ModuleOptions { - logger: Logger; - config: Config; -} - -/** @public */ -export async function createModule(options: ModuleOptions): Promise { - const catalogClient = new CatalogClient( - options.config.getString('backend.baseUrl'), - ); - - const resolvers: Resolvers = { - JSON: GraphQLJSON, - JSONObject: GraphQLJSONObject, - DefaultEntitySpec: { - raw: rootValue => { - const { entity } = rootValue as { entity: Entity }; - return entity.spec ?? null; - }, - }, - Query: { - catalog: () => ({} as CatalogQuery), - }, - CatalogQuery: { - list: async () => { - return await catalogClient.list(); - }, - }, - CatalogEntity: { - metadata: entity => ({ ...entity.metadata!, entity }), - spec: entity => ({ ...entity.spec!, entity }), - }, - EntityMetadata: { - __resolveType: rootValue => { - const { - entity: { kind }, - } = rootValue as { entity: Entity }; - - switch (kind) { - case 'Component': - return 'ComponentMetadata'; - case 'Template': - return 'TemplateMetadata'; - default: - return 'DefaultEntityMetadata'; - } - }, - annotation: (e, { name }) => e.annotations?.[name] ?? null, - labels: e => e.labels ?? {}, - annotations: e => e.annotations ?? {}, - label: (e, { name }) => e.labels?.[name] ?? null, - }, - EntitySpec: { - __resolveType: rootValue => { - const { - entity: { kind }, - } = rootValue as { entity: Entity }; - - switch (kind) { - case 'Component': - return 'ComponentEntitySpec'; - case 'Template': - return 'TemplateEntitySpec'; - default: - return 'DefaultEntitySpec'; - } - }, - }, - }; - - return createGraphQLModule({ - id: 'plugin-catalog-graphql', - typeDefs: gql(typeDefs), - resolvers, - }); -} diff --git a/plugins/catalog-graphql/src/graphql/types.ts b/plugins/catalog-graphql/src/graphql/types.ts deleted file mode 100644 index aecf2a1cd1..0000000000 --- a/plugins/catalog-graphql/src/graphql/types.ts +++ /dev/null @@ -1,544 +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 { - GraphQLResolveInfo, - GraphQLScalarType, - GraphQLScalarTypeConfig, -} from 'graphql'; - -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type Exact = { - [K in keyof T]: T[K]; -}; -export type MakeOptional = Omit & { - [SubKey in K]?: Maybe; -}; -export type MakeMaybe = Omit & { - [SubKey in K]: Maybe; -}; -export type Omit = Pick>; -export type RequireFields = { - [X in Exclude]?: T[X]; -} & { [P in K]-?: NonNullable }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: string; - String: string; - Boolean: boolean; - Int: number; - Float: number; - JSON: any; - JSONObject: any; -}; - -export type CatalogEntity = { - __typename?: 'CatalogEntity'; - apiVersion: Scalars['String']; - kind: Scalars['String']; - metadata?: Maybe; - spec: EntitySpec; -}; - -export type CatalogQuery = { - __typename?: 'CatalogQuery'; - list: Array; -}; - -export type ComponentEntitySpec = { - __typename?: 'ComponentEntitySpec'; - lifecycle: Scalars['String']; - owner: Scalars['String']; - type: Scalars['String']; -}; - -export type ComponentMetadata = EntityMetadata & { - __typename?: 'ComponentMetadata'; - annotation?: Maybe; - annotations: Scalars['JSONObject']; - etag: Scalars['String']; - label?: Maybe; - labels: Scalars['JSONObject']; - name: Scalars['String']; - relationships?: Maybe; - uid: Scalars['String']; -}; - -export type ComponentMetadataAnnotationArgs = { - name: Scalars['String']; -}; - -export type ComponentMetadataLabelArgs = { - name: Scalars['String']; -}; - -export type DefaultEntityMetadata = EntityMetadata & { - __typename?: 'DefaultEntityMetadata'; - annotation?: Maybe; - annotations: Scalars['JSONObject']; - etag: Scalars['String']; - label?: Maybe; - labels: Scalars['JSONObject']; - name: Scalars['String']; - uid: Scalars['String']; -}; - -export type DefaultEntityMetadataAnnotationArgs = { - name: Scalars['String']; -}; - -export type DefaultEntityMetadataLabelArgs = { - name: Scalars['String']; -}; - -export type DefaultEntitySpec = { - __typename?: 'DefaultEntitySpec'; - raw?: Maybe; -}; - -export type EntityMetadata = { - annotation?: Maybe; - annotations: Scalars['JSONObject']; - etag: Scalars['String']; - label?: Maybe; - labels: Scalars['JSONObject']; - name: Scalars['String']; - uid: Scalars['String']; -}; - -export type EntityMetadataAnnotationArgs = { - name: Scalars['String']; -}; - -export type EntityMetadataLabelArgs = { - name: Scalars['String']; -}; - -export type EntitySpec = - | ComponentEntitySpec - | DefaultEntitySpec - | TemplateEntitySpec; - -export type Query = { - __typename?: 'Query'; - catalog: CatalogQuery; -}; - -export type TemplateEntitySpec = { - __typename?: 'TemplateEntitySpec'; - path?: Maybe; - schema: Scalars['JSONObject']; - templater: Scalars['String']; - type: Scalars['String']; -}; - -export type TemplateMetadata = EntityMetadata & { - __typename?: 'TemplateMetadata'; - annotation?: Maybe; - annotations: Scalars['JSONObject']; - etag: Scalars['String']; - label?: Maybe; - labels: Scalars['JSONObject']; - name: Scalars['String']; - uid: Scalars['String']; - updatedBy?: Maybe; -}; - -export type TemplateMetadataAnnotationArgs = { - name: Scalars['String']; -}; - -export type TemplateMetadataLabelArgs = { - name: Scalars['String']; -}; - -export type WithIndex = TObject & Record; -export type ResolversObject = WithIndex; - -export type ResolverTypeWrapper = Promise | T; - -export type ResolverWithResolve = { - resolve: ResolverFn; -}; -export type Resolver = - | ResolverFn - | ResolverWithResolve; - -export type ResolverFn = ( - parent: TParent, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo, -) => Promise | TResult; - -export type SubscriptionSubscribeFn = ( - parent: TParent, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo, -) => AsyncIterable | Promise>; - -export type SubscriptionResolveFn = ( - parent: TParent, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo, -) => TResult | Promise; - -export interface SubscriptionSubscriberObject< - TResult, - TKey extends string, - TParent, - TContext, - TArgs, -> { - subscribe: SubscriptionSubscribeFn< - { [key in TKey]: TResult }, - TParent, - TContext, - TArgs - >; - resolve?: SubscriptionResolveFn< - TResult, - { [key in TKey]: TResult }, - TContext, - TArgs - >; -} - -export interface SubscriptionResolverObject { - subscribe: SubscriptionSubscribeFn; - resolve: SubscriptionResolveFn; -} - -export type SubscriptionObject< - TResult, - TKey extends string, - TParent, - TContext, - TArgs, -> = - | SubscriptionSubscriberObject - | SubscriptionResolverObject; - -export type SubscriptionResolver< - TResult, - TKey extends string, - TParent = {}, - TContext = {}, - TArgs = {}, -> = - | (( - ...args: any[] - ) => SubscriptionObject) - | SubscriptionObject; - -export type TypeResolveFn = ( - parent: TParent, - context: TContext, - info: GraphQLResolveInfo, -) => Maybe | Promise>; - -export type IsTypeOfResolverFn = ( - obj: T, - context: TContext, - info: GraphQLResolveInfo, -) => boolean | Promise; - -export type NextResolverFn = () => Promise; - -export type DirectiveResolverFn< - TResult = {}, - TParent = {}, - TContext = {}, - TArgs = {}, -> = ( - next: NextResolverFn, - parent: TParent, - args: TArgs, - context: TContext, - info: GraphQLResolveInfo, -) => TResult | Promise; - -/** Mapping between all available schema types and the resolvers types */ -export type ResolversTypes = ResolversObject<{ - Boolean: ResolverTypeWrapper>; - CatalogEntity: ResolverTypeWrapper< - Partial< - Omit & { spec: ResolversTypes['EntitySpec'] } - > - >; - CatalogQuery: ResolverTypeWrapper>; - ComponentEntitySpec: ResolverTypeWrapper>; - ComponentMetadata: ResolverTypeWrapper>; - DefaultEntityMetadata: ResolverTypeWrapper>; - DefaultEntitySpec: ResolverTypeWrapper>; - EntityMetadata: - | ResolversTypes['ComponentMetadata'] - | ResolversTypes['DefaultEntityMetadata'] - | ResolversTypes['TemplateMetadata']; - EntitySpec: Partial< - | ResolversTypes['ComponentEntitySpec'] - | ResolversTypes['DefaultEntitySpec'] - | ResolversTypes['TemplateEntitySpec'] - >; - Int: ResolverTypeWrapper>; - JSON: ResolverTypeWrapper>; - JSONObject: ResolverTypeWrapper>; - Query: ResolverTypeWrapper<{}>; - String: ResolverTypeWrapper>; - TemplateEntitySpec: ResolverTypeWrapper>; - TemplateMetadata: ResolverTypeWrapper>; -}>; - -/** Mapping between all available schema types and the resolvers parents */ -export type ResolversParentTypes = ResolversObject<{ - Boolean: Partial; - CatalogEntity: Partial< - Omit & { spec: ResolversParentTypes['EntitySpec'] } - >; - CatalogQuery: Partial; - ComponentEntitySpec: Partial; - ComponentMetadata: Partial; - DefaultEntityMetadata: Partial; - DefaultEntitySpec: Partial; - EntityMetadata: - | ResolversParentTypes['ComponentMetadata'] - | ResolversParentTypes['DefaultEntityMetadata'] - | ResolversParentTypes['TemplateMetadata']; - EntitySpec: Partial< - | ResolversParentTypes['ComponentEntitySpec'] - | ResolversParentTypes['DefaultEntitySpec'] - | ResolversParentTypes['TemplateEntitySpec'] - >; - Int: Partial; - JSON: Partial; - JSONObject: Partial; - Query: {}; - String: Partial; - TemplateEntitySpec: Partial; - TemplateMetadata: Partial; -}>; - -export type CatalogEntityResolvers< - ContextType = any, - ParentType = ResolversParentTypes['CatalogEntity'], -> = ResolversObject<{ - apiVersion?: Resolver; - kind?: Resolver; - metadata?: Resolver< - Maybe, - ParentType, - ContextType - >; - spec?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}>; - -export type CatalogQueryResolvers< - ContextType = any, - ParentType = ResolversParentTypes['CatalogQuery'], -> = ResolversObject<{ - list?: Resolver< - Array, - ParentType, - ContextType - >; - __isTypeOf?: IsTypeOfResolverFn; -}>; - -export type ComponentEntitySpecResolvers< - ContextType = any, - ParentType = ResolversParentTypes['ComponentEntitySpec'], -> = ResolversObject<{ - lifecycle?: Resolver; - owner?: Resolver; - type?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}>; - -export type ComponentMetadataResolvers< - ContextType = any, - ParentType = ResolversParentTypes['ComponentMetadata'], -> = ResolversObject<{ - annotation?: Resolver< - Maybe, - ParentType, - ContextType, - RequireFields - >; - annotations?: Resolver; - etag?: Resolver; - label?: Resolver< - Maybe, - ParentType, - ContextType, - RequireFields - >; - labels?: Resolver; - name?: Resolver; - relationships?: Resolver< - Maybe, - ParentType, - ContextType - >; - uid?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}>; - -export type DefaultEntityMetadataResolvers< - ContextType = any, - ParentType = ResolversParentTypes['DefaultEntityMetadata'], -> = ResolversObject<{ - annotation?: Resolver< - Maybe, - ParentType, - ContextType, - RequireFields - >; - annotations?: Resolver; - etag?: Resolver; - label?: Resolver< - Maybe, - ParentType, - ContextType, - RequireFields - >; - labels?: Resolver; - name?: Resolver; - uid?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}>; - -export type DefaultEntitySpecResolvers< - ContextType = any, - ParentType = ResolversParentTypes['DefaultEntitySpec'], -> = ResolversObject<{ - raw?: Resolver, ParentType, ContextType>; - __isTypeOf?: IsTypeOfResolverFn; -}>; - -export type EntityMetadataResolvers< - ContextType = any, - ParentType = ResolversParentTypes['EntityMetadata'], -> = ResolversObject<{ - __resolveType: TypeResolveFn< - 'ComponentMetadata' | 'DefaultEntityMetadata' | 'TemplateMetadata', - ParentType, - ContextType - >; - annotation?: Resolver< - Maybe, - ParentType, - ContextType, - RequireFields - >; - annotations?: Resolver; - etag?: Resolver; - label?: Resolver< - Maybe, - ParentType, - ContextType, - RequireFields - >; - labels?: Resolver; - name?: Resolver; - uid?: Resolver; -}>; - -export type EntitySpecResolvers< - ContextType = any, - ParentType = ResolversParentTypes['EntitySpec'], -> = ResolversObject<{ - __resolveType: TypeResolveFn< - 'ComponentEntitySpec' | 'DefaultEntitySpec' | 'TemplateEntitySpec', - ParentType, - ContextType - >; -}>; - -export interface JsonScalarConfig - extends GraphQLScalarTypeConfig { - name: 'JSON'; -} - -export interface JsonObjectScalarConfig - extends GraphQLScalarTypeConfig { - name: 'JSONObject'; -} - -export type QueryResolvers< - ContextType = any, - ParentType = ResolversParentTypes['Query'], -> = ResolversObject<{ - catalog?: Resolver; -}>; - -export type TemplateEntitySpecResolvers< - ContextType = any, - ParentType = ResolversParentTypes['TemplateEntitySpec'], -> = ResolversObject<{ - path?: Resolver, ParentType, ContextType>; - schema?: Resolver; - templater?: Resolver; - type?: Resolver; - __isTypeOf?: IsTypeOfResolverFn; -}>; - -export type TemplateMetadataResolvers< - ContextType = any, - ParentType = ResolversParentTypes['TemplateMetadata'], -> = ResolversObject<{ - annotation?: Resolver< - Maybe, - ParentType, - ContextType, - RequireFields - >; - annotations?: Resolver; - etag?: Resolver; - label?: Resolver< - Maybe, - ParentType, - ContextType, - RequireFields - >; - labels?: Resolver; - name?: Resolver; - uid?: Resolver; - updatedBy?: Resolver< - Maybe, - ParentType, - ContextType - >; - __isTypeOf?: IsTypeOfResolverFn; -}>; - -export type Resolvers = ResolversObject<{ - CatalogEntity?: CatalogEntityResolvers; - CatalogQuery?: CatalogQueryResolvers; - ComponentEntitySpec?: ComponentEntitySpecResolvers; - ComponentMetadata?: ComponentMetadataResolvers; - DefaultEntityMetadata?: DefaultEntityMetadataResolvers; - DefaultEntitySpec?: DefaultEntitySpecResolvers; - EntityMetadata?: EntityMetadataResolvers; - EntitySpec?: EntitySpecResolvers; - JSON?: GraphQLScalarType; - JSONObject?: GraphQLScalarType; - Query?: QueryResolvers; - TemplateEntitySpec?: TemplateEntitySpecResolvers; - TemplateMetadata?: TemplateMetadataResolvers; -}>; diff --git a/plugins/catalog-graphql/src/schema.js b/plugins/catalog-graphql/src/schema.js deleted file mode 100644 index cf6ccf3017..0000000000 --- a/plugins/catalog-graphql/src/schema.js +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const schema = /* GraphQL */ ` - scalar JSON - scalar JSONObject - - interface EntityMetadata { - name: String! - annotations: JSONObject! - annotation(name: String!): JSON - labels: JSONObject! - label(name: String!): JSON - uid: String! - etag: String! - } - - type DefaultEntityMetadata implements EntityMetadata { - name: String! - annotations: JSONObject! - annotation(name: String!): JSON - labels: JSONObject! - label(name: String!): JSON - uid: String! - etag: String! - } - - type ComponentMetadata implements EntityMetadata { - name: String! - annotations: JSONObject! - annotation(name: String!): JSON - labels: JSONObject! - label(name: String!): JSON - uid: String! - etag: String! - # mock field to prove extensions working - relationships: String - } - - type TemplateMetadata implements EntityMetadata { - name: String! - annotations: JSONObject! - annotation(name: String!): JSON - labels: JSONObject! - label(name: String!): JSON - uid: String! - etag: String! - # mock field to prove extensions working - updatedBy: String - } - - # TODO: move this definition into plugin-scaffolder-graphql - type TemplateEntitySpec { - type: String! - path: String - schema: JSONObject! - templater: String! - } - - type ComponentEntitySpec { - type: String! - lifecycle: String! - owner: String! - } - - type DefaultEntitySpec { - raw: JSONObject - } - - union EntitySpec = - DefaultEntitySpec - | TemplateEntitySpec - | ComponentEntitySpec - - type CatalogEntity { - apiVersion: String! - kind: String! - metadata: EntityMetadata - spec: EntitySpec! - } - - type CatalogQuery { - list: [CatalogEntity!]! - } - - type Query { - catalog: CatalogQuery! - } -`; - -export default schema; diff --git a/plugins/catalog-graphql/src/service/client.test.ts b/plugins/catalog-graphql/src/service/client.test.ts deleted file mode 100644 index 72041725a3..0000000000 --- a/plugins/catalog-graphql/src/service/client.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { CatalogClient } from './client'; -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import { setupRequestMockHandlers } from '@backstage/test-utils'; - -describe('Catalog GraphQL Module', () => { - const worker = setupServer(); - setupRequestMockHandlers(worker); - - const baseUrl = 'http://localhost:1234'; - - it('will return the entities', async () => { - const expectedResponse = [{ id: 'something' }]; - - worker.use( - rest.get(`${baseUrl}/api/catalog/entities`, (_, res, ctx) => - res(ctx.status(200), ctx.json(expectedResponse)), - ), - ); - - const client = new CatalogClient(baseUrl); - - const response = await client.list(); - - expect(response).toEqual(expectedResponse); - }); - - it('throws an error with the text', async () => { - const expectedResponse = 'something broke'; - - worker.use( - rest.get(`${baseUrl}/api/catalog/entities`, (_, res, ctx) => - res(ctx.status(500), ctx.text(expectedResponse)), - ), - ); - - const client = new CatalogClient(baseUrl); - - await expect(() => client.list()).rejects.toThrow(expectedResponse); - }); -}); diff --git a/plugins/catalog-graphql/src/service/client.ts b/plugins/catalog-graphql/src/service/client.ts deleted file mode 100644 index c6a5cff140..0000000000 --- a/plugins/catalog-graphql/src/service/client.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Entity, EntityMeta } from '@backstage/catalog-model'; -import fetch from 'node-fetch'; - -export interface ReaderEntityMeta extends EntityMeta { - uid: string; - etag: string; - namespace: string; - annotations: Record; - labels: Record; -} - -export interface ReaderEntity extends Entity { - metadata: ReaderEntityMeta; -} - -export class CatalogClient { - constructor(private baseUrl: string) {} - - async list(): Promise { - const res = await fetch(`${this.baseUrl}/api/catalog/entities`); - - if (!res.ok) { - // todo(blam): need some better way to handle errors here - // experiment with throwing the input errors etc and having graphql versions of that - throw new Error(await res.text()); - } - - const entities = (await res.json()) as ReaderEntity[]; - return entities; - } -} diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index b5471762f4..df10c3e57b 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,69 @@ # @backstage/plugin-catalog-import +## 0.10.4-next.3 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-catalog-common@1.0.18 + +## 0.10.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + +## 0.10.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + +## 0.10.4-next.0 + +### Patch Changes + +- 03d0b6dcdc: The `convertLegacyRouteRef` utility used by the alpha exports is now imported from `@backstage/core-compat-api`. +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + ## 0.10.2 ### Patch Changes diff --git a/plugins/catalog-import/alpha-api-report.md b/plugins/catalog-import/api-report-alpha.md similarity index 100% rename from plugins/catalog-import/alpha-api-report.md rename to plugins/catalog-import/api-report-alpha.md diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 6cb369cf47..f40345bafb 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-import", "description": "A Backstage plugin the helps you import entities into your catalog", - "version": "0.10.2", + "version": "0.10.4-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-import/src/alpha.tsx b/plugins/catalog-import/src/alpha.tsx index 18ddda2ceb..858e4fa91b 100644 --- a/plugins/catalog-import/src/alpha.tsx +++ b/plugins/catalog-import/src/alpha.tsx @@ -20,7 +20,10 @@ import { discoveryApiRef, identityApiRef, } from '@backstage/core-plugin-api'; -import { convertLegacyRouteRef } from '@backstage/core-compat-api'; +import { + compatWrapper, + convertLegacyRouteRef, +} from '@backstage/core-compat-api'; import { createApiExtension, createPageExtension, @@ -38,10 +41,12 @@ import { catalogApiRef } from '@backstage/plugin-catalog-react'; // TODO: It's currently possible to override the import page with a custom one. We need to decide // whether this type of override is typically done with an input or by overriding the entire extension. const CatalogImportPageExtension = createPageExtension({ - id: 'plugin.catalog-import.page', defaultPath: '/catalog-import', routeRef: convertLegacyRouteRef(rootRouteRef), - loader: () => import('./components/ImportPage').then(m => ), + loader: () => + import('./components/ImportPage').then(m => + compatWrapper(), + ), }); const CatalogImportService = createApiExtension({ diff --git a/plugins/catalog-node/CHANGELOG.md b/plugins/catalog-node/CHANGELOG.md index c93baeb66d..82692baf4a 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-catalog-node +## 1.6.0-next.2 + +### Minor Changes + +- a168507: Added `EntitiesSearchFilter` and `EntityFilter` from `@backstage/plugin-catalog-backend`, for reuse +- 7804597: Permission rules can now be added for the Catalog plugin through the `CatalogPermissionExtensionPoint` interface. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## 1.5.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + +## 1.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + ## 1.5.0 ### Minor Changes diff --git a/plugins/catalog-node/alpha-api-report.md b/plugins/catalog-node/api-report-alpha.md similarity index 65% rename from plugins/catalog-node/alpha-api-report.md rename to plugins/catalog-node/api-report-alpha.md index c4dc6b12e1..74339b1bc9 100644 --- a/plugins/catalog-node/alpha-api-report.md +++ b/plugins/catalog-node/api-report-alpha.md @@ -5,8 +5,12 @@ ```ts import { CatalogApi } from '@backstage/catalog-client'; import { CatalogProcessor } from '@backstage/plugin-catalog-node'; +import { EntitiesSearchFilter } from '@backstage/plugin-catalog-node'; +import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-node'; import { ExtensionPoint } from '@backstage/backend-plugin-api'; +import { PermissionRule } from '@backstage/plugin-permission-node'; +import { PermissionRuleParams } from '@backstage/plugin-permission-common'; import { PlaceholderResolver } from '@backstage/plugin-catalog-node'; import { ScmLocationAnalyzer } from '@backstage/plugin-catalog-node'; import { ServiceRef } from '@backstage/backend-plugin-api'; @@ -20,6 +24,24 @@ export interface CatalogAnalysisExtensionPoint { // @alpha (undocumented) export const catalogAnalysisExtensionPoint: ExtensionPoint; +// @alpha (undocumented) +export interface CatalogPermissionExtensionPoint { + // (undocumented) + addPermissionRules( + ...rules: Array< + CatalogPermissionRuleInput | Array + > + ): void; +} + +// @alpha (undocumented) +export const catalogPermissionExtensionPoint: ExtensionPoint; + +// @alpha (undocumented) +export type CatalogPermissionRuleInput< + TParams extends PermissionRuleParams = PermissionRuleParams, +> = PermissionRule; + // @alpha (undocumented) export interface CatalogProcessingExtensionPoint { // (undocumented) diff --git a/plugins/catalog-node/api-report.md b/plugins/catalog-node/api-report.md index ef2c09e61f..a4ba95073f 100644 --- a/plugins/catalog-node/api-report.md +++ b/plugins/catalog-node/api-report.md @@ -105,6 +105,25 @@ export type DeferredEntity = { locationKey?: string; }; +// @public +export type EntitiesSearchFilter = { + key: string; + values?: string[]; +}; + +// @public +export type EntityFilter = + | { + allOf: EntityFilter[]; + } + | { + anyOf: EntityFilter[]; + } + | { + not: EntityFilter; + } + | EntitiesSearchFilter; + // @public export interface EntityProvider { connect(connection: EntityProviderConnection): Promise; diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 0d5b56cbe6..d76092b076 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-node", "description": "The plugin-catalog-node module for @backstage/plugin-catalog-backend", - "version": "1.5.0", + "version": "1.6.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -47,6 +47,8 @@ "@backstage/catalog-model": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", + "@backstage/plugin-permission-common": "workspace:^", + "@backstage/plugin-permission-node": "workspace:^", "@backstage/types": "workspace:^" }, "devDependencies": { diff --git a/plugins/catalog-node/src/alpha.ts b/plugins/catalog-node/src/alpha.ts index cec1a0eedb..3e958d1df1 100644 --- a/plugins/catalog-node/src/alpha.ts +++ b/plugins/catalog-node/src/alpha.ts @@ -19,3 +19,6 @@ export type { CatalogProcessingExtensionPoint } from './extensions'; export { catalogProcessingExtensionPoint } from './extensions'; export type { CatalogAnalysisExtensionPoint } from './extensions'; export { catalogAnalysisExtensionPoint } from './extensions'; +export type { CatalogPermissionRuleInput } from './extensions'; +export type { CatalogPermissionExtensionPoint } from './extensions'; +export { catalogPermissionExtensionPoint } from './extensions'; diff --git a/plugins/catalog-node/src/api/common.ts b/plugins/catalog-node/src/api/common.ts index c91aeca2d9..7f9bd3eabf 100644 --- a/plugins/catalog-node/src/api/common.ts +++ b/plugins/catalog-node/src/api/common.ts @@ -52,3 +52,36 @@ export type EntityRelationSpec = { */ target: CompoundEntityRef; }; + +/** + * A filter expression for entities. + * + * @public + */ +export type EntityFilter = + | { allOf: EntityFilter[] } + | { anyOf: EntityFilter[] } + | { not: EntityFilter } + | EntitiesSearchFilter; + +/** + * Matches rows in the search table. + * + * @public + */ +export type EntitiesSearchFilter = { + /** + * The key to match on. + * + * Matches are always case insensitive. + */ + key: string; + + /** + * Match on plain equality of values. + * + * Match on values that are equal to any of the given array items. Matches are + * always case insensitive. + */ + values?: string[]; +}; diff --git a/plugins/catalog-node/src/api/index.ts b/plugins/catalog-node/src/api/index.ts index 66e8d6bd21..292a6cd872 100644 --- a/plugins/catalog-node/src/api/index.ts +++ b/plugins/catalog-node/src/api/index.ts @@ -15,7 +15,12 @@ */ export { processingResult } from './processingResult'; -export type { EntityRelationSpec, LocationSpec } from './common'; +export type { + EntityRelationSpec, + LocationSpec, + EntitiesSearchFilter, + EntityFilter, +} from './common'; export type { CatalogProcessor, CatalogProcessorParser, diff --git a/plugins/catalog-node/src/extensions.ts b/plugins/catalog-node/src/extensions.ts index 247ef142ad..7aa9264030 100644 --- a/plugins/catalog-node/src/extensions.ts +++ b/plugins/catalog-node/src/extensions.ts @@ -13,13 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { createExtensionPoint } from '@backstage/backend-plugin-api'; +import { Entity } from '@backstage/catalog-model'; import { - EntityProvider, CatalogProcessor, + EntitiesSearchFilter, + EntityProvider, PlaceholderResolver, ScmLocationAnalyzer, } from '@backstage/plugin-catalog-node'; +import { PermissionRuleParams } from '@backstage/plugin-permission-common'; +import { PermissionRule } from '@backstage/plugin-permission-node'; /** * @alpha @@ -56,3 +61,29 @@ export const catalogAnalysisExtensionPoint = createExtensionPoint({ id: 'catalog.analysis', }); + +/** + * @alpha + */ +export type CatalogPermissionRuleInput< + TParams extends PermissionRuleParams = PermissionRuleParams, +> = PermissionRule; + +/** + * @alpha + */ +export interface CatalogPermissionExtensionPoint { + addPermissionRules( + ...rules: Array< + CatalogPermissionRuleInput | Array + > + ): void; +} + +/** + * @alpha + */ +export const catalogPermissionExtensionPoint = + createExtensionPoint({ + id: 'catalog.permission', + }); diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 9d656e6438..3f87a2647e 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,75 @@ # @backstage/plugin-catalog-react +## 1.9.2-next.2 + +### Patch Changes + +- 8f5d6c1: Updates to the `/alpha` exports to match the extension input wrapping change. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-react@0.4.18-next.1 + +## 1.9.2-next.1 + +### Patch Changes + +- 53600976bb: Ensure that passed-in icons are taken advantage of in the presentation API +- 08d9e67199: Add default icon for kind resource. +- a5a04739e1: Internal refactor of alpha exports due to a change in how extension factories are defined. +- e223f2264d: Breaking alpha-API change to entity visibility filter functions to accept a bare entity as their first argument, instead of an object with an entity property. + + Functions that accept such filters now also support the string expression form of filters. + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + +## 1.9.2-next.0 + +### Patch Changes + +- 8587f067d2: Added pagination support to `EntityListProvider`. +- aaa6fb3bc9: Minor updates for TypeScript 5.2.2+ compatibility +- 4d9e3b39e4: Register component overrides in the global `OverrideComponentNameToClassKeys` provided by `@backstage/theme`. This will in turn will provide component style override types for `createUnifiedTheme`. +- eee0ff2946: Fixed a issue where `CatalogPage` wasn't using the chosen `initiallySelectedFilter` as intended. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + ## 1.9.0 ### Minor Changes diff --git a/plugins/catalog-react/alpha-api-report.md b/plugins/catalog-react/api-report-alpha.md similarity index 67% rename from plugins/catalog-react/alpha-api-report.md rename to plugins/catalog-react/api-report-alpha.md index ed851f810a..27ca640bbc 100644 --- a/plugins/catalog-react/alpha-api-report.md +++ b/plugins/catalog-react/api-report-alpha.md @@ -8,8 +8,8 @@ import { AnyExtensionInputMap } from '@backstage/frontend-plugin-api'; import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; import { Entity } from '@backstage/catalog-model'; -import { Extension } from '@backstage/frontend-plugin-api'; -import { ExtensionInputValues } from '@backstage/frontend-plugin-api'; +import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; +import { ResolvedExtensionInputs } from '@backstage/frontend-plugin-api'; import { ResourcePermission } from '@backstage/plugin-permission-common'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -17,31 +17,30 @@ import { RouteRef } from '@backstage/frontend-plugin-api'; export function createEntityCardExtension< TInputs extends AnyExtensionInputMap, >(options: { - id: string; + namespace?: string; + name?: string; attachTo?: { id: string; input: string; }; disabled?: boolean; inputs?: TInputs; - filter?: (ctx: { entity: Entity }) => boolean; - loader: (options: { - inputs: Expand>; - }) => Promise; -}): Extension<{ filter?: - | { - isKind?: string | undefined; - isType?: string | undefined; - }[] - | undefined; + | typeof entityFilterFunctionExtensionDataRef.T + | typeof entityFilterExpressionExtensionDataRef.T; + loader: (options: { + inputs: Expand>; + }) => Promise; +}): ExtensionDefinition<{ + filter?: string | undefined; }>; // @alpha (undocumented) export function createEntityContentExtension< TInputs extends AnyExtensionInputMap, >(options: { - id: string; + namespace?: string; + name?: string; attachTo?: { id: string; input: string; @@ -51,19 +50,16 @@ export function createEntityContentExtension< routeRef?: RouteRef; defaultPath: string; defaultTitle: string; - filter?: (ctx: { entity: Entity }) => boolean; + filter?: + | typeof entityFilterFunctionExtensionDataRef.T + | typeof entityFilterExpressionExtensionDataRef.T; loader: (options: { - inputs: Expand>; + inputs: Expand>; }) => Promise; -}): Extension<{ +}): ExtensionDefinition<{ title: string; path: string; - filter?: - | { - isKind?: string | undefined; - isType?: string | undefined; - }[] - | undefined; + filter?: string | undefined; }>; // @alpha (undocumented) @@ -73,8 +69,14 @@ export const entityContentTitleExtensionDataRef: ConfigurableExtensionDataRef< >; // @alpha (undocumented) -export const entityFilterExtensionDataRef: ConfigurableExtensionDataRef< - (ctx: { entity: Entity }) => boolean, +export const entityFilterExpressionExtensionDataRef: ConfigurableExtensionDataRef< + string, + {} +>; + +// @alpha (undocumented) +export const entityFilterFunctionExtensionDataRef: ConfigurableExtensionDataRef< + (entity: Entity) => boolean, {} >; diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index e84fa9815c..8c6b3a729f 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -284,13 +284,26 @@ export type EntityListContextProps< queryParameters: Partial>; loading: boolean; error?: Error; + pageInfo?: { + next?: () => void; + prev?: () => void; + }; }; // @public export const EntityListProvider: ( - props: PropsWithChildren<{}>, + props: EntityListProviderProps, ) => React_2.JSX.Element; +// @public (undocumented) +export type EntityListProviderProps = PropsWithChildren<{ + pagination?: + | boolean + | { + limit?: number; + }; +}>; + // @public (undocumented) export type EntityLoadingStatus = { entity?: TEntity; diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index c35710187d..4761b9abbc 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-react", "description": "A frontend library that helps other Backstage plugins interact with the catalog", - "version": "1.9.0", + "version": "1.9.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-react/src/alpha.tsx b/plugins/catalog-react/src/alpha.tsx index 8d0436e4be..8f7144681b 100644 --- a/plugins/catalog-react/src/alpha.tsx +++ b/plugins/catalog-react/src/alpha.tsx @@ -14,106 +14,75 @@ * limitations under the License. */ -import React, { lazy } from 'react'; import { AnyExtensionInputMap, ExtensionBoundary, - ExtensionInputValues, + ResolvedExtensionInputs, RouteRef, coreExtensionData, createExtension, createExtensionDataRef, createSchemaFromZod, } from '@backstage/frontend-plugin-api'; +import React, { lazy } from 'react'; +import { Entity } from '@backstage/catalog-model'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { Expand } from '../../../packages/frontend-plugin-api/src/types'; -import { Entity } from '@backstage/catalog-model'; -export { isOwnerOf } from './utils'; export { useEntityPermission } from './hooks/useEntityPermission'; +export { isOwnerOf } from './utils'; /** @alpha */ export const entityContentTitleExtensionDataRef = createExtensionDataRef('plugin.catalog.entity.content.title'); /** @alpha */ -export const entityFilterExtensionDataRef = createExtensionDataRef< - (ctx: { entity: Entity }) => boolean ->('plugin.catalog.entity.filter'); +export const entityFilterFunctionExtensionDataRef = createExtensionDataRef< + (entity: Entity) => boolean +>('plugin.catalog.entity.filter.fn'); -function applyFilter(a?: string, b?: string): boolean { - if (!a) { - return true; - } - return a.toLocaleLowerCase('en-US') === b?.toLocaleLowerCase('en-US'); -} - -// TODO: Only two hardcoded isKind and isType filters are available for now -// This is just an initial config filter implementation and needs to be revisited -function buildFilter( - config: { filter?: { isKind?: string; isType?: string }[] }, - filterFunc?: (ctx: { entity: Entity }) => boolean, -) { - return (ctx: { entity: Entity }) => { - const configuredFilterMatch = config.filter?.some(filter => { - const kindMatch = applyFilter(filter.isKind, ctx.entity.kind); - const typeMatch = applyFilter( - filter.isType, - ctx.entity.spec?.type?.toString(), - ); - return kindMatch && typeMatch; - }); - if (configuredFilterMatch) { - return true; - } - if (filterFunc) { - return filterFunc(ctx); - } - return true; - }; -} +/** @alpha */ +export const entityFilterExpressionExtensionDataRef = + createExtensionDataRef('plugin.catalog.entity.filter.expression'); // TODO: Figure out how to merge with provided config schema /** @alpha */ export function createEntityCardExtension< TInputs extends AnyExtensionInputMap, >(options: { - id: string; + namespace?: string; + name?: string; attachTo?: { id: string; input: string }; disabled?: boolean; inputs?: TInputs; - filter?: (ctx: { entity: Entity }) => boolean; + filter?: + | typeof entityFilterFunctionExtensionDataRef.T + | typeof entityFilterExpressionExtensionDataRef.T; loader: (options: { - inputs: Expand>; + inputs: Expand>; }) => Promise; }) { - const id = `entity.cards.${options.id}`; - return createExtension({ - id, + kind: 'entity-card', + namespace: options.namespace, + name: options.name, attachTo: options.attachTo ?? { - id: 'entity.content.overview', + id: 'entity-content:catalog/overview', input: 'cards', }, disabled: options.disabled ?? true, output: { element: coreExtensionData.reactElement, - filter: entityFilterExtensionDataRef, + filterFunction: entityFilterFunctionExtensionDataRef.optional(), + filterExpression: entityFilterExpressionExtensionDataRef.optional(), }, inputs: options.inputs, configSchema: createSchemaFromZod(z => z.object({ - filter: z - .array( - z.object({ - isKind: z.string().optional(), - isType: z.string().optional(), - }), - ) - .optional(), + filter: z.string().optional(), }), ), - factory({ config, inputs, source }) { + factory({ config, inputs, node }) { const ExtensionComponent = lazy(() => options .loader({ inputs }) @@ -122,11 +91,11 @@ export function createEntityCardExtension< return { element: ( - + ), - filter: buildFilter(config, options.filter), + ...mergeFilters({ config, options }), }; }, }); @@ -136,24 +105,27 @@ export function createEntityCardExtension< export function createEntityContentExtension< TInputs extends AnyExtensionInputMap, >(options: { - id: string; + namespace?: string; + name?: string; attachTo?: { id: string; input: string }; disabled?: boolean; inputs?: TInputs; routeRef?: RouteRef; defaultPath: string; defaultTitle: string; - filter?: (ctx: { entity: Entity }) => boolean; + filter?: + | typeof entityFilterFunctionExtensionDataRef.T + | typeof entityFilterExpressionExtensionDataRef.T; loader: (options: { - inputs: Expand>; + inputs: Expand>; }) => Promise; }) { - const id = `entity.content.${options.id}`; - return createExtension({ - id, + kind: 'entity-content', + namespace: options.namespace, + name: options.name, attachTo: options.attachTo ?? { - id: 'plugin.catalog.page.entity', + id: 'page:catalog/entity', input: 'contents', }, disabled: options.disabled ?? true, @@ -162,24 +134,18 @@ export function createEntityContentExtension< path: coreExtensionData.routePath, routeRef: coreExtensionData.routeRef.optional(), title: entityContentTitleExtensionDataRef, - filter: entityFilterExtensionDataRef, + filterFunction: entityFilterFunctionExtensionDataRef.optional(), + filterExpression: entityFilterExpressionExtensionDataRef.optional(), }, inputs: options.inputs, configSchema: createSchemaFromZod(z => z.object({ path: z.string().default(options.defaultPath), title: z.string().default(options.defaultTitle), - filter: z - .array( - z.object({ - isKind: z.string().optional(), - isType: z.string().optional(), - }), - ) - .optional(), + filter: z.string().optional(), }), ), - factory({ config, inputs, source }) { + factory({ config, inputs, node }) { const ExtensionComponent = lazy(() => options .loader({ inputs }) @@ -191,12 +157,39 @@ export function createEntityContentExtension< title: config.title, routeRef: options.routeRef, element: ( - + ), - filter: buildFilter(config, options.filter), + ...mergeFilters({ config, options }), }; }, }); } + +/** + * Decides what filter outputs to produce, given some options and config + */ +function mergeFilters(inputs: { + options: { + filter?: + | typeof entityFilterFunctionExtensionDataRef.T + | typeof entityFilterExpressionExtensionDataRef.T; + }; + config: { + filter?: string; + }; +}): { + filterFunction?: typeof entityFilterFunctionExtensionDataRef.T; + filterExpression?: typeof entityFilterExpressionExtensionDataRef.T; +} { + const { options, config } = inputs; + if (config.filter) { + return { filterExpression: config.filter }; + } else if (typeof options.filter === 'string') { + return { filterExpression: options.filter }; + } else if (typeof options.filter === 'function') { + return { filterFunction: options.filter }; + } + return {}; +} diff --git a/plugins/catalog-react/src/apis/EntityPresentationApi/defaultEntityPresentation.test.ts b/plugins/catalog-react/src/apis/EntityPresentationApi/defaultEntityPresentation.test.ts index ea755dfebc..5985a50b0d 100644 --- a/plugins/catalog-react/src/apis/EntityPresentationApi/defaultEntityPresentation.test.ts +++ b/plugins/catalog-react/src/apis/EntityPresentationApi/defaultEntityPresentation.test.ts @@ -37,7 +37,7 @@ describe('defaultEntityPresentation', () => { entityRef: 'component:default/test', primaryTitle: 'test', secondaryTitle: 'component:default/test | type | desc', - Icon: expect.anything(), + Icon: undefined, }); expect( @@ -58,7 +58,7 @@ describe('defaultEntityPresentation', () => { entityRef: 'component:default/test', primaryTitle: 'title', secondaryTitle: 'component:default/test | type | desc', - Icon: expect.anything(), + Icon: undefined, }); expect( @@ -82,7 +82,7 @@ describe('defaultEntityPresentation', () => { entityRef: 'component:default/test', primaryTitle: 'displayName', secondaryTitle: 'component:default/test | type | desc', - Icon: expect.anything(), + Icon: undefined, }); }); @@ -96,7 +96,7 @@ describe('defaultEntityPresentation', () => { entityRef: 'component:default/test', primaryTitle: 'test', secondaryTitle: 'component:default/test', - Icon: expect.anything(), + Icon: undefined, }); }); @@ -107,7 +107,7 @@ describe('defaultEntityPresentation', () => { entityRef: 'unknown:default/unknown', primaryTitle: 'unknown', secondaryTitle: 'unknown:default/unknown', - Icon: expect.anything(), + Icon: undefined, }); }); }); @@ -118,7 +118,7 @@ describe('defaultEntityPresentation', () => { entityRef: 'component:default/test', primaryTitle: 'test', secondaryTitle: 'component:default/test', - Icon: expect.anything(), + Icon: undefined, }); expect( @@ -129,7 +129,7 @@ describe('defaultEntityPresentation', () => { entityRef: 'component:default/test', primaryTitle: 'component:test', secondaryTitle: 'component:default/test', - Icon: expect.anything(), + Icon: undefined, }); expect( @@ -140,7 +140,7 @@ describe('defaultEntityPresentation', () => { entityRef: 'component:default/test', primaryTitle: 'default/test', secondaryTitle: 'component:default/test', - Icon: expect.anything(), + Icon: undefined, }); }); @@ -149,14 +149,14 @@ describe('defaultEntityPresentation', () => { entityRef: 'unknown:default/unknown', primaryTitle: 'unknown', secondaryTitle: 'unknown:default/unknown', - Icon: expect.anything(), + Icon: undefined, }); expect(defaultEntityPresentation('name')).toEqual({ entityRef: 'unknown:default/name', primaryTitle: 'name', secondaryTitle: 'unknown:default/name', - Icon: expect.anything(), + Icon: undefined, }); }); }); @@ -173,7 +173,7 @@ describe('defaultEntityPresentation', () => { entityRef: 'component:default/test', primaryTitle: 'test', secondaryTitle: 'component:default/test', - Icon: expect.anything(), + Icon: undefined, }); expect( @@ -187,7 +187,7 @@ describe('defaultEntityPresentation', () => { entityRef: 'component:default/test', primaryTitle: 'component:test', secondaryTitle: 'component:default/test', - Icon: expect.anything(), + Icon: undefined, }); expect( @@ -201,7 +201,7 @@ describe('defaultEntityPresentation', () => { entityRef: 'component:default/test', primaryTitle: 'default/test', secondaryTitle: 'component:default/test', - Icon: expect.anything(), + Icon: undefined, }); }); @@ -217,14 +217,14 @@ describe('defaultEntityPresentation', () => { entityRef: 'component:default/test', primaryTitle: 'default/test', secondaryTitle: 'component:default/test', - Icon: expect.anything(), + Icon: undefined, }); expect(defaultEntityPresentation('')).toEqual({ entityRef: 'unknown:default/unknown', primaryTitle: 'unknown', secondaryTitle: 'unknown:default/unknown', - Icon: expect.anything(), + Icon: undefined, }); }); }); @@ -235,7 +235,7 @@ describe('defaultEntityPresentation', () => { entityRef: 'unknown:default/unknown', primaryTitle: 'unknown', secondaryTitle: 'unknown:default/unknown', - Icon: expect.anything(), + Icon: undefined, }); expect(defaultEntityPresentation(undefined as unknown as Entity)).toEqual( @@ -243,7 +243,7 @@ describe('defaultEntityPresentation', () => { entityRef: 'unknown:default/unknown', primaryTitle: 'unknown', secondaryTitle: 'unknown:default/unknown', - Icon: expect.anything(), + Icon: undefined, }, ); @@ -253,7 +253,7 @@ describe('defaultEntityPresentation', () => { entityRef: 'unknown:default/unknown', primaryTitle: 'unknown', secondaryTitle: 'unknown:default/unknown', - Icon: expect.anything(), + Icon: undefined, }); }); }); diff --git a/plugins/catalog-react/src/apis/EntityPresentationApi/defaultEntityPresentation.ts b/plugins/catalog-react/src/apis/EntityPresentationApi/defaultEntityPresentation.ts index eacb659062..8d841f3c3c 100644 --- a/plugins/catalog-react/src/apis/EntityPresentationApi/defaultEntityPresentation.ts +++ b/plugins/catalog-react/src/apis/EntityPresentationApi/defaultEntityPresentation.ts @@ -20,32 +20,9 @@ import { Entity, stringifyEntityRef, } from '@backstage/catalog-model'; -import { IconComponent } from '@backstage/core-plugin-api'; -import ApartmentIcon from '@material-ui/icons/Apartment'; -import BusinessIcon from '@material-ui/icons/Business'; -import ExtensionIcon from '@material-ui/icons/Extension'; -import HelpIcon from '@material-ui/icons/Help'; -import LibraryAddIcon from '@material-ui/icons/LibraryAdd'; -import LocationOnIcon from '@material-ui/icons/LocationOn'; -import MemoryIcon from '@material-ui/icons/Memory'; -import PeopleIcon from '@material-ui/icons/People'; -import PersonIcon from '@material-ui/icons/Person'; import get from 'lodash/get'; import { EntityRefPresentationSnapshot } from './EntityPresentationApi'; -const UNKNOWN_KIND_ICON: IconComponent = HelpIcon; - -const DEFAULT_ICONS: Record = { - api: ExtensionIcon, - component: MemoryIcon, - system: BusinessIcon, - domain: ApartmentIcon, - location: LocationOnIcon, - user: PersonIcon, - group: PeopleIcon, - template: LibraryAddIcon, -}; - /** * This returns the default representation of an entity. * @@ -66,10 +43,6 @@ export function defaultEntityPresentation( const { kind, namespace, name, title, description, displayName, type } = getParts(entityOrRef); - const Icon = - (kind && DEFAULT_ICONS[kind.toLocaleLowerCase('en-US')]) || - UNKNOWN_KIND_ICON; - const entityRef: string = stringifyEntityRef({ kind: kind || 'unknown', namespace: namespace || DEFAULT_NAMESPACE, @@ -94,7 +67,7 @@ export function defaultEntityPresentation( entityRef, primaryTitle: primary, secondaryTitle: secondary || undefined, - Icon, + Icon: undefined, // leave it up to the presentation API to handle }; } diff --git a/plugins/catalog-react/src/components/CatalogFilterLayout/CatalogFilterLayout.tsx b/plugins/catalog-react/src/components/CatalogFilterLayout/CatalogFilterLayout.tsx index 1a1404edf2..1a0c446c9e 100644 --- a/plugins/catalog-react/src/components/CatalogFilterLayout/CatalogFilterLayout.tsx +++ b/plugins/catalog-react/src/components/CatalogFilterLayout/CatalogFilterLayout.tsx @@ -20,12 +20,12 @@ import { Button, Drawer, Grid, + Theme, Typography, useMediaQuery, useTheme, } from '@material-ui/core'; import FilterListIcon from '@material-ui/icons/FilterList'; -import { BackstageTheme } from '@backstage/theme'; /** @public */ export const Filters = (props: { @@ -35,10 +35,10 @@ export const Filters = (props: { drawerAnchor?: 'left' | 'right' | 'top' | 'bottom'; }; }) => { - const isScreenSmallerThanBreakpoint = useMediaQuery(theme => + const isScreenSmallerThanBreakpoint = useMediaQuery((theme: Theme) => theme.breakpoints.down(props.options?.drawerBreakpoint ?? 'md'), ); - const theme = useTheme(); + const theme = useTheme(); const [filterDrawerOpen, setFilterDrawerOpen] = useState(false); return isScreenSmallerThanBreakpoint ? ( diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx index 3eaba51909..98e680aa12 100644 --- a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx @@ -130,7 +130,7 @@ export function EntityAutocompletePicker< {label} - multiple disableCloseOnSelect options={availableOptions} diff --git a/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.tsx b/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.tsx index 01a6e0188d..7b8a35d162 100644 --- a/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.tsx +++ b/plugins/catalog-react/src/components/EntityProcessingStatusPicker/EntityProcessingStatusPicker.tsx @@ -72,7 +72,7 @@ export const EntityProcessingStatusPicker = () => { Processing Status - multiple disableCloseOnSelect options={availableAdvancedItems} diff --git a/plugins/catalog-react/src/components/MissingAnnotationEmptyState/MissingAnnotationEmptyState.tsx b/plugins/catalog-react/src/components/MissingAnnotationEmptyState/MissingAnnotationEmptyState.tsx index 284025d8cd..4d9329e664 100644 --- a/plugins/catalog-react/src/components/MissingAnnotationEmptyState/MissingAnnotationEmptyState.tsx +++ b/plugins/catalog-react/src/components/MissingAnnotationEmptyState/MissingAnnotationEmptyState.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; import Box from '@material-ui/core/Box'; import Button from '@material-ui/core/Button'; import { makeStyles } from '@material-ui/core/styles'; @@ -27,7 +26,7 @@ import { useEntity } from '../../hooks'; /** @public */ export type MissingAnnotationEmptyStateClassKey = 'code'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ code: { borderRadius: 6, diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx index ad56681d6c..5667447503 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.test.tsx @@ -40,6 +40,7 @@ import { storageApiRef, } from '@backstage/core-plugin-api'; import { MockStarredEntitiesApi, starredEntitiesApiRef } from '../../apis'; +import { DefaultEntityFilters } from '../../hooks'; const mockUser: UserEntity = { apiVersion: 'backstage.io/v1alpha1', @@ -289,7 +290,12 @@ describe('', () => { const updateFilters = jest.fn(); render( - + , @@ -297,6 +303,25 @@ describe('', () => { fireEvent.click(screen.getByText('Starred')); + // wait until the component has finished loading + await waitFor(() => { + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { kind: 'component', 'metadata.name': ['e-1', 'e-2'] }, + limit: 1000, + }); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { kind: 'component' }, + limit: 0, + }); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { + kind: 'component', + 'relations.ownedBy': ['user:default/testuser'], + }, + limit: 0, + }); + }); + await waitFor(() => expect(updateFilters).toHaveBeenLastCalledWith({ user: EntityUserFilter.starred([ @@ -360,12 +385,17 @@ describe('', () => { describe('filter resetting', () => { const updateFilters = jest.fn(); - const Picker = ({ ...props }: UserListPickerProps) => ( + const Picker = ({ + filters, + ...props + }: UserListPickerProps & { filters?: DefaultEntityFilters }) => ( @@ -413,6 +443,21 @@ describe('', () => { }); }); + it('does not reset the filter when request is empty', async () => { + render(); + + await waitFor(() => { + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(1); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { 'metadata.name': ['e-1', 'e-2'] }, + limit: 1000, + }); + }); + expect(updateFilters).not.toHaveBeenCalledWith({ + user: expect.any(Object), + }); + }); + it('resets the filter to "all" when entities are loaded', async () => { mockCatalogApi.queryEntities?.mockImplementation(async request => { if ( @@ -541,6 +586,21 @@ describe('', () => { }), ); }); + + it('does not reset the filter when request is empty xxxx', async () => { + render(); + + await waitFor(() => { + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(1); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { 'metadata.name': ['e-1', 'e-2'] }, + limit: 1000, + }); + }); + expect(updateFilters).not.toHaveBeenCalledWith({ + user: expect.any(Object), + }); + }); }); describe(`when there are some starred entities present`, () => { diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx index d9b32289ae..950bf5ea70 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx @@ -27,7 +27,6 @@ import { ListItemText, makeStyles, MenuItem, - Theme, Typography, } from '@material-ui/core'; import SettingsIcon from '@material-ui/icons/Settings'; @@ -48,7 +47,7 @@ export type CatalogReactUserListPickerClassKey = | 'menuItem' | 'groupWrapper'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ root: { backgroundColor: 'rgba(0, 0, 0, .11)', diff --git a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx index 1f6fbfd53d..aeaa20c535 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.test.tsx @@ -93,8 +93,8 @@ describe('useOwnedEntitiesCount', () => { ).rejects.toThrow(); expect(result.current).toEqual({ - count: 0, - loading: false, + count: undefined, + loading: true, filter: EntityUserFilter.owned([ 'user:default/spiderman', 'user:group/a-group', diff --git a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts index 1adab49361..2f03a0b285 100644 --- a/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts +++ b/plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts @@ -14,16 +14,16 @@ * limitations under the License. */ -import { QueryEntitiesInitialRequest } from '@backstage/catalog-client'; import { identityApiRef, useApi } from '@backstage/core-plugin-api'; -import { compact, intersection, isEqual } from 'lodash'; -import { useEffect, useMemo, useRef } from 'react'; +import { compact, intersection } from 'lodash'; +import { useMemo } from 'react'; import useAsync from 'react-use/lib/useAsync'; import { catalogApiRef } from '../../api'; import { EntityOwnerFilter, EntityUserFilter } from '../../filters'; import { useEntityList } from '../../hooks'; import { reduceCatalogFilters } from '../../utils'; import useAsyncFn from 'react-use/lib/useAsyncFn'; +import useDeepCompareEffect from 'react-use/lib/useDeepCompareEffect'; export function useOwnedEntitiesCount() { const identityApi = useApi(identityApiRef); @@ -37,79 +37,63 @@ export function useOwnedEntitiesCount() { [], ); - const prevRequest = useRef(); - - const request = useMemo(() => { - const { user, owners, ...allFilters } = filters; - const compacted = compact(Object.values(allFilters)); - const allFilter = reduceCatalogFilters(compacted); - const { ['metadata.name']: metadata, ...filter } = allFilter; - - const countFilter = getOwnedCountClaims(owners, ownershipEntityRefs); - - if ( - ownershipEntityRefs?.length === 0 || - countFilter === undefined || - Object.keys(filter).length === 0 - ) { - prevRequest.current = undefined; - return undefined; - } - const newRequest: QueryEntitiesInitialRequest = { - filter: { - ...filter, - 'relations.ownedBy': countFilter, - }, - limit: 0, - }; - - if (isEqual(newRequest, prevRequest.current)) { - return prevRequest.current; - } - - prevRequest.current = newRequest; - - return newRequest; - }, [filters, ownershipEntityRefs]); + const { user, owners, ...allFilters } = filters; + const { ['metadata.name']: metadata, ...filter } = reduceCatalogFilters( + compact(Object.values(allFilters)), + ); const [{ value: count, loading: loadingEntityOwnership }, fetchEntities] = useAsyncFn( - async ( - req: QueryEntitiesInitialRequest | undefined, - ownershipEntityRefsParam: string[], - ) => { - if (ownershipEntityRefsParam && !req) { + async (req: { + ownershipEntityRefs: string[]; + owners: EntityOwnerFilter | undefined; + filter: Record; + }) => { + const ownedClaims = getOwnedCountClaims( + req.owners, + req.ownershipEntityRefs, + ); + if (ownedClaims === undefined) { // this implicitly means that there aren't claims in common with // the logged in users, so avoid invoking the queryEntities endpoint // which will implicitly returns 0 return 0; } - const { totalItems } = await catalogApi.queryEntities(req); + + const { totalItems } = await catalogApi.queryEntities({ + filter: { + ...req.filter, + 'relations.ownedBy': ownedClaims, + }, + limit: 0, + }); return totalItems; }, [], { loading: true }, ); - useEffect(() => { - if (ownershipEntityRefs) { - if (request && Object.keys(request).length === 0) { - return; - } - fetchEntities(request, ownershipEntityRefs); + useDeepCompareEffect(() => { + // context contains no filter, wait + if (Object.keys(filter).length === 0) { + return; } - }, [fetchEntities, request, ownershipEntityRefs]); + // ownershipEntityRefs is loading, wait + if (ownershipEntityRefs === undefined) { + return; + } + fetchEntities({ ownershipEntityRefs, owners, filter }); + }, [ownershipEntityRefs, owners, filter]); const loading = loadingEntityRefs || loadingEntityOwnership; - const filter = useMemo( - () => EntityUserFilter.owned(ownershipEntityRefs ?? []), - [ownershipEntityRefs], - ); return { count, loading, - filter, + filter: useMemo( + () => EntityUserFilter.owned(ownershipEntityRefs ?? []), + [ownershipEntityRefs], + ), ownershipEntityRefs, }; } diff --git a/plugins/catalog-react/src/hooks/index.ts b/plugins/catalog-react/src/hooks/index.ts index ffd32206ef..c3021f8992 100644 --- a/plugins/catalog-react/src/hooks/index.ts +++ b/plugins/catalog-react/src/hooks/index.ts @@ -32,6 +32,7 @@ export { export type { DefaultEntityFilters, EntityListContextProps, + EntityListProviderProps, } from './useEntityListProvider'; export { useEntityTypeFilter } from './useEntityTypeFilter'; export { useRelatedEntities } from './useRelatedEntities'; diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx index edbfb65c0c..f6881d4a80 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx @@ -31,14 +31,13 @@ import React, { PropsWithChildren } from 'react'; import { MemoryRouter } from 'react-router-dom'; import { catalogApiRef } from '../api'; import { starredEntitiesApiRef, MockStarredEntitiesApi } from '../apis'; -import { EntityKindPicker, UserListPicker } from '../components'; import { EntityKindFilter, EntityTypeFilter, EntityUserFilter, } from '../filters'; -import { UserListFilterKind } from '../types'; import { EntityListProvider, useEntityList } from './useEntityListProvider'; +import { useMountEffect } from '@react-hookz/web'; const entities: Entity[] = [ { @@ -77,43 +76,53 @@ const mockIdentityApi: Partial = { }), getCredentials: async () => ({ token: undefined }), }; -const mockCatalogApi: Partial = { - getEntities: jest.fn().mockImplementation(async () => ({ items: entities })), - getEntityByRef: async () => undefined, +const mockCatalogApi: Partial> = { + getEntities: jest.fn().mockResolvedValue({ items: entities }), + queryEntities: jest.fn().mockResolvedValue({ + items: entities, + pageInfo: { prevCursor: 'prevCursor', nextCursor: 'nextCursor' }, + totalItems: 10, + }), + getEntityByRef: jest.fn().mockResolvedValue(undefined), }; -const wrapper = ({ - userFilter, - location, - children, -}: PropsWithChildren<{ - userFilter?: UserListFilterKind; - location?: string; -}>) => { - return ( - - - - - - - ); -}; +const createWrapper = + (options: { location?: string; pagination: boolean }) => + (props: PropsWithChildren) => { + const InitialFiltersWrapper = ({ children }: PropsWithChildren) => { + const { updateFilters } = useEntityList(); + + useMountEffect(() => { + updateFilters({ kind: new EntityKindFilter('component') }); + }); + + return <>{children}; + }; + + return ( + + + + {props.children} + + + + ); + }; describe('', () => { const origReplaceState = window.history.replaceState; + const pagination = false; + beforeEach(() => { window.history.replaceState = jest.fn(); }); @@ -125,16 +134,17 @@ describe('', () => { jest.clearAllMocks(); }); - it('resolves backend filters', async () => { + it('should send backend filters', async () => { const { result } = renderHook(() => useEntityList(), { - wrapper, + wrapper: createWrapper({ pagination }), }); await waitFor(() => { - expect(result.current.backendEntities.length).toBeGreaterThan(0); + expect(result.current.backendEntities.length).toBe(2); }); - expect(result.current.backendEntities.length).toBe(2); + expect(result.current.entities.length).toBe(2); + expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(1); expect(mockCatalogApi.getEntities).toHaveBeenCalledWith({ filter: { kind: 'component' }, }); @@ -142,17 +152,12 @@ describe('', () => { it('resolves frontend filters', async () => { const { result } = renderHook(() => useEntityList(), { - wrapper, + wrapper: createWrapper({ pagination }), initialProps: { userFilter: 'all', }, }); - await waitFor(() => { - expect(result.current.backendEntities.length).toBeGreaterThan(0); - }); - expect(result.current.backendEntities.length).toBe(2); - act(() => result.current.updateFilters({ user: EntityUserFilter.owned(ownershipEntityRefs), @@ -171,8 +176,10 @@ describe('', () => { filters: { kind: 'component', type: 'service' }, }); const { result } = renderHook(() => useEntityList(), { - wrapper: ({ children }) => - wrapper({ location: `/catalog?${query}`, children }), + wrapper: createWrapper({ + location: `/catalog?${query}`, + pagination, + }), }); await waitFor(() => { @@ -186,7 +193,7 @@ describe('', () => { it('does not fetch when only frontend filters change', async () => { const { result } = renderHook(() => useEntityList(), { - wrapper, + wrapper: createWrapper({ pagination }), }); await waitFor(() => { @@ -202,13 +209,18 @@ describe('', () => { await waitFor(() => { expect(result.current.entities.length).toBe(1); - expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(1); }); + + await expect(() => + waitFor(() => { + expect(mockCatalogApi.getEntities).not.toHaveBeenCalledTimes(1); + }), + ).rejects.toThrow(); }); it('debounces multiple filter changes', async () => { const { result } = renderHook(() => useEntityList(), { - wrapper, + wrapper: createWrapper({ pagination }), }); await waitFor(() => { @@ -218,18 +230,20 @@ describe('', () => { expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(1); await act(async () => { - result.current.updateFilters({ kind: new EntityKindFilter('component') }); + result.current.updateFilters({ kind: new EntityKindFilter('api') }); result.current.updateFilters({ type: new EntityTypeFilter('service') }); }); await waitFor(() => { - expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(2); + expect(mockCatalogApi.getEntities).toHaveBeenNthCalledWith(2, { + filter: { kind: 'api', 'spec.type': ['service'] }, + }); }); }); it('returns an error on catalogApi failure', async () => { const { result } = renderHook(() => useEntityList(), { - wrapper, + wrapper: createWrapper({ pagination }), }); await waitFor(() => { @@ -237,7 +251,7 @@ describe('', () => { }); expect(result.current.backendEntities.length).toBe(2); - mockCatalogApi.getEntities = jest.fn().mockRejectedValue('error'); + mockCatalogApi.getEntities!.mockRejectedValueOnce('error'); act(() => { result.current.updateFilters({ kind: new EntityKindFilter('api') }); }); @@ -245,4 +259,230 @@ describe('', () => { expect(result.current.error).toBeDefined(); }); }); + + it('returns an empty pageInfo', async () => { + const { result } = renderHook(() => useEntityList(), { + wrapper: createWrapper({ pagination }), + }); + await waitFor(() => { + expect(mockCatalogApi.getEntities).toHaveBeenCalled(); + }); + + expect(result.current.pageInfo).toBeUndefined(); + }); +}); + +describe('', () => { + const origReplaceState = window.history.replaceState; + const pagination = true; + const limit = 20; + const orderFields = [{ field: 'metadata.name', order: 'asc' }]; + + beforeEach(() => { + window.history.replaceState = jest.fn(); + }); + afterEach(() => { + window.history.replaceState = origReplaceState; + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should send backend filters', async () => { + const { result } = renderHook(() => useEntityList(), { + wrapper: createWrapper({ pagination }), + }); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBe(2); + }); + + expect(result.current.entities.length).toBe(2); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(1); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + filter: { kind: 'component' }, + limit, + orderFields, + }); + }); + + it('resolves frontend filters', async () => { + const { result } = renderHook(() => useEntityList(), { + wrapper: createWrapper({ pagination }), + initialProps: { + userFilter: 'all', + }, + }); + + act(() => + result.current.updateFilters({ + user: EntityUserFilter.owned(ownershipEntityRefs), + }), + ); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBe(2); + expect(result.current.entities.length).toBe(1); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(1); + }); + }); + + it('resolves query param filter values', async () => { + const query = qs.stringify({ + filters: { kind: 'component', type: 'service' }, + }); + const { result } = renderHook(() => useEntityList(), { + wrapper: createWrapper({ + location: `/catalog?${query}`, + pagination, + }), + }); + + await waitFor(() => { + expect(result.current.queryParameters).toBeTruthy(); + }); + expect(result.current.queryParameters).toEqual({ + kind: 'component', + type: 'service', + }); + }); + + it('fetch when frontend filters change', async () => { + const { result } = renderHook(() => useEntityList(), { + wrapper: createWrapper({ pagination }), + }); + + await waitFor(() => { + expect(result.current.entities.length).toBe(2); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(1); + }); + + act(() => + result.current.updateFilters({ + user: EntityUserFilter.owned(ownershipEntityRefs), + }), + ); + + await waitFor(() => { + expect(result.current.entities.length).toBe(1); + }); + + await waitFor(() => { + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(2); + }); + }); + + it('debounces multiple filter changes', async () => { + const { result } = renderHook(() => useEntityList(), { + wrapper: createWrapper({ pagination }), + }); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBeGreaterThan(0); + }); + expect(result.current.backendEntities.length).toBe(2); + expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(1); + + await act(async () => { + result.current.updateFilters({ kind: new EntityKindFilter('api') }); + result.current.updateFilters({ type: new EntityTypeFilter('service') }); + }); + + await waitFor(() => { + expect(mockCatalogApi.queryEntities).toHaveBeenNthCalledWith(2, { + filter: { kind: 'api', 'spec.type': ['service'] }, + limit, + orderFields, + }); + }); + }); + + it('returns an error on catalogApi failure', async () => { + const { result } = renderHook(() => useEntityList(), { + wrapper: createWrapper({ pagination }), + }); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBeGreaterThan(0); + }); + expect(result.current.backendEntities.length).toBe(2); + + mockCatalogApi.queryEntities!.mockRejectedValueOnce('error'); + act(() => { + result.current.updateFilters({ kind: new EntityKindFilter('api') }); + }); + await waitFor(() => { + expect(result.current.error).toBeDefined(); + }); + }); + + describe('pageInfo', () => { + it('returns an empty pageInfo', async () => { + mockCatalogApi.queryEntities!.mockResolvedValueOnce({ + items: [], + pageInfo: {}, + totalItems: 10, + }); + const { result } = renderHook(() => useEntityList(), { + wrapper: createWrapper({ pagination }), + }); + await waitFor(() => { + expect(mockCatalogApi.queryEntities).toHaveBeenCalled(); + }); + + expect(result.current.pageInfo).toStrictEqual({ + prev: undefined, + next: undefined, + }); + }); + + it('returns pageInfo with next function and properly fetch next batch', async () => { + const { result } = renderHook(() => useEntityList(), { + wrapper: createWrapper({ pagination }), + }); + await waitFor(() => { + expect(mockCatalogApi.queryEntities).toHaveBeenCalled(); + }); + + await waitFor(() => { + expect(result.current.pageInfo!.next).toBeDefined(); + }); + + act(() => { + result.current.pageInfo!.next!(); + }); + + await waitFor(() => { + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + cursor: 'nextCursor', + limit, + }); + }); + }); + + it('returns pageInfo with prev function and properly fetch prev batch', async () => { + const { result } = renderHook(() => useEntityList(), { + wrapper: createWrapper({ pagination }), + }); + await waitFor(() => { + expect(mockCatalogApi.queryEntities).toHaveBeenCalled(); + }); + + await waitFor(() => { + expect(result.current.pageInfo!.prev).toBeDefined(); + }); + + act(() => { + result.current.pageInfo!.prev!(); + }); + + await waitFor(() => { + expect(mockCatalogApi.queryEntities).toHaveBeenCalledWith({ + cursor: 'prevCursor', + limit, + }); + }); + }); + }); }); diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx index 948efc969f..1ce87c262e 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx @@ -44,8 +44,13 @@ import { EntityUserFilter, } from '../filters'; import { EntityFilter } from '../types'; -import { reduceBackendCatalogFilters, reduceEntityFilters } from '../utils'; +import { + reduceBackendCatalogFilters, + reduceCatalogFilters, + reduceEntityFilters, +} from '../utils'; import { useApi } from '@backstage/core-plugin-api'; +import { QueryEntitiesResponse } from '@backstage/catalog-client'; /** @public */ export type DefaultEntityFilters = { @@ -98,6 +103,11 @@ export type EntityListContextProps< loading: boolean; error?: Error; + + pageInfo?: { + next?: () => void; + prev?: () => void; + }; }; /** @@ -110,16 +120,25 @@ export const EntityListContext = createContext< type OutputState = { appliedFilters: EntityFilters; + appliedCursor?: string; entities: Entity[]; backendEntities: Entity[]; + pageInfo?: QueryEntitiesResponse['pageInfo']; }; +/** + * @public + */ +export type EntityListProviderProps = PropsWithChildren<{ + pagination?: boolean | { limit?: number }; +}>; + /** * Provides entities and filters for a catalog listing. * @public */ export const EntityListProvider = ( - props: PropsWithChildren<{}>, + props: EntityListProviderProps, ) => { const isMounted = useMountedState(); const catalogApi = useApi(catalogApiRef); @@ -132,13 +151,32 @@ export const EntityListProvider = ( // trigger a useLocation change; this would instead come from an external source, such as a manual // update of the URL or two catalog sidebar links with different catalog filters. const location = useLocation(); - const queryParameters = useMemo( - () => - (qs.parse(location.search, { - ignoreQueryPrefix: true, - }).filters ?? {}) as Record, - [location], - ); + + const enablePagination = + props.pagination === true || typeof props.pagination === 'object'; + + const limit = + props.pagination && + typeof props.pagination === 'object' && + typeof props.pagination.limit === 'number' + ? props.pagination.limit + : 20; + + const { queryParameters, cursor: initialCursor } = useMemo(() => { + const parsed = qs.parse(location.search, { + ignoreQueryPrefix: true, + }); + + return { + queryParameters: (parsed.filters ?? {}) as Record< + string, + string | string[] + >, + cursor: typeof parsed.cursor === 'string' ? parsed.cursor : undefined, + }; + }, [location]); + + const [cursor, setCursor] = useState(initialCursor); const [outputState, setOutputState] = useState>( () => { @@ -146,6 +184,7 @@ export const EntityListProvider = ( appliedFilters: {} as EntityFilters, entities: [], backendEntities: [], + pageInfo: enablePagination ? {} : undefined, }; }, ); @@ -156,11 +195,6 @@ export const EntityListProvider = ( const [{ loading, error }, refresh] = useAsyncFn( async () => { const compacted = compact(Object.values(requestedFilters)); - const entityFilter = reduceEntityFilters(compacted); - const backendFilter = reduceBackendCatalogFilters(compacted); - const previousBackendFilter = reduceBackendCatalogFilters( - compact(Object.values(outputState.appliedFilters)), - ); const queryParams = Object.keys(requestedFilters).reduce( (params, key) => { @@ -175,26 +209,71 @@ export const EntityListProvider = ( {} as Record, ); - // TODO(mtlewis): currently entities will never be requested unless - // there's at least one filter, we should allow an initial request - // to happen with no filters. - if (!isEqual(previousBackendFilter, backendFilter)) { - // TODO(timbonicus): should limit fields here, but would need filter - // fields + table columns - const response = await catalogApi.getEntities({ - filter: backendFilter, - }); - setOutputState({ - appliedFilters: requestedFilters, - backendEntities: response.items, - entities: response.items.filter(entityFilter), - }); + if (enablePagination) { + if (cursor) { + if (cursor !== outputState.appliedCursor) { + const entityFilter = reduceEntityFilters(compacted); + const response = await catalogApi.queryEntities({ + cursor, + limit, + }); + setOutputState({ + appliedFilters: requestedFilters, + appliedCursor: cursor, + backendEntities: response.items, + entities: response.items.filter(entityFilter), + pageInfo: response.pageInfo, + }); + } + } else { + const entityFilter = reduceEntityFilters(compacted); + const backendFilter = reduceCatalogFilters(compacted); + const previousBackendFilter = reduceCatalogFilters( + compact(Object.values(outputState.appliedFilters)), + ); + + if (!isEqual(previousBackendFilter, backendFilter)) { + const response = await catalogApi.queryEntities({ + filter: backendFilter, + limit, + orderFields: [{ field: 'metadata.name', order: 'asc' }], + }); + setOutputState({ + appliedFilters: requestedFilters, + backendEntities: response.items, + entities: response.items.filter(entityFilter), + pageInfo: response.pageInfo, + }); + } + } } else { - setOutputState({ - appliedFilters: requestedFilters, - backendEntities: outputState.backendEntities, - entities: outputState.backendEntities.filter(entityFilter), - }); + const entityFilter = reduceEntityFilters(compacted); + const backendFilter = reduceBackendCatalogFilters(compacted); + const previousBackendFilter = reduceBackendCatalogFilters( + compact(Object.values(outputState.appliedFilters)), + ); + + // TODO(mtlewis): currently entities will never be requested unless + // there's at least one filter, we should allow an initial request + // to happen with no filters. + if (!isEqual(previousBackendFilter, backendFilter)) { + // TODO(timbonicus): should limit fields here, but would need filter + // fields + table columns + const response = await catalogApi.getEntities({ + filter: backendFilter, + }); + setOutputState({ + appliedFilters: requestedFilters, + backendEntities: response.items, + entities: response.items.filter(entityFilter), + }); + } else { + setOutputState({ + appliedFilters: requestedFilters, + backendEntities: outputState.backendEntities, + entities: outputState.backendEntities.filter(entityFilter), + }); + } } if (isMounted()) { @@ -202,7 +281,7 @@ export const EntityListProvider = ( ignoreQueryPrefix: true, }); const newParams = qs.stringify( - { ...oldParams, filters: queryParams }, + { ...oldParams, filters: queryParams, cursor }, { addQueryPrefix: true, arrayFormat: 'repeat' }, ); const newUrl = `${window.location.pathname}${newParams}`; @@ -214,13 +293,20 @@ export const EntityListProvider = ( window.history?.replaceState(null, document.title, newUrl); } }, - [catalogApi, queryParameters, requestedFilters, outputState], + [ + catalogApi, + queryParameters, + requestedFilters, + outputState, + cursor, + enablePagination, + ], { loading: true }, ); // Slight debounce on the refresh, since (especially on page load) several // filters will be calling this in rapid succession. - useDebounce(refresh, 10, [requestedFilters]); + useDebounce(refresh, 10, [requestedFilters, cursor]); const updateFilters = useCallback( ( @@ -228,6 +314,12 @@ export const EntityListProvider = ( | Partial | ((prevFilters: EntityFilters) => Partial), ) => { + // changing filters will affect pagination, so we need to reset + // the cursor and start from the first page. + // TODO(vinzscam): this is currently causing issues at page reload + // where the state is not kept. Unfortunately we need to rething + // the way filters work in order to fix this. + setCursor(undefined); setRequestedFilters(prevFilters => { const newFilters = typeof update === 'function' ? update(prevFilters) : update; @@ -237,6 +329,19 @@ export const EntityListProvider = ( [], ); + const pageInfo = useMemo(() => { + if (!enablePagination) { + return undefined; + } + + const prevCursor = outputState.pageInfo?.prevCursor; + const nextCursor = outputState.pageInfo?.nextCursor; + return { + prev: prevCursor ? () => setCursor(prevCursor) : undefined, + next: nextCursor ? () => setCursor(nextCursor) : undefined, + }; + }, [enablePagination, outputState.pageInfo]); + const value = useMemo( () => ({ filters: outputState.appliedFilters, @@ -246,8 +351,9 @@ export const EntityListProvider = ( queryParameters, loading, error, + pageInfo, }), - [outputState, updateFilters, queryParameters, loading, error], + [outputState, updateFilters, queryParameters, loading, error, pageInfo], ); return ( diff --git a/plugins/catalog-react/src/overridableComponents.ts b/plugins/catalog-react/src/overridableComponents.ts index e94af1c4fb..6424c95ab5 100644 --- a/plugins/catalog-react/src/overridableComponents.ts +++ b/plugins/catalog-react/src/overridableComponents.ts @@ -44,3 +44,8 @@ export type BackstageOverrides = Overrides & { StyleRules >; }; + +declare module '@backstage/theme' { + interface OverrideComponentNameToClassKeys + extends CatalogReactComponentsNameToClassKey {} +} diff --git a/plugins/catalog-unprocessed-entities/CHANGELOG.md b/plugins/catalog-unprocessed-entities/CHANGELOG.md index 13bb7f0731..be54f6fd00 100644 --- a/plugins/catalog-unprocessed-entities/CHANGELOG.md +++ b/plugins/catalog-unprocessed-entities/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-catalog-unprocessed-entities +## 0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.1.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.1.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.1.5 ### Patch Changes diff --git a/plugins/catalog-unprocessed-entities/package.json b/plugins/catalog-unprocessed-entities/package.json index e5730512c2..12a805c2fd 100644 --- a/plugins/catalog-unprocessed-entities/package.json +++ b/plugins/catalog-unprocessed-entities/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-unprocessed-entities", - "version": "0.1.5", + "version": "0.1.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 9dbcedb3a9..319ec22fa6 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,113 @@ # @backstage/plugin-catalog +## 1.16.0-next.3 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 8f5d6c1: Updates to the `/alpha` exports to match the extension input wrapping change. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-scaffolder-common@1.4.3 + - @backstage/plugin-search-common@1.2.8 + +## 1.16.0-next.2 + +### Minor Changes + +- e223f2264d: Properly support both function- and string-form visibility filter expressions in the new extensions exported via `/alpha`. + +### Patch Changes + +- 53600976bb: Ensure that passed-in icons are taken advantage of in the presentation API +- a5a04739e1: Internal refactor of alpha exports due to a change in how extension factories are defined. +- 78a10bb085: Adding in spec.type chip to search results for clarity +- fb8f3bdbc2: Updated alpha translation message keys to use nested format and camel case. +- 531e1a2a79: Updated alpha plugin to include the `unregisterRedirect` external route. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-scaffolder-common@1.4.3 + - @backstage/plugin-search-common@1.2.8 + +## 1.16.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + +## 1.16.0-next.0 + +### Minor Changes + +- b8e1eb2c0f: The `columns` prop can be an array or a function that returns an array in order to override the default columns of the `CatalogIndexPage`. + +### Patch Changes + +- bc7e6d3eb9: Fix copy entity url function in http contexts. +- cd910c4fa5: - Fixes bug where after unregistering an entity you are redirected to `/`. + - Adds an optional external route `unregisterRedirect` to override this behaviour to another route. +- 03d0b6dcdc: The `convertLegacyRouteRef` utility used by the alpha exports is now imported from `@backstage/core-compat-api`. +- 4d9e3b39e4: Register component overrides in the global `OverrideComponentNameToClassKeys` provided by `@backstage/theme`. This will in turn will provide component style override types for `createUnifiedTheme`. +- 8587f067d2: Added pagination support to `CatalogIndexPage` + + `CatalogIndexPage` now offers an optional pagination feature, designed to accommodate adopters managing extensive catalogs. This new capability allows for better handling of large amounts of data. + + To activate the pagination mode, simply update your `App.tsx` as follows: + + ```diff + const routes = ( + + ... + - } /> + + } /> + ... + ``` + + In case you have a custom catalog page and you want to enable pagination, you need to pass the `pagination` prop to `EntityListProvider` instead. + +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-scaffolder-common@1.4.3 + - @backstage/plugin-search-common@1.2.8 + ## 1.15.0 ### Minor Changes diff --git a/plugins/catalog/alpha-api-report.md b/plugins/catalog/api-report-alpha.md similarity index 87% rename from plugins/catalog/alpha-api-report.md rename to plugins/catalog/api-report-alpha.md index 43e589bdc3..3226d10270 100644 --- a/plugins/catalog/alpha-api-report.md +++ b/plugins/catalog/api-report-alpha.md @@ -7,7 +7,7 @@ import { AnyExtensionInputMap } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; -import { Extension } from '@backstage/frontend-plugin-api'; +import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; import { PortableSchema } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; @@ -17,11 +17,12 @@ export function createCatalogFilterExtension< TInputs extends AnyExtensionInputMap, TConfig = never, >(options: { - id: string; + namespace?: string; + name?: string; inputs?: TInputs; configSchema?: PortableSchema; loader: (options: { config: TConfig }) => Promise; -}): Extension; +}): ExtensionDefinition; // @alpha (undocumented) const _default: BackstagePlugin< @@ -50,6 +51,7 @@ const _default: BackstagePlugin< }, true >; + unregisterRedirect: ExternalRouteRef; } >; export default _default; diff --git a/plugins/catalog/api-report.md b/plugins/catalog/api-report.md index 6647f8deaa..bef24b50d8 100644 --- a/plugins/catalog/api-report.md +++ b/plugins/catalog/api-report.md @@ -11,6 +11,7 @@ import { CatalogApi } from '@backstage/plugin-catalog-react'; import { ComponentEntity } from '@backstage/catalog-model'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { Entity } from '@backstage/catalog-model'; +import { EntityListContextProps } from '@backstage/plugin-catalog-react'; import { EntityOwnerPickerProps } from '@backstage/plugin-catalog-react'; import { EntityPresentationApi } from '@backstage/plugin-catalog-react'; import { EntityRefPresentation } from '@backstage/plugin-catalog-react'; @@ -122,6 +123,7 @@ export const catalogPlugin: BackstagePlugin< }, true >; + unregisterRedirect: ExternalRouteRef; } >; @@ -156,7 +158,9 @@ export const CatalogTable: { createSystemColumn(): TableColumn; createOwnerColumn(): TableColumn; createSpecTargetsColumn(): TableColumn; - createSpecTypeColumn(): TableColumn; + createSpecTypeColumn(options?: { + hidden: boolean; + }): TableColumn; createSpecLifecycleColumn(): TableColumn; createMetadataDescriptionColumn(): TableColumn; createTagsColumn(): TableColumn; @@ -180,12 +184,17 @@ export const CatalogTable: { }>; }; +// @public +export type CatalogTableColumnsFunc = ( + entityListContext: EntityListContextProps, +) => TableColumn[]; + // @public export interface CatalogTableProps { // (undocumented) actions?: TableProps['actions']; // (undocumented) - columns?: TableColumn[]; + columns?: TableColumn[] | CatalogTableColumnsFunc; // (undocumented) emptyContent?: ReactNode; // (undocumented) @@ -217,7 +226,7 @@ export interface DefaultCatalogPageProps { // (undocumented) actions?: TableProps['actions']; // (undocumented) - columns?: TableColumn[]; + columns?: TableColumn[] | CatalogTableColumnsFunc; // (undocumented) emptyContent?: ReactNode; // (undocumented) @@ -227,6 +236,12 @@ export interface DefaultCatalogPageProps { // (undocumented) ownerPickerMode?: EntityOwnerPickerProps['mode']; // (undocumented) + pagination?: + | boolean + | { + limit?: number; + }; + // (undocumented) tableOptions?: TableProps['options']; } diff --git a/plugins/catalog/config.d.ts b/plugins/catalog/config.d.ts new file mode 100644 index 0000000000..af749db905 --- /dev/null +++ b/plugins/catalog/config.d.ts @@ -0,0 +1,27 @@ +/* + * 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 interface Config { + catalog?: { + /** + * @deepVisibility frontend + */ + experimentalPagination?: + | boolean + | { + limit?: number; + }; + }; +} diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 150f5362f3..12d66efedb 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog", "description": "The Backstage plugin for browsing the Backstage catalog", - "version": "1.15.0", + "version": "1.16.0-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -91,6 +91,8 @@ "@testing-library/user-event": "^14.0.0" }, "files": [ - "dist" - ] + "dist", + "config.d.ts" + ], + "configSchema": "config.d.ts" } diff --git a/plugins/catalog/src/alpha/EntityOverviewPage.tsx b/plugins/catalog/src/alpha/EntityOverviewPage.tsx index baa93845ae..932e13d962 100644 --- a/plugins/catalog/src/alpha/EntityOverviewPage.tsx +++ b/plugins/catalog/src/alpha/EntityOverviewPage.tsx @@ -14,29 +14,95 @@ * limitations under the License. */ -import React from 'react'; -import { useEntity } from '@backstage/plugin-catalog-react'; import { Entity } from '@backstage/catalog-model'; +import { useEntity } from '@backstage/plugin-catalog-react'; import Grid from '@material-ui/core/Grid'; +import React, { useMemo } from 'react'; +import { parseFilterExpression } from './filter/parseFilterExpression'; interface EntityOverviewPageProps { cards: Array<{ element: React.JSX.Element; - filter: (ctx: { entity: Entity }) => boolean; + filterFunction?: (entity: Entity) => boolean; + filterExpression?: string; }>; } +// Keeps track of what filter expression strings that we've seen duplicates of +// with functions, or which emitted parsing errors for so far +const seenParseErrorExpressionStrings = new Set(); +const seenDuplicateExpressionStrings = new Set(); + +// Given an optional filter function and an optional filter expression, make +// sure that at most one of them was given, and return a filter function that +// does the right thing. +function buildFilterFn( + filterFunction?: (entity: Entity) => boolean, + filterExpression?: string, +): (entity: Entity) => boolean { + if ( + filterFunction && + filterExpression && + !seenDuplicateExpressionStrings.has(filterExpression) + ) { + // eslint-disable-next-line no-console + console.warn( + `Duplicate entity filter methods found, both '${filterExpression}' as well as a callback function, which is not permitted - using the callback`, + ); + seenDuplicateExpressionStrings.add(filterExpression); + } + + const filter = filterFunction || filterExpression; + if (!filter) { + return () => true; + } else if (typeof filter === 'function') { + return subject => filter(subject); + } + + const result = parseFilterExpression(filter); + if ( + result.expressionParseErrors.length && + !seenParseErrorExpressionStrings.has(filter) + ) { + // eslint-disable-next-line no-console + console.warn( + `Error(s) in entity filter expression '${filter}'`, + result.expressionParseErrors, + ); + seenParseErrorExpressionStrings.add(filter); + } + + return result.filterFn; +} + +// Handles the memoized parsing of filter expressions for each card +function CardWrapper(props: { + entity: Entity; + element: React.JSX.Element; + filterFunction?: (entity: Entity) => boolean; + filterExpression?: string; +}) { + const { entity, element, filterFunction, filterExpression } = props; + + const filterFn = useMemo( + () => buildFilterFn(filterFunction, filterExpression), + [filterFunction, filterExpression], + ); + + return filterFn(entity) ? ( + + {element} + + ) : null; +} + export function EntityOverviewPage(props: EntityOverviewPageProps) { const { entity } = useEntity(); return ( - {props.cards - .filter(card => card.filter({ entity })) - .map(card => ( - - {card.element} - - ))} + {props.cards.map((card, index) => ( + + ))} ); } diff --git a/plugins/catalog/src/alpha/createCatalogFilterExtension.tsx b/plugins/catalog/src/alpha/createCatalogFilterExtension.tsx index cf3dbd318a..48ee647b81 100644 --- a/plugins/catalog/src/alpha/createCatalogFilterExtension.tsx +++ b/plugins/catalog/src/alpha/createCatalogFilterExtension.tsx @@ -28,22 +28,23 @@ export function createCatalogFilterExtension< TInputs extends AnyExtensionInputMap, TConfig = never, >(options: { - id: string; + namespace?: string; + name?: string; inputs?: TInputs; configSchema?: PortableSchema; loader: (options: { config: TConfig }) => Promise; }) { - const id = `catalog.filter.${options.id}`; - return createExtension({ - id, - attachTo: { id: 'plugin.catalog.page.index', input: 'filters' }, + kind: 'catalog-filter', + namespace: options.namespace, + name: options.name, + attachTo: { id: 'page:catalog', input: 'filters' }, inputs: options.inputs ?? {}, configSchema: options.configSchema, output: { element: coreExtensionData.reactElement, }, - factory({ config, source }) { + factory({ config, node }) { const ExtensionComponent = lazy(() => options .loader({ config }) @@ -52,7 +53,7 @@ export function createCatalogFilterExtension< return { element: ( - + ), diff --git a/plugins/catalog/src/alpha/entityCards.tsx b/plugins/catalog/src/alpha/entityCards.tsx index c7b75679a7..371c62afbe 100644 --- a/plugins/catalog/src/alpha/entityCards.tsx +++ b/plugins/catalog/src/alpha/entityCards.tsx @@ -16,79 +16,80 @@ import React from 'react'; import { createEntityCardExtension } from '@backstage/plugin-catalog-react/alpha'; +import { compatWrapper } from '@backstage/core-compat-api'; export const EntityAboutCard = createEntityCardExtension({ - id: 'about', + name: 'about', loader: async () => - import('../components/AboutCard').then(m => ( - - )), + import('../components/AboutCard').then(m => + compatWrapper(), + ), }); export const EntityLinksCard = createEntityCardExtension({ - id: 'links', - filter: ({ entity }) => Boolean(entity.metadata.links), + name: 'links', + filter: 'has:links', loader: async () => - import('../components/EntityLinksCard').then(m => { - return ; - }), + import('../components/EntityLinksCard').then(m => + compatWrapper(), + ), }); export const EntityLabelsCard = createEntityCardExtension({ - id: 'labels', - filter: ({ entity }) => Boolean(entity.metadata.labels), + name: 'labels', + filter: 'has:labels', loader: async () => - import('../components/EntityLabelsCard').then(m => ( - - )), + import('../components/EntityLabelsCard').then(m => + compatWrapper(), + ), }); export const EntityDependsOnComponentsCard = createEntityCardExtension({ - id: 'dependsOn.components', + name: 'depends-on-components', loader: async () => - import('../components/DependsOnComponentsCard').then(m => ( - - )), + import('../components/DependsOnComponentsCard').then(m => + compatWrapper(), + ), }); export const EntityDependsOnResourcesCard = createEntityCardExtension({ - id: 'dependsOn.resources', + name: 'depends-on-resources', loader: async () => - import('../components/DependsOnResourcesCard').then(m => ( - - )), + import('../components/DependsOnResourcesCard').then(m => + compatWrapper(), + ), }); export const EntityHasComponentsCard = createEntityCardExtension({ - id: 'has.components', + name: 'has-components', loader: async () => - import('../components/HasComponentsCard').then(m => ( - - )), + import('../components/HasComponentsCard').then(m => + compatWrapper(), + ), }); export const EntityHasResourcesCard = createEntityCardExtension({ - id: 'has.resources', + name: 'has-resources', loader: async () => - import('../components/HasResourcesCard').then(m => ( - - )), + import('../components/HasResourcesCard').then(m => + compatWrapper(), + ), }); export const EntityHasSubcomponentsCard = createEntityCardExtension({ - id: 'has.subcomponents', + name: 'has-subcomponents', loader: async () => - import('../components/HasSubcomponentsCard').then(m => ( - - )), + import('../components/HasSubcomponentsCard').then(m => + compatWrapper(), + ), }); export const EntityHasSystemsCard = createEntityCardExtension({ - id: 'has.systems', + name: 'has-systems', loader: async () => - import('../components/HasSystemsCard').then(m => ( - - )), + import('../components/HasSystemsCard').then(m => + compatWrapper(), + ), }); export default [ diff --git a/plugins/catalog/src/alpha/entityContents.tsx b/plugins/catalog/src/alpha/entityContents.tsx index 9bef4a5e0d..b278e15735 100644 --- a/plugins/catalog/src/alpha/entityContents.tsx +++ b/plugins/catalog/src/alpha/entityContents.tsx @@ -21,23 +21,25 @@ import { } from '@backstage/frontend-plugin-api'; import { createEntityContentExtension, - entityFilterExtensionDataRef, + entityFilterFunctionExtensionDataRef, + entityFilterExpressionExtensionDataRef, } from '@backstage/plugin-catalog-react/alpha'; export const OverviewEntityContent = createEntityContentExtension({ - id: 'overview', + name: 'overview', defaultPath: '/', defaultTitle: 'Overview', disabled: false, inputs: { cards: createExtensionInput({ element: coreExtensionData.reactElement, - filter: entityFilterExtensionDataRef, + filterFunction: entityFilterFunctionExtensionDataRef.optional(), + filterExpression: entityFilterExpressionExtensionDataRef.optional(), }), }, loader: async ({ inputs }) => import('./EntityOverviewPage').then(m => ( - + c.output)} /> )), }); diff --git a/plugins/catalog/src/alpha/filter/matrchers/createHasMatcher.test.ts b/plugins/catalog/src/alpha/filter/matrchers/createHasMatcher.test.ts new file mode 100644 index 0000000000..53524d228e --- /dev/null +++ b/plugins/catalog/src/alpha/filter/matrchers/createHasMatcher.test.ts @@ -0,0 +1,98 @@ +/* + * 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. + */ + +import { Entity } from '@backstage/catalog-model'; +import { createHasMatcher } from './createHasMatcher'; + +describe('createHasMatcher', () => { + const empty1 = { + metadata: {}, + } as unknown as Entity; + const empty2 = { + metadata: { + labels: {}, + links: [], + }, + } as unknown as Entity; + const labels = { + metadata: { + labels: { a: 'b' }, + }, + } as unknown as Entity; + const links = { + metadata: { links: [{}] }, + } as unknown as Entity; + + const err = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('supports valid parameters', () => { + expect(createHasMatcher(['labels'], err)(empty1)).toBe(false); + expect(createHasMatcher(['labels'], err)(empty2)).toBe(false); + expect(createHasMatcher(['labels'], err)(labels)).toBe(true); + + expect(createHasMatcher(['links'], err)(empty1)).toBe(false); + expect(createHasMatcher(['links'], err)(empty2)).toBe(false); + expect(createHasMatcher(['links'], err)(links)).toBe(true); + + expect(err).not.toHaveBeenCalled(); + }); + + it('matches if ANY parameter matches', () => { + expect(createHasMatcher(['labels', 'links'], err)(empty1)).toBe(false); + expect(createHasMatcher(['labels', 'links'], err)(empty2)).toBe(false); + expect(createHasMatcher(['labels', 'links'], err)(labels)).toBe(true); + expect(createHasMatcher(['labels', 'links'], err)(links)).toBe(true); + + expect(err).not.toHaveBeenCalled(); + }); + + it('emits errors properly, and skips over bad parameters', () => { + // throw if callback throws + expect(() => + createHasMatcher(['labels', 'bar'], e => { + throw e; + }), + ).toThrowErrorMatchingInlineSnapshot( + `"'bar' is not a valid parameter for 'has' filter expressions, expected one of 'labels','links'"`, + ); + expect(err).not.toHaveBeenCalled(); + + // continue if callback does not throw, and skip over the bad parameter + let matcher = createHasMatcher(['labels', 'foo', 'bar'], err); + expect(err).toHaveBeenCalledTimes(2); + expect(err).toHaveBeenCalledWith( + expect.objectContaining({ + message: `'foo' is not a valid parameter for 'has' filter expressions, expected one of 'labels','links'`, + }), + ); + expect(err).toHaveBeenCalledWith( + expect.objectContaining({ + message: `'bar' is not a valid parameter for 'has' filter expressions, expected one of 'labels','links'`, + }), + ); + expect(matcher(empty1)).toBe(false); + expect(matcher(labels)).toBe(true); + + // when no parameters at all match, just return true + matcher = createHasMatcher(['foo', 'bar'], err); + expect(matcher(empty1)).toBe(true); + expect(matcher(labels)).toBe(true); + }); +}); diff --git a/plugins/catalog/src/alpha/filter/matrchers/createHasMatcher.ts b/plugins/catalog/src/alpha/filter/matrchers/createHasMatcher.ts new file mode 100644 index 0000000000..9fd393a561 --- /dev/null +++ b/plugins/catalog/src/alpha/filter/matrchers/createHasMatcher.ts @@ -0,0 +1,52 @@ +/* + * 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. + */ + +import { InputError } from '@backstage/errors'; +import { EntityMatcherFn } from './types'; + +const allowedMatchers: Record = { + labels: entity => { + return Object.keys(entity.metadata.labels ?? {}).length > 0; + }, + links: entity => { + return (entity.metadata.links ?? []).length > 0; + }, +}; + +/** + * Matches on the non-empty presence of different parts of the entity + */ +export function createHasMatcher( + parameters: string[], + onParseError: (error: Error) => void, +): EntityMatcherFn { + const matchers = parameters.flatMap(parameter => { + const matcher = allowedMatchers[parameter.toLocaleLowerCase('en-US')]; + if (!matcher) { + const known = Object.keys(allowedMatchers).map(m => `'${m}'`); + onParseError( + new InputError( + `'${parameter}' is not a valid parameter for 'has' filter expressions, expected one of ${known}`, + ), + ); + return []; + } + return [matcher]; + }); + + return entity => + matchers.length ? matchers.some(matcher => matcher(entity)) : true; +} diff --git a/plugins/catalog/src/alpha/filter/matrchers/createIsMatcher.test.ts b/plugins/catalog/src/alpha/filter/matrchers/createIsMatcher.test.ts new file mode 100644 index 0000000000..4cb3094d62 --- /dev/null +++ b/plugins/catalog/src/alpha/filter/matrchers/createIsMatcher.test.ts @@ -0,0 +1,75 @@ +/* + * 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. + */ + +import { Entity } from '@backstage/catalog-model'; +import { createIsMatcher } from './createIsMatcher'; + +describe('createIsMatcher', () => { + const empty = { + metadata: {}, + } as unknown as Entity; + const orphan = { + metadata: { + annotations: { ['backstage.io/orphan']: 'true' }, + }, + } as unknown as Entity; + + const err = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('supports valid parameters', () => { + expect(createIsMatcher(['orphan'], err)(empty)).toBe(false); + expect(createIsMatcher(['orphan'], err)(orphan)).toBe(true); + + expect(err).not.toHaveBeenCalled(); + }); + + it('emits errors properly, and skips over bad parameters', () => { + // throw if callback throws + expect(() => + createIsMatcher(['orphan', 'foo'], e => { + throw e; + }), + ).toThrowErrorMatchingInlineSnapshot( + `"'foo' is not a valid parameter for 'is' filter expressions, expected one of 'orphan'"`, + ); + expect(err).not.toHaveBeenCalled(); + + // continue if callback does not throw, and skip over the bad parameter + let matcher = createIsMatcher(['orphan', 'foo', 'bar'], err); + expect(err).toHaveBeenCalledTimes(2); + expect(err).toHaveBeenCalledWith( + expect.objectContaining({ + message: `'foo' is not a valid parameter for 'is' filter expressions, expected one of 'orphan'`, + }), + ); + expect(err).toHaveBeenCalledWith( + expect.objectContaining({ + message: `'bar' is not a valid parameter for 'is' filter expressions, expected one of 'orphan'`, + }), + ); + expect(matcher(empty)).toBe(false); + expect(matcher(orphan)).toBe(true); + + // when no parameters at all match, just return true + matcher = createIsMatcher(['foo', 'bar'], err); + expect(matcher(empty)).toBe(true); + expect(matcher(orphan)).toBe(true); + }); +}); diff --git a/plugins/catalog/src/alpha/filter/matrchers/createIsMatcher.ts b/plugins/catalog/src/alpha/filter/matrchers/createIsMatcher.ts new file mode 100644 index 0000000000..49a54349d1 --- /dev/null +++ b/plugins/catalog/src/alpha/filter/matrchers/createIsMatcher.ts @@ -0,0 +1,48 @@ +/* + * 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. + */ + +import { InputError } from '@backstage/errors'; +import { EntityMatcherFn } from './types'; + +const allowedMatchers: Record = { + orphan: entity => + Boolean(entity.metadata.annotations?.['backstage.io/orphan']), +}; + +/** + * Matches on different semantic properties of the entity + */ +export function createIsMatcher( + parameters: string[], + onParseError: (error: Error) => void, +): EntityMatcherFn { + const matchers = parameters.flatMap(parameter => { + const matcher = allowedMatchers[parameter.toLocaleLowerCase('en-US')]; + if (!matcher) { + const known = Object.keys(allowedMatchers).map(m => `'${m}'`); + onParseError( + new InputError( + `'${parameter}' is not a valid parameter for 'is' filter expressions, expected one of ${known}`, + ), + ); + return []; + } + return [matcher]; + }); + + return entity => + matchers.length ? matchers.some(matcher => matcher(entity)) : true; +} diff --git a/plugins/catalog/src/alpha/filter/matrchers/createKindMatcher.test.ts b/plugins/catalog/src/alpha/filter/matrchers/createKindMatcher.test.ts new file mode 100644 index 0000000000..f109acccd4 --- /dev/null +++ b/plugins/catalog/src/alpha/filter/matrchers/createKindMatcher.test.ts @@ -0,0 +1,46 @@ +/* + * 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. + */ + +import { Entity } from '@backstage/catalog-model'; +import { createKindMatcher } from './createKindMatcher'; + +describe('createKindMatcher', () => { + const component = { kind: 'Component' } as unknown as Entity; + const user = { kind: 'User' } as unknown as Entity; + const resource = { kind: 'Resource' } as unknown as Entity; + + const err = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('supports valid parameters', () => { + expect(createKindMatcher(['component'], err)(component)).toBe(true); + expect(createKindMatcher(['componenT'], err)(component)).toBe(true); + expect(createKindMatcher(['user'], err)(component)).toBe(false); + + expect(err).not.toHaveBeenCalled(); + }); + + it('matches if ANY parameter matches', () => { + expect(createKindMatcher(['user', 'component'], err)(user)).toBe(true); + expect(createKindMatcher(['user', 'component'], err)(component)).toBe(true); + expect(createKindMatcher(['user', 'component'], err)(resource)).toBe(false); + + expect(err).not.toHaveBeenCalled(); + }); +}); diff --git a/plugins/catalog/src/alpha/filter/matrchers/createKindMatcher.ts b/plugins/catalog/src/alpha/filter/matrchers/createKindMatcher.ts new file mode 100644 index 0000000000..4f7c475ebe --- /dev/null +++ b/plugins/catalog/src/alpha/filter/matrchers/createKindMatcher.ts @@ -0,0 +1,28 @@ +/* + * 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. + */ + +import { EntityMatcherFn } from './types'; + +/** + * Matches on kind + */ +export function createKindMatcher( + parameters: string[], + _onParseError: (error: Error) => void, +): EntityMatcherFn { + const items = parameters.map(p => p.toLocaleLowerCase('en-US')); + return entity => items.includes(entity.kind.toLocaleLowerCase('en-US')); +} diff --git a/plugins/catalog/src/alpha/filter/matrchers/createTypeMatcher.test.ts b/plugins/catalog/src/alpha/filter/matrchers/createTypeMatcher.test.ts new file mode 100644 index 0000000000..31c9af7e11 --- /dev/null +++ b/plugins/catalog/src/alpha/filter/matrchers/createTypeMatcher.test.ts @@ -0,0 +1,54 @@ +/* + * 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. + */ + +import { Entity } from '@backstage/catalog-model'; +import { createTypeMatcher } from './createTypeMatcher'; + +describe('createTypeMatcher', () => { + const empty1 = {} as unknown as Entity; + const empty2 = { spec: {} } as unknown as Entity; + const service = { spec: { type: 'service' } } as unknown as Entity; + const website = { spec: { type: 'website' } } as unknown as Entity; + const pipeline = { spec: { type: 'pipeline' } } as unknown as Entity; + + const err = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('supports valid parameters', () => { + expect(createTypeMatcher(['service'], err)(empty1)).toBe(false); + expect(createTypeMatcher(['service'], err)(empty2)).toBe(false); + + expect(createTypeMatcher(['service'], err)(service)).toBe(true); + expect(createTypeMatcher(['sErViCe'], err)(service)).toBe(true); + expect(createTypeMatcher(['service'], err)(service)).toBe(true); + expect(createTypeMatcher(['website'], err)(service)).toBe(false); + + expect(err).not.toHaveBeenCalled(); + }); + + it('matches if ANY parameter matches', () => { + expect(createTypeMatcher(['service', 'website'], err)(service)).toBe(true); + expect(createTypeMatcher(['service', 'website'], err)(website)).toBe(true); + expect(createTypeMatcher(['service', 'website'], err)(pipeline)).toBe( + false, + ); + + expect(err).not.toHaveBeenCalled(); + }); +}); diff --git a/plugins/catalog/src/alpha/filter/matrchers/createTypeMatcher.ts b/plugins/catalog/src/alpha/filter/matrchers/createTypeMatcher.ts new file mode 100644 index 0000000000..31f7a5a461 --- /dev/null +++ b/plugins/catalog/src/alpha/filter/matrchers/createTypeMatcher.ts @@ -0,0 +1,34 @@ +/* + * 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. + */ + +import { EntityMatcherFn } from './types'; + +/** + * Matches on spec.type + */ +export function createTypeMatcher( + parameters: string[], + _onParseError: (error: Error) => void, +): EntityMatcherFn { + const items = parameters.map(p => p.toLocaleLowerCase('en-US')); + return entity => { + const value = entity.spec?.type; + return ( + typeof value === 'string' && + items.includes(value.toLocaleLowerCase('en-US')) + ); + }; +} diff --git a/plugins/catalog/src/alpha/filter/matrchers/types.ts b/plugins/catalog/src/alpha/filter/matrchers/types.ts new file mode 100644 index 0000000000..0fff91b3d5 --- /dev/null +++ b/plugins/catalog/src/alpha/filter/matrchers/types.ts @@ -0,0 +1,19 @@ +/* + * 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. + */ + +import { Entity } from '@backstage/catalog-model'; + +export type EntityMatcherFn = (entity: Entity) => boolean; diff --git a/plugins/catalog/src/alpha/filter/parseFilterExpression.test.ts b/plugins/catalog/src/alpha/filter/parseFilterExpression.test.ts new file mode 100644 index 0000000000..616091739e --- /dev/null +++ b/plugins/catalog/src/alpha/filter/parseFilterExpression.test.ts @@ -0,0 +1,151 @@ +/* + * 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. + */ + +import { Entity } from '@backstage/catalog-model'; +import { + parseFilterExpression, + splitFilterExpression, +} from './parseFilterExpression'; + +describe('parseFilterExpression', () => { + function run(expression: string) { + const result = parseFilterExpression(expression); + if (result.expressionParseErrors.length) { + throw result.expressionParseErrors[0]; + } + return result.filterFn; + } + + it('supports "kind" expressions', () => { + const component = { kind: 'Component' } as unknown as Entity; + const user = { kind: 'User' } as unknown as Entity; + const resource = { kind: 'Resource' } as unknown as Entity; + + expect(run('kind:user,component')(user)).toBe(true); + expect(run('kind:user,component')(component)).toBe(true); + expect(run('kind:user,component')(resource)).toBe(false); + }); + + it('supports "type" expressions', () => { + const empty = {} as unknown as Entity; + const service = { spec: { type: 'service' } } as unknown as Entity; + const website = { spec: { type: 'website' } } as unknown as Entity; + const pipeline = { spec: { type: 'pipeline' } } as unknown as Entity; + + expect(run('type:service,website')(empty)).toBe(false); + expect(run('type:service,website')(service)).toBe(true); + expect(run('type:service,website')(website)).toBe(true); + expect(run('type:service,website')(pipeline)).toBe(false); + }); + + it('supports "is" expressions', () => { + const empty = { + metadata: {}, + } as unknown as Entity; + const orphan = { + metadata: { + annotations: { ['backstage.io/orphan']: 'true' }, + }, + } as unknown as Entity; + + expect(run('is:orphan')(empty)).toBe(false); + expect(run('is:orphan')(orphan)).toBe(true); + + expect(() => run('is:orphan,bar')).toThrowErrorMatchingInlineSnapshot( + `"'bar' is not a valid parameter for 'is' filter expressions, expected one of 'orphan'"`, + ); + }); + + it('supports "has" expressions', () => { + const empty = { + metadata: {}, + } as unknown as Entity; + const labels = { + metadata: { labels: { a: 'b' } }, + } as unknown as Entity; + const annotations = { + metadata: { annotations: { a: 'b' } }, + } as unknown as Entity; + const links = { + metadata: { links: [{}] }, + } as unknown as Entity; + + expect(run('has:labels,links')(empty)).toBe(false); + expect(run('has:labels,links')(labels)).toBe(true); + expect(run('has:labels,links')(links)).toBe(true); + expect(run('has:labels,links')(annotations)).toBe(false); + + expect(() => run('has:labels,bar')).toThrowErrorMatchingInlineSnapshot( + `"'bar' is not a valid parameter for 'has' filter expressions, expected one of 'labels','links'"`, + ); + }); + + it('rejects unknown keys', () => { + expect(() => run('unknown:foo')).toThrowErrorMatchingInlineSnapshot( + `"'unknown' is not a valid filter expression key, expected one of 'kind','type','is','has'"`, + ); + }); + + it('rejects malformed inputs', () => { + expect(() => run(':')).toThrowErrorMatchingInlineSnapshot( + `"':' is not a valid filter expression, expected 'key:parameter' form"`, + ); + expect(() => run(':a')).toThrowErrorMatchingInlineSnapshot( + `"':a' is not a valid filter expression, expected 'key:parameter' form"`, + ); + expect(() => run('a:')).toThrowErrorMatchingInlineSnapshot( + `"'a:' is not a valid filter expression, expected 'key:parameter' form"`, + ); + }); +}); + +describe('splitFilterExpression', () => { + function run(expression: string) { + return splitFilterExpression(expression, e => { + throw e; + }); + } + + it('properly splits into expression atoms', () => { + expect(run('')).toEqual([]); + expect(run(' ')).toEqual([]); + expect(run('kind:component')).toEqual([ + { key: 'kind', parameters: ['component'] }, + ]); + expect(run('kind:component,user')).toEqual([ + { key: 'kind', parameters: ['component', 'user'] }, + ]); + expect(run('kind:component,user type:foo')).toEqual([ + { key: 'kind', parameters: ['component', 'user'] }, + { key: 'type', parameters: ['foo'] }, + ]); + expect(run('with:multiple:colons')).toEqual([ + { key: 'with', parameters: ['multiple:colons'] }, + ]); + }); + + it('rejects malformed inputs', () => { + expect(() => run(':')).toThrowErrorMatchingInlineSnapshot( + `"':' is not a valid filter expression, expected 'key:parameter' form"`, + ); + expect(() => run(':a')).toThrowErrorMatchingInlineSnapshot( + `"':a' is not a valid filter expression, expected 'key:parameter' form"`, + ); + expect(() => run('a:')).toThrowErrorMatchingInlineSnapshot( + `"'a:' is not a valid filter expression, expected 'key:parameter' form"`, + ); + }); +}); diff --git a/plugins/catalog/src/alpha/filter/parseFilterExpression.ts b/plugins/catalog/src/alpha/filter/parseFilterExpression.ts new file mode 100644 index 0000000000..a4c17cb8da --- /dev/null +++ b/plugins/catalog/src/alpha/filter/parseFilterExpression.ts @@ -0,0 +1,126 @@ +/* + * 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. + */ + +import { Entity } from '@backstage/catalog-model'; +import { InputError } from '@backstage/errors'; +import { EntityMatcherFn } from './matrchers/types'; +import { createKindMatcher } from './matrchers/createKindMatcher'; +import { createTypeMatcher } from './matrchers/createTypeMatcher'; +import { createIsMatcher } from './matrchers/createIsMatcher'; +import { createHasMatcher } from './matrchers/createHasMatcher'; + +const rootMatcherFactories: Record< + string, + ( + parameters: string[], + onParseError: (error: Error) => void, + ) => EntityMatcherFn +> = { + kind: createKindMatcher, + type: createTypeMatcher, + is: createIsMatcher, + has: createHasMatcher, +}; + +/** + * Parses a filter expression that decides whether to render an entity component + * or not. Returns a function that matches entities based on that expression. + * + * @remarks + * + * Filter strings are on the form `kind:user,group is:orphan`. There's + * effectively an AND between the space separated parts, and an OR between comma + * separated parameters. So the example filter string semantically means + * "entities that are of either User or Group kind, and also are orphans". + * + * The `expressionParseErrors` array contains any errors that were encountered + * during initial parsing of the expression. Note that the parts of the input + * expression that had errors are ignored entirely and parsing continues as if + * they didn't exist. + */ +export function parseFilterExpression(expression: string): { + filterFn: (entity: Entity) => boolean; + expressionParseErrors: Error[]; +} { + const expressionParseErrors: Error[] = []; + + const parts = splitFilterExpression(expression, e => + expressionParseErrors.push(e), + ); + + const matchers = parts.flatMap(part => { + const factory = rootMatcherFactories[part.key]; + if (!factory) { + const known = Object.keys(rootMatcherFactories).map(m => `'${m}'`); + expressionParseErrors.push( + new InputError( + `'${part.key}' is not a valid filter expression key, expected one of ${known}`, + ), + ); + return []; + } + + const matcher = factory(part.parameters, e => + expressionParseErrors.push(e), + ); + return [matcher]; + }); + + const filterFn = (entity: Entity) => + matchers.every(matcher => { + try { + return matcher(entity); + } catch { + return false; + } + }); + + return { + filterFn, + expressionParseErrors, + }; +} + +export function splitFilterExpression( + expression: string, + onParseError: (error: Error) => void, +): Array<{ key: string; parameters: string[] }> { + const words = expression + .split(' ') + .map(w => w.trim()) + .filter(Boolean); + + const result = new Array<{ key: string; parameters: string[] }>(); + + for (const word of words) { + const match = word.match(/^([^:]+):(.+)$/); + if (!match) { + onParseError( + new InputError( + `'${word}' is not a valid filter expression, expected 'key:parameter' form`, + ), + ); + continue; + } + + const key = match[1]; + const parameters = match[2].split(',').filter(Boolean); // silently ignore double commas + + result.push({ key, parameters }); + } + + return result; +} diff --git a/plugins/catalog/src/alpha/filters.tsx b/plugins/catalog/src/alpha/filters.tsx index 7b73c2d14b..be06e70611 100644 --- a/plugins/catalog/src/alpha/filters.tsx +++ b/plugins/catalog/src/alpha/filters.tsx @@ -19,7 +19,7 @@ import { createCatalogFilterExtension } from './createCatalogFilterExtension'; import { createSchemaFromZod } from '@backstage/frontend-plugin-api'; const CatalogEntityTagFilter = createCatalogFilterExtension({ - id: 'entity.tag', + name: 'tag', loader: async () => { const { EntityTagPicker } = await import('@backstage/plugin-catalog-react'); return ; @@ -27,7 +27,7 @@ const CatalogEntityTagFilter = createCatalogFilterExtension({ }); const CatalogEntityKindFilter = createCatalogFilterExtension({ - id: 'entity.kind', + name: 'kind', configSchema: createSchemaFromZod(z => z.object({ initialFilter: z.string().default('component'), @@ -42,7 +42,7 @@ const CatalogEntityKindFilter = createCatalogFilterExtension({ }); const CatalogEntityTypeFilter = createCatalogFilterExtension({ - id: 'entity.type', + name: 'type', loader: async () => { const { EntityTypePicker } = await import( '@backstage/plugin-catalog-react' @@ -52,7 +52,7 @@ const CatalogEntityTypeFilter = createCatalogFilterExtension({ }); const CatalogEntityOwnerFilter = createCatalogFilterExtension({ - id: 'entity.mode', + name: 'mode', configSchema: createSchemaFromZod(z => z.object({ mode: z.enum(['owners-only', 'all']).optional(), @@ -67,7 +67,7 @@ const CatalogEntityOwnerFilter = createCatalogFilterExtension({ }); const CatalogEntityNamespaceFilter = createCatalogFilterExtension({ - id: 'entity.namespace', + name: 'namespace', loader: async () => { const { EntityNamespacePicker } = await import( '@backstage/plugin-catalog-react' @@ -77,7 +77,7 @@ const CatalogEntityNamespaceFilter = createCatalogFilterExtension({ }); const CatalogEntityLifecycleFilter = createCatalogFilterExtension({ - id: 'entity.lifecycle', + name: 'lifecycle', loader: async () => { const { EntityLifecyclePicker } = await import( '@backstage/plugin-catalog-react' @@ -87,7 +87,7 @@ const CatalogEntityLifecycleFilter = createCatalogFilterExtension({ }); const CatalogEntityProcessingStatusFilter = createCatalogFilterExtension({ - id: 'entity.processing.status', + name: 'processing.status', loader: async () => { const { EntityProcessingStatusPicker } = await import( '@backstage/plugin-catalog-react' @@ -97,7 +97,7 @@ const CatalogEntityProcessingStatusFilter = createCatalogFilterExtension({ }); const CatalogUserListFilter = createCatalogFilterExtension({ - id: 'user.list', + name: 'list', configSchema: createSchemaFromZod(z => z.object({ initialFilter: z.enum(['owned', 'starred', 'all']).default('owned'), diff --git a/plugins/catalog/src/alpha/navItems.tsx b/plugins/catalog/src/alpha/navItems.tsx index 77ea394a97..8dde27b95a 100644 --- a/plugins/catalog/src/alpha/navItems.tsx +++ b/plugins/catalog/src/alpha/navItems.tsx @@ -20,7 +20,6 @@ import { createNavItemExtension } from '@backstage/frontend-plugin-api'; import { rootRouteRef } from '../routes'; export const CatalogIndexNavItem = createNavItemExtension({ - id: 'catalog.nav.index', routeRef: convertLegacyRouteRef(rootRouteRef), title: 'Catalog', icon: HomeIcon, diff --git a/plugins/catalog/src/alpha/pages.tsx b/plugins/catalog/src/alpha/pages.tsx index 6324f53083..c80e17ba4e 100644 --- a/plugins/catalog/src/alpha/pages.tsx +++ b/plugins/catalog/src/alpha/pages.tsx @@ -15,7 +15,10 @@ */ import React from 'react'; -import { convertLegacyRouteRef } from '@backstage/core-compat-api'; +import { + compatWrapper, + convertLegacyRouteRef, +} from '@backstage/core-compat-api'; import { createPageExtension, coreExtensionData, @@ -30,7 +33,6 @@ import { rootRouteRef } from '../routes'; import { useEntityFromUrl } from '../components/CatalogEntityPage/useEntityFromUrl'; export const CatalogIndexPage = createPageExtension({ - id: 'plugin.catalog.page.index', defaultPath: '/catalog', routeRef: convertLegacyRouteRef(rootRouteRef), inputs: { @@ -40,13 +42,13 @@ export const CatalogIndexPage = createPageExtension({ }, loader: async ({ inputs }) => { const { BaseCatalogPage } = await import('../components/CatalogPage'); - const filters = inputs.filters.map(filter => filter.element); - return {filters}} />; + const filters = inputs.filters.map(filter => filter.output.element); + return compatWrapper({filters}} />); }, }); export const CatalogEntityPage = createPageExtension({ - id: 'plugin.catalog.page.entity', + name: 'entity', defaultPath: '/catalog/:namespace/:kind/:name', routeRef: convertLegacyRouteRef(entityRouteRef), inputs: { @@ -65,18 +67,18 @@ export const CatalogEntityPage = createPageExtension({ {inputs.contents.map(content => ( - {content.element} + {content.output.element} ))} ); }; - return ; + return compatWrapper(); }, }); diff --git a/plugins/catalog/src/alpha/plugin.tsx b/plugins/catalog/src/alpha/plugin.tsx index 9b8494f1b0..99aacd27da 100644 --- a/plugins/catalog/src/alpha/plugin.tsx +++ b/plugins/catalog/src/alpha/plugin.tsx @@ -23,6 +23,7 @@ import { createComponentRouteRef, createFromTemplateRouteRef, rootRouteRef, + unregisterRedirectRouteRef, viewTechDocRouteRef, } from '../routes'; @@ -45,6 +46,7 @@ export default createPlugin({ viewTechDoc: convertLegacyRouteRef(viewTechDocRouteRef), createComponent: convertLegacyRouteRef(createComponentRouteRef), createFromTemplate: convertLegacyRouteRef(createFromTemplateRouteRef), + unregisterRedirect: convertLegacyRouteRef(unregisterRedirectRouteRef), }, extensions: [ ...apis, diff --git a/plugins/catalog/src/alpha/searchResultItems.tsx b/plugins/catalog/src/alpha/searchResultItems.tsx index f677869136..c84aabf300 100644 --- a/plugins/catalog/src/alpha/searchResultItems.tsx +++ b/plugins/catalog/src/alpha/searchResultItems.tsx @@ -18,7 +18,6 @@ import { createSearchResultListItemExtension } from '@backstage/plugin-search-re export const CatalogSearchResultListItemExtension = createSearchResultListItemExtension({ - id: 'catalog', predicate: result => result.type === 'software-catalog', component: () => import('../components/CatalogSearchResultListItem').then( diff --git a/plugins/catalog/src/apis/EntityPresentationApi/DefaultEntityPresentationApi.ts b/plugins/catalog/src/apis/EntityPresentationApi/DefaultEntityPresentationApi.ts index 5f1119e598..b610173421 100644 --- a/plugins/catalog/src/apis/EntityPresentationApi/DefaultEntityPresentationApi.ts +++ b/plugins/catalog/src/apis/EntityPresentationApi/DefaultEntityPresentationApi.ts @@ -34,6 +34,7 @@ import { DEFAULT_BATCH_DELAY, DEFAULT_CACHE_TTL, DEFAULT_ICONS, + UNKNOWN_KIND_ICON, createDefaultRenderer, } from './defaults'; @@ -134,10 +135,7 @@ export interface DefaultEntityPresentationApiOptions { * @remarks * * The keys are kinds (case insensitive) that map to icon values to represent - * kinds by. - * - * If you do not supply a set of icons here, a set of fallback icons will be - * used. If you supply the empty object, no fallback icons will be used. + * kinds by. These are merged with the default set of icons. */ kindIcons?: Record; @@ -194,11 +192,12 @@ export class DefaultEntityPresentationApi implements EntityPresentationApi { const renderer = options.renderer ?? createDefaultRenderer({ async: true }); const kindIcons: Record = {}; - Object.entries(options.kindIcons ?? DEFAULT_ICONS).forEach( - ([kind, icon]) => { - kindIcons[kind.toLocaleLowerCase('en-US')] = icon; - }, - ); + Object.entries(DEFAULT_ICONS).forEach(([kind, icon]) => { + kindIcons[kind.toLocaleLowerCase('en-US')] = icon; + }); + Object.entries(options.kindIcons ?? {}).forEach(([kind, icon]) => { + kindIcons[kind.toLocaleLowerCase('en-US')] = icon; + }); if (renderer.async) { if (!options.catalogApi) { @@ -396,6 +395,8 @@ export class DefaultEntityPresentationApi implements EntityPresentationApi { return false; } - return this.#kindIcons[kind.toLocaleLowerCase('en-US')]; + return ( + this.#kindIcons[kind.toLocaleLowerCase('en-US')] ?? UNKNOWN_KIND_ICON + ); } } diff --git a/plugins/catalog/src/apis/EntityPresentationApi/defaults.tsx b/plugins/catalog/src/apis/EntityPresentationApi/defaults.tsx index afcd1f5464..84f04c6f83 100644 --- a/plugins/catalog/src/apis/EntityPresentationApi/defaults.tsx +++ b/plugins/catalog/src/apis/EntityPresentationApi/defaults.tsx @@ -26,6 +26,7 @@ import LocationOnIcon from '@material-ui/icons/LocationOn'; import MemoryIcon from '@material-ui/icons/Memory'; import PeopleIcon from '@material-ui/icons/People'; import PersonIcon from '@material-ui/icons/Person'; +import WorkIcon from '@material-ui/icons/Work'; import { DefaultEntityPresentationApiRenderer } from './DefaultEntityPresentationApi'; export const DEFAULT_CACHE_TTL: HumanDuration = { seconds: 10 }; @@ -38,6 +39,7 @@ export const DEFAULT_ICONS: Record = { api: ExtensionIcon, component: MemoryIcon, system: BusinessIcon, + resource: WorkIcon, domain: ApartmentIcon, location: LocationOnIcon, user: PersonIcon, diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx index 0ced712344..e7ba2b960e 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.test.tsx @@ -32,8 +32,8 @@ import { MockStarredEntitiesApi, starredEntitiesApiRef, } from '@backstage/plugin-catalog-react'; +import { mockBreakpoint } from '@backstage/core-components/testUtils'; import { - mockBreakpoint, MockStorageApi, TestApiProvider, renderInTestApp, @@ -45,6 +45,8 @@ import { createComponentRouteRef } from '../../routes'; import { CatalogTableRow } from '../CatalogTable'; import { DefaultCatalogPage } from './DefaultCatalogPage'; +import { CatalogTableColumnsFunc } from '../CatalogTable/types'; + describe('DefaultCatalogPage', () => { const origReplaceState = window.history.replaceState; beforeEach(() => { @@ -217,6 +219,25 @@ describe('DefaultCatalogPage', () => { expect(columnHeaderLabels).toEqual(['Foo', 'Bar', 'Baz', 'Actions']); }, 20_000); + it('should render the custom column function passed as prop', async () => { + const columns: CatalogTableColumnsFunc = ({ filters, entities }) => { + return filters.kind?.value === 'component' && entities.length + ? [ + { title: 'Foo', field: 'entity.foo' }, + { title: 'Bar', field: 'entity.bar' }, + { title: 'Baz', field: 'entity.spec.lifecycle' }, + ] + : []; + }; + await renderWrapped(); + + const columnHeader = screen + .getAllByRole('button') + .filter(c => c.tagName === 'SPAN'); + const columnHeaderLabels = columnHeader.map(c => c.textContent); + expect(columnHeaderLabels).toEqual(['Foo', 'Bar', 'Baz', 'Actions']); + }, 20_000); + it('should render the default actions of an item in the grid', async () => { await renderWrapped(); await waitFor(() => expect(catalogApi.queryEntities).toHaveBeenCalled()); diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx index e50c69b8ec..8dfc29f87f 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx @@ -44,31 +44,34 @@ import { CatalogTable, CatalogTableRow } from '../CatalogTable'; import { catalogTranslationRef } from '../../translation'; import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +import { CatalogTableColumnsFunc } from '../CatalogTable/types'; + /** @internal */ -export interface BaseCatalogPageProps { +export type BaseCatalogPageProps = { filters: ReactNode; content?: ReactNode; -} + pagination?: boolean | { limit?: number }; +}; /** @internal */ export function BaseCatalogPage(props: BaseCatalogPageProps) { - const { filters, content = } = props; + const { filters, content = , pagination } = props; const orgName = useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage'; const createComponentLink = useRouteRef(createComponentRouteRef); const { t } = useTranslationRef(catalogTranslationRef); return ( - + All your software catalog entities - + {filters} {content} @@ -86,12 +89,13 @@ export function BaseCatalogPage(props: BaseCatalogPageProps) { */ export interface DefaultCatalogPageProps { initiallySelectedFilter?: UserListFilterKind; - columns?: TableColumn[]; + columns?: TableColumn[] | CatalogTableColumnsFunc; actions?: TableProps['actions']; initialKind?: string; tableOptions?: TableProps['options']; emptyContent?: ReactNode; ownerPickerMode?: EntityOwnerPickerProps['mode']; + pagination?: boolean | { limit?: number }; } export function DefaultCatalogPage(props: DefaultCatalogPageProps) { @@ -102,6 +106,7 @@ export function DefaultCatalogPage(props: DefaultCatalogPageProps) { initialKind = 'component', tableOptions = {}, emptyContent, + pagination, ownerPickerMode, } = props; @@ -127,6 +132,7 @@ export function DefaultCatalogPage(props: DefaultCatalogPageProps) { emptyContent={emptyContent} /> } + pagination={pagination} /> ); } diff --git a/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx index 06906aecc1..4c6b567d8a 100644 --- a/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx +++ b/plugins/catalog/src/components/CatalogSearchResultListItem/CatalogSearchResultListItem.tsx @@ -107,6 +107,7 @@ export function CatalogSearchResultListItem( /> {result.kind && } + {result.type && } {result.lifecycle && ( )} diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx index c242372a97..052d8f4787 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.test.tsx @@ -32,6 +32,7 @@ import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import { act, fireEvent, screen } from '@testing-library/react'; import * as React from 'react'; import { CatalogTable } from './CatalogTable'; +import { CatalogTableColumnsFunc } from './types'; const entities: Entity[] = [ { @@ -379,4 +380,63 @@ describe('CatalogTable component', () => { const labelCellValue = screen.getByText('generic'); expect(labelCellValue).toBeInTheDocument(); }); + + it('should render the label column with customised title and value as specified using function', async () => { + const columns: CatalogTableColumnsFunc = ({ + filters, + entities: entities1, + }) => { + return filters.kind?.value === 'api' && entities1.length + ? [ + CatalogTable.columns.createNameColumn({ defaultKind: 'API' }), + CatalogTable.columns.createLabelColumn('category', { + title: 'Category', + }), + ] + : []; + }; + + const entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'API', + metadata: { + name: 'APIWithLabel', + labels: { category: 'generic' }, + }, + }; + const expectedColumns = ['Name', 'Category', 'Actions']; + + await renderInTestApp( + + ({ kind: 'api' }), + toQueryValue: () => 'api', + }, + }, + }} + > + + + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name': entityRouteRef, + }, + }, + ); + + const columnHeader = screen + .getAllByRole('button') + .filter(c => c.tagName === 'SPAN'); + const columnHeaderLabels = columnHeader.map(c => c.textContent); + expect(columnHeaderLabels).toEqual(expectedColumns); + + const labelCellValue = screen.getByText('generic'); + expect(labelCellValue).toBeInTheDocument(); + }); }); diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx index 04584f688a..006210bb1d 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx @@ -45,7 +45,8 @@ import { capitalize } from 'lodash'; import pluralize from 'pluralize'; import React, { ReactNode, useMemo } from 'react'; import { columnFactories } from './columns'; -import { CatalogTableRow } from './types'; +import { CatalogTableColumnsFunc, CatalogTableRow } from './types'; +import { PaginatedCatalogTable } from './PaginatedCatalogTable'; /** * Props for {@link CatalogTable}. @@ -53,7 +54,7 @@ import { CatalogTableRow } from './types'; * @public */ export interface CatalogTableProps { - columns?: TableColumn[]; + columns?: TableColumn[] | CatalogTableColumnsFunc; actions?: TableProps['actions']; tableOptions?: TableProps['options']; emptyContent?: ReactNode; @@ -76,55 +77,66 @@ const refCompare = (a: Entity, b: Entity) => { return toRef(a).localeCompare(toRef(b)); }; +const defaultColumnsFunc: CatalogTableColumnsFunc = ({ filters, entities }) => { + const showTypeColumn = filters.type === undefined; + + return [ + columnFactories.createTitleColumn({ hidden: true }), + columnFactories.createNameColumn({ defaultKind: filters.kind?.value }), + ...createEntitySpecificColumns(), + columnFactories.createMetadataDescriptionColumn(), + columnFactories.createTagsColumn(), + ]; + + function createEntitySpecificColumns(): TableColumn[] { + const baseColumns = [ + columnFactories.createSystemColumn(), + columnFactories.createOwnerColumn(), + columnFactories.createSpecTypeColumn({ hidden: !showTypeColumn }), + columnFactories.createSpecLifecycleColumn(), + ]; + switch (filters.kind?.value) { + case 'user': + return []; + case 'domain': + case 'system': + return [columnFactories.createOwnerColumn()]; + case 'group': + case 'template': + return [ + columnFactories.createSpecTypeColumn({ hidden: !showTypeColumn }), + ]; + case 'location': + return [ + columnFactories.createSpecTypeColumn({ hidden: !showTypeColumn }), + columnFactories.createSpecTargetsColumn(), + ]; + default: + return entities.every(entity => entity.metadata.namespace === 'default') + ? baseColumns + : [...baseColumns, columnFactories.createNamespaceColumn()]; + } + } +}; + /** @public */ export const CatalogTable = (props: CatalogTableProps) => { - const { columns, actions, tableOptions, subtitle, emptyContent } = props; + const { + columns = defaultColumnsFunc, + tableOptions, + subtitle, + emptyContent, + } = props; const { isStarredEntity, toggleStarredEntity } = useStarredEntities(); - const { loading, error, entities, filters } = useEntityList(); + const entityListContext = useEntityList(); + const { loading, error, entities, filters, pageInfo } = entityListContext; + const enablePagination = !!pageInfo; - const defaultColumns: TableColumn[] = useMemo(() => { - return [ - columnFactories.createTitleColumn({ hidden: true }), - columnFactories.createNameColumn({ defaultKind: filters.kind?.value }), - ...createEntitySpecificColumns(), - columnFactories.createMetadataDescriptionColumn(), - columnFactories.createTagsColumn(), - ]; - - function createEntitySpecificColumns(): TableColumn[] { - const baseColumns = [ - columnFactories.createSystemColumn(), - columnFactories.createOwnerColumn(), - columnFactories.createSpecTypeColumn(), - columnFactories.createSpecLifecycleColumn(), - ]; - switch (filters.kind?.value) { - case 'user': - return []; - case 'domain': - case 'system': - return [columnFactories.createOwnerColumn()]; - case 'group': - case 'template': - return [columnFactories.createSpecTypeColumn()]; - case 'location': - return [ - columnFactories.createSpecTypeColumn(), - columnFactories.createSpecTargetsColumn(), - ]; - default: - return entities.every( - entity => entity.metadata.namespace === 'default', - ) - ? baseColumns - : [...baseColumns, columnFactories.createNamespaceColumn()]; - } - } - }, [filters.kind?.value, entities]); - - const showTypeColumn = filters.type === undefined; - // TODO(timbonicus): remove the title from the CatalogTable once using EntitySearchBar - const titlePreamble = capitalize(filters.user?.value ?? 'all'); + const tableColumns = useMemo( + () => + typeof columns === 'function' ? columns(entityListContext) : columns, + [columns, entityListContext], + ); if (error) { return ( @@ -196,66 +208,58 @@ export const CatalogTable = (props: CatalogTableProps) => { }, ]; - const rows = entities.sort(refCompare).map(entity => { - const partOfSystemRelations = getEntityRelations(entity, RELATION_PART_OF, { - kind: 'system', - }); - const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY); - - return { - entity, - resolved: { - // This name is here for backwards compatibility mostly; the - // presentation of refs in the table should in general be handled with - // EntityRefLink / EntityName components - name: humanizeEntityRef(entity, { - defaultKind: 'Component', - }), - entityRef: stringifyEntityRef(entity), - ownedByRelationsTitle: ownedByRelations - .map(r => humanizeEntityRef(r, { defaultKind: 'group' })) - .join(', '), - ownedByRelations, - partOfSystemRelationTitle: partOfSystemRelations - .map(r => - humanizeEntityRef(r, { - defaultKind: 'system', - }), - ) - .join(', '), - partOfSystemRelations, - }, - }; - }); - - const typeColumn = (columns || defaultColumns).find(c => c.title === 'Type'); - if (typeColumn) { - typeColumn.hidden = !showTypeColumn; - } - const showPagination = rows.length > 20; const currentKind = filters.kind?.value || ''; const currentType = filters.type?.value || ''; + // TODO(timbonicus): remove the title from the CatalogTable once using EntitySearchBar + const titlePreamble = capitalize(filters.user?.value ?? 'all'); const titleDisplay = [titlePreamble, currentType, pluralize(currentKind)] .filter(s => s) .join(' '); + const title = `${titleDisplay} (${entities.length})`; + const actions = props.actions || defaultActions; + const options = { + actionsColumnIndex: -1, + loadingType: 'linear' as const, + showEmptyDataSourceMessage: !loading, + padding: 'dense' as const, + ...tableOptions, + }; + + if (enablePagination) { + return ( + + ); + } + + const rows = entities.sort(refCompare).map(toEntityRow); + const pageSize = 20; + const showPagination = rows.length > pageSize; + return ( isLoading={loading} - columns={columns || defaultColumns} + columns={tableColumns} options={{ paging: showPagination, - pageSize: 20, - actionsColumnIndex: -1, - loadingType: 'linear', - showEmptyDataSourceMessage: !loading, - padding: 'dense', + pageSize: pageSize, pageSizeOptions: [20, 50, 100], - ...tableOptions, + ...options, }} title={`${titleDisplay} (${entities.length})`} data={rows} - actions={actions || defaultActions} + actions={actions} subtitle={subtitle} emptyContent={emptyContent} /> @@ -263,3 +267,35 @@ export const CatalogTable = (props: CatalogTableProps) => { }; CatalogTable.columns = columnFactories; + +function toEntityRow(entity: Entity) { + const partOfSystemRelations = getEntityRelations(entity, RELATION_PART_OF, { + kind: 'system', + }); + const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY); + + return { + entity, + resolved: { + // This name is here for backwards compatibility mostly; the + // presentation of refs in the table should in general be handled with + // EntityRefLink / EntityName components + name: humanizeEntityRef(entity, { + defaultKind: 'Component', + }), + entityRef: stringifyEntityRef(entity), + ownedByRelationsTitle: ownedByRelations + .map(r => humanizeEntityRef(r, { defaultKind: 'group' })) + .join(', '), + ownedByRelations, + partOfSystemRelationTitle: partOfSystemRelations + .map(r => + humanizeEntityRef(r, { + defaultKind: 'system', + }), + ) + .join(', '), + partOfSystemRelations, + }, + }; +} diff --git a/plugins/catalog/src/components/CatalogTable/PaginatedCatalogTable.test.tsx b/plugins/catalog/src/components/CatalogTable/PaginatedCatalogTable.test.tsx new file mode 100644 index 0000000000..dbf37c2d5c --- /dev/null +++ b/plugins/catalog/src/components/CatalogTable/PaginatedCatalogTable.test.tsx @@ -0,0 +1,99 @@ +/* + * 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. + */ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react'; +import { PaginatedCatalogTable } from './PaginatedCatalogTable'; +import { screen } from '@testing-library/react'; +import { CatalogTableRow } from './types'; + +describe('PaginatedCatalogTable', () => { + const data = new Array(100).fill(0).map((_, index) => { + const name = `component-${index}`; + return { + entity: { + apiVersion: '1', + kind: 'component', + metadata: { + name, + }, + }, + resolved: { + name, + entityRef: 'component:default/component', + }, + } as CatalogTableRow; + }); + + const columns = [ + { + title: 'Title', + field: 'entity.metadata.name', + searchable: true, + }, + ]; + + it('should display all the items', () => { + render(); + + for (const item of data) { + expect(screen.queryByText(item.resolved.name)).toBeInTheDocument(); + } + }); + + it('should display and invoke the next button', async () => { + const { rerender } = render( + , + ); + + expect( + screen.queryAllByRole('button', { name: 'Next Page' })[0], + ).toBeDisabled(); + + const fn = jest.fn(); + + rerender(); + + const nextButton = screen.queryAllByRole('button', { + name: 'Next Page', + })[0]; + expect(nextButton).toBeEnabled(); + + fireEvent.click(nextButton); + expect(fn).toHaveBeenCalled(); + }); + + it('should display and invoke the prev button', async () => { + const { rerender } = render( + , + ); + + expect( + screen.queryAllByRole('button', { name: 'Next Page' })[0], + ).toBeDisabled(); + + const fn = jest.fn(); + + rerender(); + + const prevButton = screen.queryAllByRole('button', { + name: 'Previous Page', + })[0]; + expect(prevButton).toBeEnabled(); + + fireEvent.click(prevButton); + expect(fn).toHaveBeenCalled(); + }); +}); diff --git a/plugins/catalog/src/components/CatalogTable/PaginatedCatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/PaginatedCatalogTable.tsx new file mode 100644 index 0000000000..771878b65c --- /dev/null +++ b/plugins/catalog/src/components/CatalogTable/PaginatedCatalogTable.tsx @@ -0,0 +1,58 @@ +/* + * 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. + */ + +import React from 'react'; + +import { Table, TableProps } from '@backstage/core-components'; +import { CatalogTableRow } from './types'; + +type PaginatedCatalogTableProps = { + prev?(): void; + next?(): void; +} & TableProps; + +/** + * @internal + */ +export function PaginatedCatalogTable(props: PaginatedCatalogTableProps) { + const { columns, data, next, prev } = props; + + return ( + { + if (page > 0) { + next?.(); + } else { + prev?.(); + } + }} + /* this will enable the prev button accordingly */ + page={prev ? 1 : 0} + /* this will enable the next button accordingly */ + totalCount={next ? Number.MAX_VALUE : Number.MAX_SAFE_INTEGER} + localization={{ pagination: { labelDisplayedRows: '' } }} + /> + ); +} diff --git a/plugins/catalog/src/components/CatalogTable/columns.tsx b/plugins/catalog/src/components/CatalogTable/columns.tsx index 3c31fcadf1..4260a0c26b 100644 --- a/plugins/catalog/src/components/CatalogTable/columns.tsx +++ b/plugins/catalog/src/components/CatalogTable/columns.tsx @@ -100,11 +100,15 @@ export const columnFactories = Object.freeze({ ), }; }, - createSpecTypeColumn(): TableColumn { + createSpecTypeColumn( + options: { + hidden: boolean; + } = { hidden: false }, + ): TableColumn { return { title: 'Type', field: 'entity.spec.type', - hidden: true, + hidden: options.hidden, width: 'auto', }; }, diff --git a/plugins/catalog/src/components/CatalogTable/index.ts b/plugins/catalog/src/components/CatalogTable/index.ts index 4e1b90f80a..f5d1ca1bb7 100644 --- a/plugins/catalog/src/components/CatalogTable/index.ts +++ b/plugins/catalog/src/components/CatalogTable/index.ts @@ -16,4 +16,4 @@ export { CatalogTable } from './CatalogTable'; export type { CatalogTableProps } from './CatalogTable'; -export type { CatalogTableRow } from './types'; +export type { CatalogTableRow, CatalogTableColumnsFunc } from './types'; diff --git a/plugins/catalog/src/components/CatalogTable/types.ts b/plugins/catalog/src/components/CatalogTable/types.ts index f2b3324169..c991205b11 100644 --- a/plugins/catalog/src/components/CatalogTable/types.ts +++ b/plugins/catalog/src/components/CatalogTable/types.ts @@ -14,7 +14,9 @@ * limitations under the License. */ -import { Entity, CompoundEntityRef } from '@backstage/catalog-model'; +import { CompoundEntityRef, Entity } from '@backstage/catalog-model'; +import { EntityListContextProps } from '@backstage/plugin-catalog-react'; +import { TableColumn } from '@backstage/core-components'; /** @public */ export interface CatalogTableRow { @@ -31,3 +33,12 @@ export interface CatalogTableRow { ownedByRelations: CompoundEntityRef[]; }; } + +/** + * Typed columns function to dynamically render columns based on entity list context. + * + * @public + */ +export type CatalogTableColumnsFunc = ( + entityListContext: EntityListContextProps, +) => TableColumn[]; diff --git a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx index 9cd377b447..0fc746f455 100644 --- a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx +++ b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx @@ -28,12 +28,13 @@ import { Theme, makeStyles } from '@material-ui/core/styles'; import BugReportIcon from '@material-ui/icons/BugReport'; import MoreVert from '@material-ui/icons/MoreVert'; import FileCopyTwoToneIcon from '@material-ui/icons/FileCopyTwoTone'; -import React, { useCallback, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { IconComponent } from '@backstage/core-plugin-api'; import { useEntityPermission } from '@backstage/plugin-catalog-react/alpha'; import { catalogEntityDeletePermission } from '@backstage/plugin-catalog-common/alpha'; import { UnregisterEntity, UnregisterEntityOptions } from './UnregisterEntity'; import { useApi, alertApiRef } from '@backstage/core-plugin-api'; +import useCopyToClipboard from 'react-use/lib/useCopyToClipboard'; /** @public */ export type EntityContextMenuClassKey = 'button'; @@ -87,16 +88,16 @@ export function EntityContextMenu(props: EntityContextMenuProps) { }; const alertApi = useApi(alertApiRef); - - const copyToClipboard = useCallback(() => { - window.navigator.clipboard.writeText(window.location.toString()).then(() => + const [copyState, copyToClipboard] = useCopyToClipboard(); + useEffect(() => { + if (!copyState.error && copyState.value) { alertApi.post({ message: 'Copied!', severity: 'info', display: 'transient', - }), - ); - }, [alertApi]); + }); + } + }, [copyState, alertApi]); const extraItems = UNSTABLE_extraContextMenuItems && [ ...UNSTABLE_extraContextMenuItems.map(item => ( @@ -163,7 +164,7 @@ export function EntityContextMenu(props: EntityContextMenuProps) { { onClose(); - copyToClipboard(); + copyToClipboard(window.location.toString()); }} > diff --git a/plugins/catalog/src/components/EntityLabelsCard/EntityLabelsEmptyState.tsx b/plugins/catalog/src/components/EntityLabelsCard/EntityLabelsEmptyState.tsx index a193a90d05..8878cb827f 100644 --- a/plugins/catalog/src/components/EntityLabelsCard/EntityLabelsEmptyState.tsx +++ b/plugins/catalog/src/components/EntityLabelsCard/EntityLabelsEmptyState.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; import { Button, makeStyles, Typography } from '@material-ui/core'; import React from 'react'; import { CodeSnippet } from '@backstage/core-components'; @@ -24,7 +23,7 @@ const ENTITY_YAML = `metadata: labels: javaVersion: 1.2.3`; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ code: { borderRadius: 6, diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx index 3634405af8..c222c2d7b6 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.test.tsx @@ -15,7 +15,11 @@ */ import { CatalogApi } from '@backstage/catalog-client'; -import { Entity } from '@backstage/catalog-model'; +import { + ANNOTATION_ORIGIN_LOCATION, + Entity, + RELATION_OWNED_BY, +} from '@backstage/catalog-model'; import { ApiProvider } from '@backstage/core-app-api'; import { AlertApi, alertApiRef } from '@backstage/core-plugin-api'; import { @@ -30,27 +34,30 @@ import { permissionApiRef } from '@backstage/plugin-permission-react'; import { MockPermissionApi, renderInTestApp, + TestApiProvider, TestApiRegistry, } from '@backstage/test-utils'; -import { act, fireEvent, screen } from '@testing-library/react'; +import { act, fireEvent, screen, waitFor } from '@testing-library/react'; import React from 'react'; import { EntityLayout } from './EntityLayout'; - -const mockEntity = { - kind: 'MyKind', - metadata: { - name: 'my-entity', - }, -} as Entity; - -const mockApis = TestApiRegistry.from( - [catalogApiRef, {} as CatalogApi], - [alertApiRef, {} as AlertApi], - [starredEntitiesApiRef, new MockStarredEntitiesApi()], - [permissionApiRef, new MockPermissionApi()], -); +import { rootRouteRef, unregisterRedirectRouteRef } from '../../routes'; +import { Route, Routes } from 'react-router-dom'; describe('EntityLayout', () => { + const mockEntity = { + kind: 'MyKind', + metadata: { + name: 'my-entity', + }, + } as Entity; + + const mockApis = TestApiRegistry.from( + [catalogApiRef, {} as CatalogApi], + [alertApiRef, {} as AlertApi], + [starredEntitiesApiRef, new MockStarredEntitiesApi()], + [permissionApiRef, new MockPermissionApi()], + ); + it('renders simplest case', async () => { await renderInTestApp( @@ -65,6 +72,7 @@ describe('EntityLayout', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -97,6 +105,7 @@ describe('EntityLayout', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -120,6 +129,7 @@ describe('EntityLayout', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -146,6 +156,7 @@ describe('EntityLayout', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -178,6 +189,7 @@ describe('EntityLayout', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -225,6 +237,7 @@ describe('EntityLayout', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -253,6 +266,7 @@ describe('EntityLayout', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -265,3 +279,168 @@ describe('EntityLayout', () => { expect(linkParent?.tagName).toBe('P'); }); }); + +describe('EntityLayout - CleanUpAfterRemoval', () => { + const entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'n', + namespace: 'ns', + annotations: { + [ANNOTATION_ORIGIN_LOCATION]: 'url:http://example.com', + }, + }, + spec: { + owner: 'tools', + type: 'service', + }, + relations: [ + { + type: RELATION_OWNED_BY, + targetRef: 'group:default/tools', + }, + ], + }; + const getLocationByRef: jest.MockedFunction = + jest.fn(); + const getEntities: jest.MockedFunction = jest.fn(); + const removeEntityByUid: jest.MockedFunction< + CatalogApi['removeEntityByUid'] + > = jest.fn(); + const getEntityFacets: jest.MockedFunction = + jest.fn(); + getLocationByRef.mockResolvedValue(undefined); + getEntities.mockResolvedValue({ items: [{ ...entity }] }); + getEntityFacets.mockResolvedValue({ + facets: { + 'relations.ownedBy': [{ count: 1, value: 'group:default/tools' }], + }, + }); + + const alertApi: AlertApi = { + post() { + return undefined; + }, + alert$() { + throw new Error('not implemented'); + }, + }; + + it('redirects to externalRouteRef when unregisterRedirectRouteRef is bound', async () => { + await renderInTestApp( + + + + +
tabbed-test-content
+
+
+
+ + catalog-page

} /> + external-page

} /> +
+
, + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, + '/testRoute': unregisterRedirectRouteRef, + }, + }, + ); + + const menuButton = screen.queryAllByTestId('menu-button')[0]; + fireEvent.click(menuButton); + const listItemUnregister = screen.queryAllByRole('menuitem', { + name: /Unregister entity/i, + })[0]; + fireEvent.click(listItemUnregister); + await waitFor(() => { + const deleteEntityButton = screen.getByRole('button', { + name: /Delete Entity/i, + }); + act(() => { + fireEvent.click(deleteEntityButton); + }); + }); + + await waitFor(() => { + expect(screen.getByText('external-page')).toBeInTheDocument(); + }); + }); + + it('redirects to rootRouteRef when unregisterRedirectRouteRef is not bound', async () => { + await renderInTestApp( + + + + +
tabbed-test-content
+
+
+
+ + catalog-page

} /> + external-page

} /> +
+
, + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, + }, + }, + ); + + const menuButton = screen.queryAllByTestId('menu-button')[0]; + fireEvent.click(menuButton); + const listItemUnregister = screen.queryAllByRole('menuitem', { + name: /Unregister entity/i, + })[0]; + fireEvent.click(listItemUnregister); + await waitFor(() => { + const deleteEntityButton = screen.getByRole('button', { + name: /Delete Entity/i, + }); + act(() => { + fireEvent.click(deleteEntityButton); + }); + }); + + await waitFor(() => { + expect(screen.getByText('catalog-page')).toBeInTheDocument(); + }); + }); +}); diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx index f9999f26e9..8e11f92599 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx @@ -33,6 +33,7 @@ import { attachComponentData, IconComponent, useElementFilter, + useRouteRef, useRouteRefParams, } from '@backstage/core-plugin-api'; import { @@ -50,6 +51,7 @@ import { Alert } from '@material-ui/lab'; import React, { useEffect, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { EntityContextMenu } from '../EntityContextMenu/EntityContextMenu'; +import { rootRouteRef, unregisterRedirectRouteRef } from '../../routes'; /** @public */ export type EntityLayoutRouteProps = { @@ -229,10 +231,15 @@ export const EntityLayout = (props: EntityLayoutProps) => { const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false); const [inspectionDialogOpen, setInspectionDialogOpen] = useState(false); const navigate = useNavigate(); + const catalogRoute = useRouteRef(rootRouteRef); + const unregisterRedirectRoute = useRouteRef(unregisterRedirectRouteRef); + const cleanUpAfterRemoval = async () => { setConfirmationDialogOpen(false); setInspectionDialogOpen(false); - navigate('/'); + navigate( + unregisterRedirectRoute ? unregisterRedirectRoute() : catalogRoute(), + ); }; // Make sure to close the dialog if the user clicks links in it that navigate diff --git a/plugins/catalog/src/components/EntityLinksCard/EntityLinksEmptyState.tsx b/plugins/catalog/src/components/EntityLinksCard/EntityLinksEmptyState.tsx index f55527c78a..59ab3f3db2 100644 --- a/plugins/catalog/src/components/EntityLinksCard/EntityLinksEmptyState.tsx +++ b/plugins/catalog/src/components/EntityLinksCard/EntityLinksEmptyState.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; import { Button, makeStyles, Typography } from '@material-ui/core'; import React from 'react'; import { CodeSnippet } from '@backstage/core-components'; @@ -29,7 +28,7 @@ const ENTITY_YAML = `metadata: /** @public */ export type EntityLinksEmptyStateClassKey = 'code'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ code: { borderRadius: 6, diff --git a/plugins/catalog/src/components/EntityNotFound/EntityNotFound.tsx b/plugins/catalog/src/components/EntityNotFound/EntityNotFound.tsx index fca763c37b..d8d9fe0855 100644 --- a/plugins/catalog/src/components/EntityNotFound/EntityNotFound.tsx +++ b/plugins/catalog/src/components/EntityNotFound/EntityNotFound.tsx @@ -17,10 +17,9 @@ import React from 'react'; import { Grid, Button, Typography } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; -import { BackstageTheme } from '@backstage/theme'; import { Illo } from './Illo'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ container: { paddingTop: theme.spacing(24), paddingLeft: theme.spacing(8), diff --git a/plugins/catalog/src/overridableComponents.ts b/plugins/catalog/src/overridableComponents.ts index 5cd82202d5..0d981b1700 100644 --- a/plugins/catalog/src/overridableComponents.ts +++ b/plugins/catalog/src/overridableComponents.ts @@ -33,3 +33,8 @@ export type BackstageOverrides = Overrides & { StyleRules >; }; + +declare module '@backstage/theme' { + interface OverrideComponentNameToClassKeys + extends PluginCatalogComponentsNameToClassKey {} +} diff --git a/plugins/catalog/src/plugin.ts b/plugins/catalog/src/plugin.ts index d310639fb1..f41fefe404 100644 --- a/plugins/catalog/src/plugin.ts +++ b/plugins/catalog/src/plugin.ts @@ -25,6 +25,7 @@ import { import { createComponentRouteRef, createFromTemplateRouteRef, + unregisterRedirectRouteRef, viewTechDocRouteRef, } from './routes'; import { @@ -89,6 +90,7 @@ export const catalogPlugin = createPlugin({ createComponent: createComponentRouteRef, viewTechDoc: viewTechDocRouteRef, createFromTemplate: createFromTemplateRouteRef, + unregisterRedirect: unregisterRedirectRouteRef, }, }); diff --git a/plugins/catalog/src/routes.ts b/plugins/catalog/src/routes.ts index ab70a3c551..dcc46c7988 100644 --- a/plugins/catalog/src/routes.ts +++ b/plugins/catalog/src/routes.ts @@ -36,6 +36,11 @@ export const createFromTemplateRouteRef = createExternalRouteRef({ params: ['namespace', 'templateName'], }); +export const unregisterRedirectRouteRef = createExternalRouteRef({ + id: 'catalog:unregister-redirect', + optional: true, +}); + export const rootRouteRef = createRouteRef({ id: 'catalog', }); diff --git a/plugins/catalog/src/translation.ts b/plugins/catalog/src/translation.ts index 2d1e3f2c8a..bd27069fde 100644 --- a/plugins/catalog/src/translation.ts +++ b/plugins/catalog/src/translation.ts @@ -20,7 +20,9 @@ import { createTranslationRef } from '@backstage/core-plugin-api/alpha'; export const catalogTranslationRef = createTranslationRef({ id: 'catalog', messages: { - catalog_page_title: `{{orgName}} Catalog`, - catalog_page_create_button_title: 'Create', + indexPage: { + title: `{{orgName}} Catalog`, + createButtonTitle: 'Create', + }, }, }); diff --git a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md index 7a62334c54..b9dba4590c 100644 --- a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md +++ b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-cicd-statistics-module-gitlab +## 0.1.24-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-cicd-statistics@0.1.30-next.2 + +## 0.1.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-cicd-statistics@0.1.30-next.1 + - @backstage/catalog-model@1.4.3 + +## 0.1.24-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-cicd-statistics@0.1.30-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.1.22 ### Patch Changes diff --git a/plugins/cicd-statistics-module-gitlab/package.json b/plugins/cicd-statistics-module-gitlab/package.json index 7575dd2971..aa3bfa17c0 100644 --- a/plugins/cicd-statistics-module-gitlab/package.json +++ b/plugins/cicd-statistics-module-gitlab/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cicd-statistics-module-gitlab", "description": "CI/CD Statistics plugin module; Gitlab CICD", - "version": "0.1.22", + "version": "0.1.24-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cicd-statistics/CHANGELOG.md b/plugins/cicd-statistics/CHANGELOG.md index 200d4ca231..419a70f0e1 100644 --- a/plugins/cicd-statistics/CHANGELOG.md +++ b/plugins/cicd-statistics/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-cicd-statistics +## 0.1.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.1.30-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + +## 0.1.30-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.1.28 ### Patch Changes diff --git a/plugins/cicd-statistics/package.json b/plugins/cicd-statistics/package.json index 64689b4e26..f660fb3466 100644 --- a/plugins/cicd-statistics/package.json +++ b/plugins/cicd-statistics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cicd-statistics", "description": "A frontend plugin visualizing CI/CD pipeline statistics (build time)", - "version": "0.1.28", + "version": "0.1.30-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cicd-statistics/src/components/chart-filters.tsx b/plugins/cicd-statistics/src/components/chart-filters.tsx index 03cbea5dd0..026e81fd74 100644 --- a/plugins/cicd-statistics/src/components/chart-filters.tsx +++ b/plugins/cicd-statistics/src/components/chart-filters.tsx @@ -27,7 +27,6 @@ import { Switch, Tooltip, Typography, - Theme, makeStyles, } from '@material-ui/core'; import ShowChartIcon from '@material-ui/icons/ShowChart'; @@ -54,7 +53,7 @@ import { Toggle } from './toggle'; import { DurationSlider } from './duration-slider'; import { Label } from './label'; -export const useStyles = makeStyles( +export const useStyles = makeStyles( theme => ({ rootCard: { padding: theme.spacing(0, 0, 0, 0), diff --git a/plugins/cicd-statistics/src/components/label.tsx b/plugins/cicd-statistics/src/components/label.tsx index fe064d30a6..1c9a05b303 100644 --- a/plugins/cicd-statistics/src/components/label.tsx +++ b/plugins/cicd-statistics/src/components/label.tsx @@ -15,9 +15,9 @@ */ import React, { PropsWithChildren } from 'react'; -import { Typography, Theme, makeStyles } from '@material-ui/core'; +import { Typography, makeStyles } from '@material-ui/core'; -export const useStyles = makeStyles( +export const useStyles = makeStyles( theme => ({ label: { fontWeight: 'normal', diff --git a/plugins/cicd-statistics/src/entity-page.tsx b/plugins/cicd-statistics/src/entity-page.tsx index db5cba42aa..25b8477f61 100644 --- a/plugins/cicd-statistics/src/entity-page.tsx +++ b/plugins/cicd-statistics/src/entity-page.tsx @@ -15,7 +15,7 @@ */ import React, { useCallback, useState, useMemo, useEffect } from 'react'; -import { Grid, makeStyles, Theme } from '@material-ui/core'; +import { Grid, makeStyles } from '@material-ui/core'; import { Alert } from '@material-ui/lab'; import { useEntity } from '@backstage/plugin-catalog-react'; import { useApi, errorApiRef } from '@backstage/core-plugin-api'; @@ -57,7 +57,7 @@ export function EntityPageCicdCharts() { )); } -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ pane: { padding: theme.spacing(1, 1, 1, 1), diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index 6bb03a723f..ca28077dd0 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-circleci +## 0.3.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.3.28-next.1 + +### Patch Changes + +- 375b6f7d68: CircelCI plugin moved permanently +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.3.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.3.26 ### Patch Changes diff --git a/plugins/circleci/README.md b/plugins/circleci/README.md index f468ab37e2..86af7081c7 100644 --- a/plugins/circleci/README.md +++ b/plugins/circleci/README.md @@ -1,6 +1,7 @@ # CircleCI Plugin -Website: [https://circleci.com/](https://circleci.com/) +> [!IMPORTANT] +> This plugin is now developed & maintained by CircleCI. Please refer to [their up-to-date documentation](https://github.com/CircleCI-Public/backstage-plugin) & [plugin repository](https://github.com/CircleCI-Public/backstage-plugin/) for help. ## Screenshots @@ -14,7 +15,7 @@ Website: [https://circleci.com/](https://circleci.com/) ```bash # From your Backstage root directory -yarn add --cwd packages/app @backstage/plugin-circleci +yarn add --cwd packages/app @circleci/backstage-plugin ``` 2. Add the `EntityCircleCIContent` extension to the entity page in your app: @@ -24,7 +25,7 @@ yarn add --cwd packages/app @backstage/plugin-circleci import { EntityCircleCIContent, isCircleCIAvailable, -} from '@backstage/plugin-circleci'; +} from '@circleci/backstage-plugin'; // For example in the CI/CD section const cicdContent = ( diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index 8564afedf7..977962ac75 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-circleci", "description": "A Backstage plugin that integrates towards Circle CI", - "version": "0.3.26", + "version": "0.3.28-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index 673fd20ad8..bc43903bb6 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-cloudbuild +## 0.3.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.3.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.3.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.3.26 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 8c8ce0f251..f25cccd169 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cloudbuild", "description": "A Backstage plugin that integrates towards Google Cloud Build", - "version": "0.3.26", + "version": "0.3.28-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cloudbuild/src/components/Cards/Cards.tsx b/plugins/cloudbuild/src/components/Cards/Cards.tsx index 2b7a8607b7..11efe520e0 100644 --- a/plugins/cloudbuild/src/components/Cards/Cards.tsx +++ b/plugins/cloudbuild/src/components/Cards/Cards.tsx @@ -19,7 +19,7 @@ import { useWorkflowRuns, WorkflowRun } from '../useWorkflowRuns'; import { WorkflowRunsTable } from '../WorkflowRunsTable'; import { useEntity } from '@backstage/plugin-catalog-react'; import { WorkflowRunStatus } from '../WorkflowRunStatus'; -import { Theme, makeStyles, LinearProgress } from '@material-ui/core'; +import { makeStyles, LinearProgress } from '@material-ui/core'; import ExternalLinkIcon from '@material-ui/icons/Launch'; import { CLOUDBUILD_ANNOTATION } from '../useProjectName'; @@ -31,7 +31,7 @@ import { } from '@backstage/core-components'; import { errorApiRef, useApi } from '@backstage/core-plugin-api'; -const useStyles = makeStyles({ +const useStyles = makeStyles({ externalLinkIcon: { fontSize: 'inherit', verticalAlign: 'bottom', diff --git a/plugins/cloudbuild/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx b/plugins/cloudbuild/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx index a35d9b6f6c..f55d7957a3 100644 --- a/plugins/cloudbuild/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx +++ b/plugins/cloudbuild/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx @@ -25,7 +25,6 @@ import { TableCell, TableContainer, TableRow, - Theme, Typography, } from '@material-ui/core'; import ExternalLinkIcon from '@material-ui/icons/Launch'; @@ -36,7 +35,7 @@ import { WorkflowRunStatus } from '../WorkflowRunStatus'; import { useWorkflowRunsDetails } from './useWorkflowRunsDetails'; import { Breadcrumbs, Link, WarningPanel } from '@backstage/core-components'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ root: { maxWidth: 720, margin: theme.spacing(2), diff --git a/plugins/code-climate/CHANGELOG.md b/plugins/code-climate/CHANGELOG.md index cc10575866..a90f606447 100644 --- a/plugins/code-climate/CHANGELOG.md +++ b/plugins/code-climate/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-code-climate +## 0.1.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.1.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.1.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.1.26 ### Patch Changes diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 3f0ea38a5c..8c04865875 100644 --- a/plugins/code-climate/package.json +++ b/plugins/code-climate/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-code-climate", - "version": "0.1.26", + "version": "0.1.28-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index 6b951615b6..deaf2c0f4f 100644 --- a/plugins/code-coverage-backend/CHANGELOG.md +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/plugin-code-coverage-backend +## 0.2.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + +## 0.2.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.2.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.2.21 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 26bc8d8562..e0b1c15ccf 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage-backend", "description": "A Backstage backend plugin that helps you keep track of your code coverage", - "version": "0.2.21", + "version": "0.2.22-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md index 8e44f4b3c3..a0ab67a5eb 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-code-coverage +## 0.2.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.2.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.2.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.2.19 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 27c9a05240..227c7b5fc8 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage", "description": "A Backstage plugin that helps you keep track of your code coverage", - "version": "0.2.19", + "version": "0.2.21-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx index 09f499fafd..3cb4ad5d56 100644 --- a/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx +++ b/plugins/code-coverage/src/components/CoverageHistoryChart/CoverageHistoryChart.tsx @@ -15,7 +15,6 @@ */ import { useEntity } from '@backstage/plugin-catalog-react'; -import { BackstageTheme } from '@backstage/theme'; import { Box, Card, @@ -50,7 +49,7 @@ import { DateTime } from 'luxon'; type Coverage = 'line' | 'branch'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ trendDown: { color: theme.palette.status.warning, }, diff --git a/plugins/codescene/CHANGELOG.md b/plugins/codescene/CHANGELOG.md index 6e0d3ae6fc..c11691896a 100644 --- a/plugins/codescene/CHANGELOG.md +++ b/plugins/codescene/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-codescene +## 0.1.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.1.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.1.19 ### Patch Changes diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index b4ff1063cb..d464f7ee85 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-codescene", - "version": "0.1.19", + "version": "0.1.20-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/codescene/src/components/Gauge/Gauge.tsx b/plugins/codescene/src/components/Gauge/Gauge.tsx index 97e6b33daf..df91136b6a 100644 --- a/plugins/codescene/src/components/Gauge/Gauge.tsx +++ b/plugins/codescene/src/components/Gauge/Gauge.tsx @@ -13,13 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BackstagePalette, BackstageTheme } from '@backstage/theme'; + import { makeStyles, useTheme } from '@material-ui/core/styles'; +import { Palette } from '@material-ui/core/styles/createPalette'; import Tooltip from '@material-ui/core/Tooltip'; import { Circle } from 'rc-progress'; import React, { useEffect, useState } from 'react'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ root: { position: 'relative', @@ -51,7 +52,7 @@ export type GaugeProps = { }; export type GaugePropsGetColorOptions = { - palette: BackstagePalette; + palette: Palette; value: number; max: number; }; @@ -78,11 +79,10 @@ export const getProgressColor: GaugePropsGetColor = ({ /** * Circular Progress Bar - * */ export function Gauge(props: GaugeProps) { const classes = useStyles(props); - const { palette } = useTheme(); + const { palette } = useTheme(); const [hoverRef, setHoverRef] = useState(null); const [open, setOpen] = useState(false); const { value, max, tooltipDelay, tooltipText } = { diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index 51b911edfe..0409799b68 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-config-schema +## 0.1.48-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## 0.1.48-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + +## 0.1.48-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.1.47 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 32702c0cb0..ce63fa086b 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-config-schema", "description": "A Backstage plugin that lets you browse the configuration schema of your app", - "version": "0.1.47", + "version": "0.1.48-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index 90eb389a51..231b3d426a 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-cost-insights +## 0.12.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-cost-insights-common@0.1.2 + +## 0.12.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-cost-insights-common@0.1.2 + +## 0.12.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-cost-insights-common@0.1.2 + ## 0.12.15 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index bac6840839..2582bb04b7 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cost-insights", "description": "A Backstage plugin that helps you keep track of your cloud spend", - "version": "0.12.15", + "version": "0.12.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/cost-insights/src/utils/styles.ts b/plugins/cost-insights/src/utils/styles.ts index cec9c0150d..c4c330138b 100644 --- a/plugins/cost-insights/src/utils/styles.ts +++ b/plugins/cost-insights/src/utils/styles.ts @@ -21,9 +21,9 @@ import { getLuminance, lighten, makeStyles, + Theme, } from '@material-ui/core'; import { CostInsightsTheme, CostInsightsThemeOptions } from '../types'; -import { BackstageTheme } from '@backstage/theme'; export const costInsightsLightTheme = { palette: { @@ -231,7 +231,7 @@ export const useCostInsightsStyles = makeStyles(theme => ({ }, })); -export const useCostInsightsTabsStyles = makeStyles(theme => ({ +export const useCostInsightsTabsStyles = makeStyles(theme => ({ tabs: { borderBottom: `1px solid ${theme.palette.textVerySubtle}`, backgroundColor: brighten(theme.palette.background.default), diff --git a/plugins/devtools-backend/CHANGELOG.md b/plugins/devtools-backend/CHANGELOG.md index 7bd16724d8..b333d869f3 100644 --- a/plugins/devtools-backend/CHANGELOG.md +++ b/plugins/devtools-backend/CHANGELOG.md @@ -1,5 +1,56 @@ # @backstage/plugin-devtools-backend +## 0.2.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.6.0-next.0 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.6 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## 0.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-devtools-common@0.1.6 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + +## 0.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/config-loader@1.5.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.6 + - @backstage/plugin-permission-common@0.7.10 + ## 0.2.4 ### Patch Changes diff --git a/plugins/devtools-backend/package.json b/plugins/devtools-backend/package.json index d9763095b4..358d710b0d 100644 --- a/plugins/devtools-backend/package.json +++ b/plugins/devtools-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools-backend", - "version": "0.2.4", + "version": "0.2.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/devtools/CHANGELOG.md b/plugins/devtools/CHANGELOG.md index 5b8a39d4dd..c964fe5efe 100644 --- a/plugins/devtools/CHANGELOG.md +++ b/plugins/devtools/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-devtools +## 0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.6 + - @backstage/plugin-permission-react@0.4.18-next.1 + +## 0.1.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.6 + +## 0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.6 + ## 0.1.6 ### Patch Changes diff --git a/plugins/devtools/package.json b/plugins/devtools/package.json index d342645e2b..34b12ebc3d 100644 --- a/plugins/devtools/package.json +++ b/plugins/devtools/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools", - "version": "0.1.6", + "version": "0.1.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/dynatrace/CHANGELOG.md b/plugins/dynatrace/CHANGELOG.md index f9e13ac855..1d6999a63d 100644 --- a/plugins/dynatrace/CHANGELOG.md +++ b/plugins/dynatrace/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-dynatrace +## 8.0.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 8.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 8.0.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + ## 8.0.0 ### Patch Changes diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index 433dab8087..654b0d5df6 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-dynatrace", - "version": "8.0.0", + "version": "8.0.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback-backend/CHANGELOG.md b/plugins/entity-feedback-backend/CHANGELOG.md index 222588decc..23e4cd1c5f 100644 --- a/plugins/entity-feedback-backend/CHANGELOG.md +++ b/plugins/entity-feedback-backend/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-entity-feedback-backend +## 0.2.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## 0.2.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## 0.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-entity-feedback-common@0.1.3 + ## 0.2.4 ### Patch Changes diff --git a/plugins/entity-feedback-backend/package.json b/plugins/entity-feedback-backend/package.json index 7f4474a39a..b91c57f6dc 100644 --- a/plugins/entity-feedback-backend/package.json +++ b/plugins/entity-feedback-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-feedback-backend", - "version": "0.2.4", + "version": "0.2.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback/CHANGELOG.md b/plugins/entity-feedback/CHANGELOG.md index dfa555eb19..721087414c 100644 --- a/plugins/entity-feedback/CHANGELOG.md +++ b/plugins/entity-feedback/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-entity-feedback +## 0.2.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## 0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## 0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-entity-feedback-common@0.1.3 + ## 0.2.9 ### Patch Changes diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index 090c715bcc..9e90fbdd97 100644 --- a/plugins/entity-feedback/package.json +++ b/plugins/entity-feedback/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-feedback", - "version": "0.2.9", + "version": "0.2.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.tsx b/plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.tsx index 654cfd1413..863cdcc6b6 100644 --- a/plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.tsx +++ b/plugins/entity-feedback/src/components/FeedbackResponseTable/FeedbackResponseTable.tsx @@ -18,7 +18,6 @@ import { ErrorPanel, Table } from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; import { EntityRefLink } from '@backstage/plugin-catalog-react'; import { FeedbackResponse } from '@backstage/plugin-entity-feedback-common'; -import { BackstageTheme } from '@backstage/theme'; import { Chip, makeStyles } from '@material-ui/core'; import CheckIcon from '@material-ui/icons/Check'; import React from 'react'; @@ -28,7 +27,7 @@ import { entityFeedbackApiRef } from '../../api'; type ResponseRow = Omit; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ consentCheck: { color: theme.palette.status.ok, }, diff --git a/plugins/entity-validation/CHANGELOG.md b/plugins/entity-validation/CHANGELOG.md index c58ade3930..383aa44ed8 100644 --- a/plugins/entity-validation/CHANGELOG.md +++ b/plugins/entity-validation/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-entity-validation +## 0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + +## 0.1.13-next.1 + +### Patch Changes + +- a518c5a25b: Updated dependency `@react-hookz/web` to `^23.0.0`. +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-catalog-common@1.0.18 + +## 0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + ## 0.1.11 ### Patch Changes diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index 86480cf972..65534acc76 100644 --- a/plugins/entity-validation/package.json +++ b/plugins/entity-validation/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-entity-validation", - "version": "0.1.11", + "version": "0.1.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -43,7 +43,7 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", - "@react-hookz/web": "^20.0.0", + "@react-hookz/web": "^23.0.0", "@types/react": "^16.13.1 || ^17.0.0", "@uiw/react-codemirror": "^4.9.3", "lodash": "^4.17.21", diff --git a/plugins/events-backend-module-aws-sqs/CHANGELOG.md b/plugins/events-backend-module-aws-sqs/CHANGELOG.md index 06cebde4ad..879335c401 100644 --- a/plugins/events-backend-module-aws-sqs/CHANGELOG.md +++ b/plugins/events-backend-module-aws-sqs/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-events-backend-module-aws-sqs +## 0.2.11-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.2 + +## 0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## 0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.0 + ## 0.2.10 ### Patch Changes diff --git a/plugins/events-backend-module-aws-sqs/alpha-api-report.md b/plugins/events-backend-module-aws-sqs/api-report-alpha.md similarity index 100% rename from plugins/events-backend-module-aws-sqs/alpha-api-report.md rename to plugins/events-backend-module-aws-sqs/api-report-alpha.md diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index 0bc34c7df9..8bdd7b93bc 100644 --- a/plugins/events-backend-module-aws-sqs/package.json +++ b/plugins/events-backend-module-aws-sqs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-aws-sqs", - "version": "0.2.10", + "version": "0.2.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-aws-sqs/src/service/eventsModuleAwsSqsConsumingEventPublisher.ts b/plugins/events-backend-module-aws-sqs/src/service/eventsModuleAwsSqsConsumingEventPublisher.ts index 9045047094..eabab94708 100644 --- a/plugins/events-backend-module-aws-sqs/src/service/eventsModuleAwsSqsConsumingEventPublisher.ts +++ b/plugins/events-backend-module-aws-sqs/src/service/eventsModuleAwsSqsConsumingEventPublisher.ts @@ -29,7 +29,7 @@ import { AwsSqsConsumingEventPublisher } from '../publisher/AwsSqsConsumingEvent */ export const eventsModuleAwsSqsConsumingEventPublisher = createBackendModule({ pluginId: 'events', - moduleId: 'awsSqsConsumingEventPublisher', + moduleId: 'aws-sqs-consuming-event-publisher', register(env) { env.registerInit({ deps: { diff --git a/plugins/events-backend-module-azure/CHANGELOG.md b/plugins/events-backend-module-azure/CHANGELOG.md index cfaf0e5949..4ebc628da0 100644 --- a/plugins/events-backend-module-azure/CHANGELOG.md +++ b/plugins/events-backend-module-azure/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-events-backend-module-azure +## 0.1.18-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/plugin-events-node@0.2.17-next.2 + +## 0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## 0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/plugin-events-node@0.2.17-next.0 + ## 0.1.17 ### Patch Changes diff --git a/plugins/events-backend-module-azure/alpha-api-report.md b/plugins/events-backend-module-azure/api-report-alpha.md similarity index 100% rename from plugins/events-backend-module-azure/alpha-api-report.md rename to plugins/events-backend-module-azure/api-report-alpha.md diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index 12c2ce7cc1..1ed2869432 100644 --- a/plugins/events-backend-module-azure/package.json +++ b/plugins/events-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-azure", - "version": "0.1.17", + "version": "0.1.18-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-azure/src/service/eventsModuleAzureDevOpsEventRouter.ts b/plugins/events-backend-module-azure/src/service/eventsModuleAzureDevOpsEventRouter.ts index 36f3acada0..50bc384502 100644 --- a/plugins/events-backend-module-azure/src/service/eventsModuleAzureDevOpsEventRouter.ts +++ b/plugins/events-backend-module-azure/src/service/eventsModuleAzureDevOpsEventRouter.ts @@ -27,7 +27,7 @@ import { AzureDevOpsEventRouter } from '../router/AzureDevOpsEventRouter'; */ export const eventsModuleAzureDevOpsEventRouter = createBackendModule({ pluginId: 'events', - moduleId: 'azureDevOpsEventRouter', + moduleId: 'azure-dev-ops-event-router', register(env) { env.registerInit({ deps: { diff --git a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md index c9bb1d25f5..cc2ee606ea 100644 --- a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-events-backend-module-bitbucket-cloud +## 0.1.18-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/plugin-events-node@0.2.17-next.2 + +## 0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## 0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/plugin-events-node@0.2.17-next.0 + ## 0.1.17 ### Patch Changes diff --git a/plugins/events-backend-module-bitbucket-cloud/alpha-api-report.md b/plugins/events-backend-module-bitbucket-cloud/api-report-alpha.md similarity index 100% rename from plugins/events-backend-module-bitbucket-cloud/alpha-api-report.md rename to plugins/events-backend-module-bitbucket-cloud/api-report-alpha.md diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index 83aabe7ac6..3c8a6aa028 100644 --- a/plugins/events-backend-module-bitbucket-cloud/package.json +++ b/plugins/events-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-bitbucket-cloud", - "version": "0.1.17", + "version": "0.1.18-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-bitbucket-cloud/src/service/eventsModuleBitbucketCloudEventRouter.ts b/plugins/events-backend-module-bitbucket-cloud/src/service/eventsModuleBitbucketCloudEventRouter.ts index 60a8cc31c8..841a463001 100644 --- a/plugins/events-backend-module-bitbucket-cloud/src/service/eventsModuleBitbucketCloudEventRouter.ts +++ b/plugins/events-backend-module-bitbucket-cloud/src/service/eventsModuleBitbucketCloudEventRouter.ts @@ -27,7 +27,7 @@ import { BitbucketCloudEventRouter } from '../router/BitbucketCloudEventRouter'; */ export const eventsModuleBitbucketCloudEventRouter = createBackendModule({ pluginId: 'events', - moduleId: 'bitbucketCloudEventRouter', + moduleId: 'bitbucket-cloud-event-router', register(env) { env.registerInit({ deps: { diff --git a/plugins/events-backend-module-gerrit/CHANGELOG.md b/plugins/events-backend-module-gerrit/CHANGELOG.md index 81bf072e4a..28edd10328 100644 --- a/plugins/events-backend-module-gerrit/CHANGELOG.md +++ b/plugins/events-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-events-backend-module-gerrit +## 0.1.18-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/plugin-events-node@0.2.17-next.2 + +## 0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## 0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/plugin-events-node@0.2.17-next.0 + ## 0.1.17 ### Patch Changes diff --git a/plugins/events-backend-module-gerrit/alpha-api-report.md b/plugins/events-backend-module-gerrit/api-report-alpha.md similarity index 100% rename from plugins/events-backend-module-gerrit/alpha-api-report.md rename to plugins/events-backend-module-gerrit/api-report-alpha.md diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index c771792179..a561a52eaa 100644 --- a/plugins/events-backend-module-gerrit/package.json +++ b/plugins/events-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gerrit", - "version": "0.1.17", + "version": "0.1.18-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gerrit/src/service/eventsModuleGerritEventRouter.ts b/plugins/events-backend-module-gerrit/src/service/eventsModuleGerritEventRouter.ts index 8d490ea0b2..780ff7f878 100644 --- a/plugins/events-backend-module-gerrit/src/service/eventsModuleGerritEventRouter.ts +++ b/plugins/events-backend-module-gerrit/src/service/eventsModuleGerritEventRouter.ts @@ -27,7 +27,7 @@ import { GerritEventRouter } from '../router/GerritEventRouter'; */ export const eventsModuleGerritEventRouter = createBackendModule({ pluginId: 'events', - moduleId: 'gerritEventRouter', + moduleId: 'gerrit-event-router', register(env) { env.registerInit({ deps: { diff --git a/plugins/events-backend-module-github/CHANGELOG.md b/plugins/events-backend-module-github/CHANGELOG.md index 3112949e98..d06becd7db 100644 --- a/plugins/events-backend-module-github/CHANGELOG.md +++ b/plugins/events-backend-module-github/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-events-backend-module-github +## 0.1.18-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.2 + +## 0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## 0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.0 + ## 0.1.17 ### Patch Changes diff --git a/plugins/events-backend-module-github/alpha-api-report.md b/plugins/events-backend-module-github/api-report-alpha.md similarity index 100% rename from plugins/events-backend-module-github/alpha-api-report.md rename to plugins/events-backend-module-github/api-report-alpha.md diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index dfd3e12b6e..8639513699 100644 --- a/plugins/events-backend-module-github/package.json +++ b/plugins/events-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-github", - "version": "0.1.17", + "version": "0.1.18-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-github/src/service/eventsModuleGithubEventRouter.ts b/plugins/events-backend-module-github/src/service/eventsModuleGithubEventRouter.ts index 17485098c2..093307dfaf 100644 --- a/plugins/events-backend-module-github/src/service/eventsModuleGithubEventRouter.ts +++ b/plugins/events-backend-module-github/src/service/eventsModuleGithubEventRouter.ts @@ -27,7 +27,7 @@ import { GithubEventRouter } from '../router/GithubEventRouter'; */ export const eventsModuleGithubEventRouter = createBackendModule({ pluginId: 'events', - moduleId: 'githubEventRouter', + moduleId: 'github-event-router', register(env) { env.registerInit({ deps: { diff --git a/plugins/events-backend-module-github/src/service/eventsModuleGithubWebhook.ts b/plugins/events-backend-module-github/src/service/eventsModuleGithubWebhook.ts index b4bd666036..647b21c364 100644 --- a/plugins/events-backend-module-github/src/service/eventsModuleGithubWebhook.ts +++ b/plugins/events-backend-module-github/src/service/eventsModuleGithubWebhook.ts @@ -30,7 +30,7 @@ import { createGithubSignatureValidator } from '../http/createGithubSignatureVal */ export const eventsModuleGithubWebhook = createBackendModule({ pluginId: 'events', - moduleId: 'githubWebhook', + moduleId: 'github-webhook', register(env) { env.registerInit({ deps: { diff --git a/plugins/events-backend-module-gitlab/CHANGELOG.md b/plugins/events-backend-module-gitlab/CHANGELOG.md index dd1a112dde..8bb110a240 100644 --- a/plugins/events-backend-module-gitlab/CHANGELOG.md +++ b/plugins/events-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-events-backend-module-gitlab +## 0.1.18-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.2 + +## 0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## 0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.0 + ## 0.1.17 ### Patch Changes diff --git a/plugins/events-backend-module-gitlab/alpha-api-report.md b/plugins/events-backend-module-gitlab/api-report-alpha.md similarity index 100% rename from plugins/events-backend-module-gitlab/alpha-api-report.md rename to plugins/events-backend-module-gitlab/api-report-alpha.md diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index 3afa25a017..92453d78c2 100644 --- a/plugins/events-backend-module-gitlab/package.json +++ b/plugins/events-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend-module-gitlab", - "version": "0.1.17", + "version": "0.1.18-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabEventRouter.ts b/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabEventRouter.ts index 3425601529..fc44e95057 100644 --- a/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabEventRouter.ts +++ b/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabEventRouter.ts @@ -27,7 +27,7 @@ import { GitlabEventRouter } from '../router/GitlabEventRouter'; */ export const eventsModuleGitlabEventRouter = createBackendModule({ pluginId: 'events', - moduleId: 'gitlabEventRouter', + moduleId: 'gitlab-event-router', register(env) { env.registerInit({ deps: { diff --git a/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabWebhook.ts b/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabWebhook.ts index bd596b4baf..77bca7236b 100644 --- a/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabWebhook.ts +++ b/plugins/events-backend-module-gitlab/src/service/eventsModuleGitlabWebhook.ts @@ -32,7 +32,7 @@ import { createGitlabTokenValidator } from '../http/createGitlabTokenValidator'; */ export const eventsModuleGitlabWebhook = createBackendModule({ pluginId: 'events', - moduleId: 'gitlabWebhook', + moduleId: 'gitlab-webhook', register(env) { env.registerInit({ deps: { diff --git a/plugins/events-backend-test-utils/CHANGELOG.md b/plugins/events-backend-test-utils/CHANGELOG.md index f9e12dcbe3..5861eaa428 100644 --- a/plugins/events-backend-test-utils/CHANGELOG.md +++ b/plugins/events-backend-test-utils/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-events-backend-test-utils +## 0.1.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.17-next.2 + +## 0.1.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.17-next.1 + +## 0.1.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.17-next.0 + ## 0.1.17 ### Patch Changes diff --git a/plugins/events-backend-test-utils/package.json b/plugins/events-backend-test-utils/package.json index c189dc9ec4..837b188adc 100644 --- a/plugins/events-backend-test-utils/package.json +++ b/plugins/events-backend-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-events-backend-test-utils", "description": "The plugin-events-backend-test-utils for @backstage/plugin-events-node", - "version": "0.1.17", + "version": "0.1.18-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend/CHANGELOG.md b/plugins/events-backend/CHANGELOG.md index 626457814a..9ac727208f 100644 --- a/plugins/events-backend/CHANGELOG.md +++ b/plugins/events-backend/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-events-backend +## 0.2.17-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.2 + +## 0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.1 + +## 0.2.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.17-next.0 + ## 0.2.16 ### Patch Changes diff --git a/plugins/events-backend/README.md b/plugins/events-backend/README.md index 969e1bbcb2..29c420cef2 100644 --- a/plugins/events-backend/README.md +++ b/plugins/events-backend/README.md @@ -201,7 +201,7 @@ import { eventsExtensionPoint } from '@backstage/plugin-events-node'; export const yourModuleEventsModule = createBackendModule({ pluginId: 'events', - moduleId: 'yourModule', + moduleId: 'your-module', register(env) { // [...] env.registerInit({ @@ -252,7 +252,7 @@ import { eventsExtensionPoint } from '@backstage/plugin-events-node'; export const eventsModuleYourFeature = createBackendModule({ pluginId: 'events', - moduleId: 'yourFeature', + moduleId: 'your-feature', register(env) { // [...] env.registerInit({ diff --git a/plugins/events-backend/alpha-api-report.md b/plugins/events-backend/api-report-alpha.md similarity index 100% rename from plugins/events-backend/alpha-api-report.md rename to plugins/events-backend/api-report-alpha.md diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index f986f42651..ace840a60c 100644 --- a/plugins/events-backend/package.json +++ b/plugins/events-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-events-backend", - "version": "0.2.16", + "version": "0.2.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-node/CHANGELOG.md b/plugins/events-node/CHANGELOG.md index 7bc8152b5a..edacba99cd 100644 --- a/plugins/events-node/CHANGELOG.md +++ b/plugins/events-node/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-events-node +## 0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + +## 0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + +## 0.2.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + ## 0.2.16 ### Patch Changes diff --git a/plugins/events-node/alpha-api-report.md b/plugins/events-node/api-report-alpha.md similarity index 100% rename from plugins/events-node/alpha-api-report.md rename to plugins/events-node/api-report-alpha.md diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index 2ce27f7ca6..fea1a0ff82 100644 --- a/plugins/events-node/package.json +++ b/plugins/events-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-events-node", "description": "The plugin-events-node module for @backstage/plugin-events-backend", - "version": "0.2.16", + "version": "0.2.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/example-todo-list-backend/CHANGELOG.md b/plugins/example-todo-list-backend/CHANGELOG.md index 0e4bab1de3..698f0bd2d4 100644 --- a/plugins/example-todo-list-backend/CHANGELOG.md +++ b/plugins/example-todo-list-backend/CHANGELOG.md @@ -1,5 +1,38 @@ # @internal/plugin-todo-list-backend +## 1.0.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## 1.0.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 1.0.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 1.0.19 ### Patch Changes diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index 7ede62f19b..81ac1adcac 100644 --- a/plugins/example-todo-list-backend/package.json +++ b/plugins/example-todo-list-backend/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-backend", - "version": "1.0.19", + "version": "1.0.20-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/example-todo-list/CHANGELOG.md b/plugins/example-todo-list/CHANGELOG.md index 95f0f62ffb..e49acee4c1 100644 --- a/plugins/example-todo-list/CHANGELOG.md +++ b/plugins/example-todo-list/CHANGELOG.md @@ -1,5 +1,32 @@ # @internal/plugin-todo-list +## 1.0.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 1.0.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## 1.0.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + ## 1.0.19 ### Patch Changes diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index c7dfef7744..484b02601d 100644 --- a/plugins/example-todo-list/package.json +++ b/plugins/example-todo-list/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list", - "version": "1.0.19", + "version": "1.0.20-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore-backend/CHANGELOG.md b/plugins/explore-backend/CHANGELOG.md index 0c1d8f6b31..9f3d3c837e 100644 --- a/plugins/explore-backend/CHANGELOG.md +++ b/plugins/explore-backend/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-explore-backend +## 0.0.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.2 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.8 + +## 0.0.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.1 + - @backstage/plugin-search-common@1.2.8 + +## 0.0.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-search-backend-module-explore@0.1.12-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.8 + ## 0.0.17 ### Patch Changes diff --git a/plugins/explore-backend/package.json b/plugins/explore-backend/package.json index c13df1a1b9..f444599527 100644 --- a/plugins/explore-backend/package.json +++ b/plugins/explore-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-explore-backend", - "version": "0.0.17", + "version": "0.0.18-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore-react/CHANGELOG.md b/plugins/explore-react/CHANGELOG.md index 2aff4fce99..08217fd6de 100644 --- a/plugins/explore-react/CHANGELOG.md +++ b/plugins/explore-react/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-explore-react +## 0.0.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-explore-common@0.0.2 + +## 0.0.34-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-explore-common@0.0.2 + ## 0.0.33 ### Patch Changes diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index e67280c2ff..aee56ab3fd 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore-react", "description": "A frontend library for Backstage plugins that want to interact with the explore plugin", - "version": "0.0.33", + "version": "0.0.34-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index 6ef2d598c7..9d8535deba 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,57 @@ # @backstage/plugin-explore +## 0.4.14-next.2 + +### Patch Changes + +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-explore-react@0.0.34-next.1 + - @backstage/plugin-search-common@1.2.8 + +## 0.4.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/plugin-explore-react@0.0.34-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.8 + +## 0.4.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/plugin-explore-react@0.0.34-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.8 + ## 0.4.12 ### Patch Changes diff --git a/plugins/explore/alpha-api-report.md b/plugins/explore/api-report-alpha.md similarity index 75% rename from plugins/explore/alpha-api-report.md rename to plugins/explore/api-report-alpha.md index 8670338f3e..4d1afa89bf 100644 --- a/plugins/explore/alpha-api-report.md +++ b/plugins/explore/api-report-alpha.md @@ -4,14 +4,14 @@ ```ts import { BackstagePlugin } from '@backstage/frontend-plugin-api'; -import { Extension } from '@backstage/frontend-plugin-api'; +import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) const _default: BackstagePlugin<{}, {}>; export default _default; // @alpha (undocumented) -export const ExploreSearchResultListItemExtension: Extension<{ +export const ExploreSearchResultListItemExtension: ExtensionDefinition<{ noTrack?: boolean | undefined; }>; diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 7fe669e74c..341640dbbf 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore", "description": "A Backstage plugin for building an exploration page of your software ecosystem", - "version": "0.4.12", + "version": "0.4.14-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/explore/src/alpha.tsx b/plugins/explore/src/alpha.tsx index 1825af5ddb..f06379c84b 100644 --- a/plugins/explore/src/alpha.tsx +++ b/plugins/explore/src/alpha.tsx @@ -20,7 +20,6 @@ import { createSearchResultListItemExtension } from '@backstage/plugin-search-re /** @alpha */ export const ExploreSearchResultListItemExtension = createSearchResultListItemExtension({ - id: 'explore', predicate: result => result.type === 'tools', component: () => import('./components/ToolSearchResultListItem').then( diff --git a/plugins/explore/src/components/ToolCard/ToolCard.tsx b/plugins/explore/src/components/ToolCard/ToolCard.tsx index c2d9079f8f..47c2cfb41d 100644 --- a/plugins/explore/src/components/ToolCard/ToolCard.tsx +++ b/plugins/explore/src/components/ToolCard/ToolCard.tsx @@ -15,7 +15,6 @@ */ import { ExploreTool } from '@backstage/plugin-explore-react'; -import { BackstageTheme } from '@backstage/theme'; import { Box, Card, @@ -24,6 +23,7 @@ import { CardMedia, Chip, makeStyles, + Theme, Typography, } from '@material-ui/core'; import { LinkButton } from '@backstage/core-components'; @@ -32,7 +32,7 @@ import React from 'react'; // TODO: Align styling between Domain and ToolCard -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ media: { height: 128, diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index 3594528343..23612fd132 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-firehydrant +## 0.2.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.2.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.2.10 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index 61e9909fea..b16e34dd3a 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-firehydrant", "description": "A Backstage plugin that integrates towards FireHydrant", - "version": "0.2.10", + "version": "0.2.12-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index dcfec7fdb2..79e357e510 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-fossa +## 0.2.60-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.2.60-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.2.60-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.2.58 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index c87bd3b6cb..9cc11ba6d1 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-fossa", "description": "A Backstage plugin that integrates towards FOSSA", - "version": "0.2.58", + "version": "0.2.60-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcalendar/CHANGELOG.md b/plugins/gcalendar/CHANGELOG.md index fd16a9bf60..d27cbd1c53 100644 --- a/plugins/gcalendar/CHANGELOG.md +++ b/plugins/gcalendar/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-gcalendar +## 0.3.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.3.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.3.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/errors@1.2.3 + ## 0.3.20 ### Patch Changes diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index 64504f14e8..eb3df7606a 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcalendar", - "version": "0.3.20", + "version": "0.3.21-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index c2cbe56a29..32785c6523 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-gcp-projects +## 0.3.44-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.3.44-next.1 + +### Patch Changes + +- a518c5a25b: Updated dependency `@react-hookz/web` to `^23.0.0`. +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## 0.3.44-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + ## 0.3.43 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 7cf04c03eb..c025fb5781 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gcp-projects", "description": "A Backstage plugin that helps you manage projects in GCP", - "version": "0.3.43", + "version": "0.3.44-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -40,7 +40,7 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", - "@react-hookz/web": "^20.0.0", + "@react-hookz/web": "^23.0.0", "@types/react": "^16.13.1 || ^17.0.0" }, "peerDependencies": { diff --git a/plugins/gcp-projects/src/components/ProjectDetailsPage/ProjectDetailsPage.tsx b/plugins/gcp-projects/src/components/ProjectDetailsPage/ProjectDetailsPage.tsx index 364033ce73..9cde3a51c2 100644 --- a/plugins/gcp-projects/src/components/ProjectDetailsPage/ProjectDetailsPage.tsx +++ b/plugins/gcp-projects/src/components/ProjectDetailsPage/ProjectDetailsPage.tsx @@ -23,7 +23,6 @@ import { TableBody, TableCell, TableRow, - Theme, Typography, } from '@material-ui/core'; import React from 'react'; @@ -43,7 +42,7 @@ import { import { useApi, useRouteRef } from '@backstage/core-plugin-api'; import { rootRouteRef } from '../../routes'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ root: { maxWidth: 720, margin: theme.spacing(2), diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index 4cc38f3a5d..72a56328c2 100644 --- a/plugins/git-release-manager/CHANGELOG.md +++ b/plugins/git-release-manager/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-git-release-manager +## 0.3.40-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration@1.8.0-next.1 + +## 0.3.40-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/theme@0.5.0-next.0 + +## 0.3.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + ## 0.3.39 ### Patch Changes diff --git a/plugins/git-release-manager/api-report.md b/plugins/git-release-manager/api-report.md index 3e4c0847a7..d2dd7e909f 100644 --- a/plugins/git-release-manager/api-report.md +++ b/plugins/git-release-manager/api-report.md @@ -317,42 +317,42 @@ function LinearProgressWithLabel(props: { // 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; +const MOCK_RELEASE_BRANCH_NAME_CALVER = 'rc/2020.01.01_1'; // 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; +const MOCK_RELEASE_BRANCH_NAME_SEMVER = 'rc/1.2.3'; // 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; +const MOCK_RELEASE_CANDIDATE_TAG_NAME_CALVER = 'rc-2020.01.01_1'; // 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; +const MOCK_RELEASE_CANDIDATE_TAG_NAME_SEMVER = 'rc-1.2.3'; // 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; +const MOCK_RELEASE_NAME_CALVER = 'Version 2020.01.01_1'; // 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; +const MOCK_RELEASE_NAME_SEMVER = 'Version 1.2.3'; // 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; +const MOCK_RELEASE_VERSION_TAG_NAME_CALVER = 'version-2020.01.01_1'; // 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; +const MOCK_RELEASE_VERSION_TAG_NAME_SEMVER = 'version-1.2.3'; // 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) // diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 4c45244552..12df99ac0e 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-git-release-manager", "description": "A Backstage plugin that helps you manage releases in git", - "version": "0.3.39", + "version": "0.3.40-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index 7cb205acc5..757e4f6c41 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-github-actions +## 0.6.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + +## 0.6.9-next.1 + +### Patch Changes + +- 08d7e4676a: Github Workflow Runs UI is modified to show in optional Card view instead of table, with branch selection option +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.6.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.6.7 ### Patch Changes diff --git a/plugins/github-actions/README.md b/plugins/github-actions/README.md index b94862db2b..d0b5ceb54d 100644 --- a/plugins/github-actions/README.md +++ b/plugins/github-actions/README.md @@ -92,3 +92,19 @@ integrations: - There is a limit of 100 apps for one OAuth client/token pair - The OAuth application must be at the GitHub organization level in order to display the workflows. If you do not see any workflows, confirm the OAuth application was created in the organization and not a specific user account. + +## Optional Workflow Runs Card View + +Github Workflow Runs optional UI to show in Card view instead of table, with branch selection option + +```tsx + +// You can add the tab to any number of pages, the service page is shown as an +// example given here +const serviceEntityPage = ( + + {/* other tabs... */} + + + +``` diff --git a/plugins/github-actions/api-report.md b/plugins/github-actions/api-report.md index 887556f431..7a7eb4e972 100644 --- a/plugins/github-actions/api-report.md +++ b/plugins/github-actions/api-report.md @@ -16,6 +16,17 @@ import { RestEndpointMethodTypes } from '@octokit/rest'; import { RouteRef } from '@backstage/core-plugin-api'; import { ScmAuthApi } from '@backstage/integration-react'; +// @public (undocumented) +export type Branch = { + name: string; +}; + +// @public (undocumented) +export type Branches = { + default_branch: string; + branches: Branch[]; +}; + // @public (undocumented) export enum BuildStatus { // (undocumented) @@ -29,7 +40,7 @@ export enum BuildStatus { } // @public (undocumented) -export const EntityGithubActionsContent: () => JSX_2.Element; +export const EntityGithubActionsContent: (props: RouterProps) => JSX_2.Element; // @public (undocumented) export const EntityLatestGithubActionRunCard: (props: { @@ -106,6 +117,21 @@ export type GithubActionsApi = { }) => Promise< RestEndpointMethodTypes['actions']['downloadJobLogsForWorkflowRun']['response']['data'] >; + listBranches: (options: { + hostname?: string; + owner: string; + repo: string; + page: number; + }) => Promise< + RestEndpointMethodTypes['repos']['listBranches']['response']['data'] + >; + getDefaultBranch: (options: { + hostname?: string; + owner: string; + repo: string; + }) => Promise< + RestEndpointMethodTypes['repos']['get']['response']['data']['default_branch'] + >; }; // @public (undocumented) @@ -124,6 +150,14 @@ export class GithubActionsClient implements GithubActionsApi { RestEndpointMethodTypes['actions']['downloadJobLogsForWorkflowRun']['response']['data'] >; // (undocumented) + getDefaultBranch(options: { + hostname?: string; + owner: string; + repo: string; + }): Promise< + RestEndpointMethodTypes['repos']['get']['response']['data']['default_branch'] + >; + // (undocumented) getWorkflow(options: { hostname?: string; owner: string; @@ -142,6 +176,15 @@ export class GithubActionsClient implements GithubActionsApi { RestEndpointMethodTypes['actions']['getWorkflowRun']['response']['data'] >; // (undocumented) + listBranches(options: { + hostname?: string; + owner: string; + repo: string; + page?: number; + }): Promise< + RestEndpointMethodTypes['repos']['listBranches']['response']['data'] + >; + // (undocumented) listJobsForWorkflowRun(options: { hostname?: string; owner: string; @@ -226,7 +269,13 @@ export const RecentWorkflowRunsCard: (props: { }) => React_2.JSX.Element; // @public (undocumented) -export const Router: () => React_2.JSX.Element; +export const Router: (props: RouterProps) => React_2.JSX.Element; + +// @public (undocumented) +export interface RouterProps { + // (undocumented) + view?: 'cards' | 'table'; +} // @public (undocumented) export type Step = { diff --git a/plugins/github-actions/dev/index.tsx b/plugins/github-actions/dev/index.tsx index 153478ddbc..8321d33930 100644 --- a/plugins/github-actions/dev/index.tsx +++ b/plugins/github-actions/dev/index.tsx @@ -63,6 +63,12 @@ const mockGithubActionsApi: GithubActionsApi = { async reRunWorkflow() { return {} as any; }, + async listBranches() { + return {} as any; + }, + async getDefaultBranch() { + return {} as any; + }, }; createDevApp() diff --git a/plugins/github-actions/docs/card-view.png b/plugins/github-actions/docs/card-view.png new file mode 100644 index 0000000000..ef59c294d4 Binary files /dev/null and b/plugins/github-actions/docs/card-view.png differ diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 6f783ca9a5..e8e9a4712a 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-actions", "description": "A Backstage plugin that integrates towards GitHub Actions", - "version": "0.6.7", + "version": "0.6.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-actions/src/api/GithubActionsApi.ts b/plugins/github-actions/src/api/GithubActionsApi.ts index 14dbc3210e..6d3b25f93d 100644 --- a/plugins/github-actions/src/api/GithubActionsApi.ts +++ b/plugins/github-actions/src/api/GithubActionsApi.ts @@ -83,4 +83,21 @@ export type GithubActionsApi = { }) => Promise< RestEndpointMethodTypes['actions']['downloadJobLogsForWorkflowRun']['response']['data'] >; + + listBranches: (options: { + hostname?: string; + owner: string; + repo: string; + page: number; + }) => Promise< + RestEndpointMethodTypes['repos']['listBranches']['response']['data'] + >; + + getDefaultBranch: (options: { + hostname?: string; + owner: string; + repo: string; + }) => Promise< + RestEndpointMethodTypes['repos']['get']['response']['data']['default_branch'] + >; }; diff --git a/plugins/github-actions/src/api/GithubActionsClient.ts b/plugins/github-actions/src/api/GithubActionsClient.ts index e427c343e2..734326e61b 100644 --- a/plugins/github-actions/src/api/GithubActionsClient.ts +++ b/plugins/github-actions/src/api/GithubActionsClient.ts @@ -174,4 +174,41 @@ export class GithubActionsClient implements GithubActionsApi { return workflow.data; } + + async listBranches(options: { + hostname?: string; + owner: string; + repo: string; + page?: number; + }): Promise< + RestEndpointMethodTypes['repos']['listBranches']['response']['data'] + > { + const { hostname, owner, repo, page = 0 } = options; + const octokit = await this.getOctokit(hostname); + const response = await octokit.rest.repos.listBranches({ + owner, + repo, + per_page: 100, + page, + }); + + return response.data; + } + + async getDefaultBranch(options: { + hostname?: string; + owner: string; + repo: string; + }): Promise< + RestEndpointMethodTypes['repos']['get']['response']['data']['default_branch'] + > { + const { hostname, owner, repo } = options; + const octokit = await this.getOctokit(hostname); + const response = await octokit.rest.repos.get({ + owner, + repo, + }); + + return response.data.default_branch; + } } diff --git a/plugins/github-actions/src/api/types.ts b/plugins/github-actions/src/api/types.ts index 2e997d9bf7..394289149b 100644 --- a/plugins/github-actions/src/api/types.ts +++ b/plugins/github-actions/src/api/types.ts @@ -49,3 +49,19 @@ export enum BuildStatus { 'pending', 'running', } + +/** @public */ +export type Branch = { + name: string; +}; + +/** @public */ +export type Branches = { + default_branch: string; + branches: Branch[]; +}; + +/** @public */ +export interface RouterProps { + view?: 'cards' | 'table'; +} diff --git a/plugins/github-actions/src/components/Cards/Cards.tsx b/plugins/github-actions/src/components/Cards/Cards.tsx index 205288cba7..0075e3f775 100644 --- a/plugins/github-actions/src/components/Cards/Cards.tsx +++ b/plugins/github-actions/src/components/Cards/Cards.tsx @@ -15,12 +15,7 @@ */ import { useEntity } from '@backstage/plugin-catalog-react'; -import { - LinearProgress, - makeStyles, - Theme, - Typography, -} from '@material-ui/core'; +import { LinearProgress, makeStyles, Typography } from '@material-ui/core'; import ExternalLinkIcon from '@material-ui/icons/Launch'; import React, { useEffect } from 'react'; import { GITHUB_ACTIONS_ANNOTATION } from '../getProjectNameFromEntity'; @@ -36,7 +31,7 @@ import { } from '@backstage/core-components'; import { getHostnameFromEntity } from '../getHostnameFromEntity'; -const useStyles = makeStyles({ +const useStyles = makeStyles({ externalLinkIcon: { fontSize: 'inherit', verticalAlign: 'bottom', diff --git a/plugins/github-actions/src/components/Router.tsx b/plugins/github-actions/src/components/Router.tsx index e9a40f13f4..ff4e6bfa44 100644 --- a/plugins/github-actions/src/components/Router.tsx +++ b/plugins/github-actions/src/components/Router.tsx @@ -23,15 +23,18 @@ import { import { Routes, Route } from 'react-router-dom'; import { buildRouteRef } from '../routes'; import { WorkflowRunDetails } from './WorkflowRunDetails'; +import { WorkflowRunsCard } from './WorkflowRunsCard'; import { WorkflowRunsTable } from './WorkflowRunsTable'; import { GITHUB_ACTIONS_ANNOTATION } from './getProjectNameFromEntity'; +import { RouterProps } from '../api/types'; /** @public */ export const isGithubActionsAvailable = (entity: Entity) => Boolean(entity.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION]); /** @public */ -export const Router = () => { +export const Router = (props: RouterProps) => { + const { view = 'table' } = props; const { entity } = useEntity(); if (!isGithubActionsAvailable(entity)) { @@ -39,14 +42,21 @@ export const Router = () => { ); } + + const workflowRunsComponent = + view === 'cards' ? ( + + ) : ( + + ); + return ( - } /> + } /> - ) ); }; diff --git a/plugins/github-actions/src/components/WorkflowRunLogs/WorkflowRunLogs.tsx b/plugins/github-actions/src/components/WorkflowRunLogs/WorkflowRunLogs.tsx index 2bf8d3356b..c83da2efdd 100644 --- a/plugins/github-actions/src/components/WorkflowRunLogs/WorkflowRunLogs.tsx +++ b/plugins/github-actions/src/components/WorkflowRunLogs/WorkflowRunLogs.tsx @@ -23,7 +23,6 @@ import { Fade, makeStyles, Modal, - Theme, Tooltip, Typography, Zoom, @@ -35,7 +34,7 @@ import { getProjectNameFromEntity } from '../getProjectNameFromEntity'; import { useDownloadWorkflowRunLogs } from './useDownloadWorkflowRunLogs'; import { getHostnameFromEntity } from '../getHostnameFromEntity'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ button: { order: -1, marginRight: 0, diff --git a/plugins/github-actions/src/components/WorkflowRunsCard/WorkflowRunsCard.tsx b/plugins/github-actions/src/components/WorkflowRunsCard/WorkflowRunsCard.tsx new file mode 100644 index 0000000000..dc97720736 --- /dev/null +++ b/plugins/github-actions/src/components/WorkflowRunsCard/WorkflowRunsCard.tsx @@ -0,0 +1,412 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React, { ChangeEvent, useEffect, useState } from 'react'; +import { + Typography, + Box, + IconButton, + Tooltip, + Button, + Chip, + ButtonGroup, + Grid, + makeStyles, + createStyles, + Theme, + TablePagination, + Select, + MenuItem, + TextField, + CircularProgress, +} from '@material-ui/core'; +import { + EmptyState, + Link, + MarkdownContent, + InfoCard, +} from '@backstage/core-components'; +import GitHubIcon from '@material-ui/icons/GitHub'; +import RetryIcon from '@material-ui/icons/Replay'; +import SyncIcon from '@material-ui/icons/Sync'; +import ExternalLinkIcon from '@material-ui/icons/Launch'; +import { useRouteRef } from '@backstage/core-plugin-api'; +import { useWorkflowRuns, WorkflowRun } from '../useWorkflowRuns'; +import { WorkflowRunStatus } from '../WorkflowRunStatus'; +import { buildRouteRef } from '../../routes'; +import { getProjectNameFromEntity } from '../getProjectNameFromEntity'; +import { getHostnameFromEntity } from '../getHostnameFromEntity'; + +import { Alert, Color } from '@material-ui/lab'; +import { Entity } from '@backstage/catalog-model'; + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + card: { + border: `1px solid ${theme.palette.divider}`, + boxShadow: theme.shadows[2], + borderRadius: '4px', + overflow: 'visible', + position: 'relative', + margin: theme.spacing(4, 1, 1), + flex: '1', + minWidth: '0px', + }, + externalLinkIcon: { + fontSize: 'inherit', + verticalAlign: 'middle', + }, + bottomline: { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + marginTop: '-5px', + }, + pagination: { + width: '100%', + }, + }), +); + +type WorkflowRunsCardViewProps = { + runs?: WorkflowRun[]; + searchTerm: string; + loading: boolean; + onChangePageSize: (pageSize: number) => void; + onChangePage: (page: number) => void; + page: number; + total: number; + pageSize: number; + projectName: string; +}; + +const statusColors: Record = { + skipped: 'warning', + canceled: 'info', + timed_out: 'error', + failure: 'error', + success: 'success', +}; + +const matchesSearchTerm = (run: WorkflowRun, searchTerm: string) => { + const lowerCaseSearchTerm = searchTerm.toLocaleLowerCase(); + return ( + run.workflowName?.toLocaleLowerCase().includes(lowerCaseSearchTerm) || + run.source.branchName?.toLocaleLowerCase().includes(lowerCaseSearchTerm) || + run.status?.toLocaleLowerCase().includes(lowerCaseSearchTerm) || + run.id?.toLocaleLowerCase().includes(lowerCaseSearchTerm) + ); +}; + +export const WorkflowRunsCardView = ({ + runs, + searchTerm, + loading, + onChangePageSize, + onChangePage, + page, + total, + pageSize, +}: WorkflowRunsCardViewProps) => { + const classes = useStyles(); + const routeLink = useRouteRef(buildRouteRef); + + const filteredRuns = runs?.filter(run => matchesSearchTerm(run, searchTerm)); + + return ( + + {filteredRuns && runs?.length !== 0 ? ( + filteredRuns.map(run => ( + + + + + + + + + + {run.workflowName} + + + + + + + + + + + + {run.source.branchName && ( + + )} + + + + + } + /> +
+ {run.githubUrl && ( + + Workflow runs on GitHub{' '} + + + )} + + + + + + + +
+
+
+ +
+ )) + ) : ( + + {loading ? : 'No matching runs found.'} + + )} +
+ onChangePage(newPage)} + onRowsPerPageChange={event => + onChangePageSize(parseInt(event.target.value, 6)) + } + labelRowsPerPage="Workflows per page" + rowsPerPageOptions={[6, 12, 18, { label: 'All', value: -1 }]} + /> +
+
+ ); +}; + +type WorkflowRunsCardProps = { + entity: Entity; +}; + +const WorkflowRunsCardSearch = ({ + searchTerm, + handleSearch, + retry, +}: { + searchTerm: string; + handleSearch: (event: ChangeEvent) => void; + retry: () => void; +}) => { + return ( + <> + + + + + + + + + + + ); +}; + +export const WorkflowRunsCard = ({ entity }: WorkflowRunsCardProps) => { + const projectName = getProjectNameFromEntity(entity); + const hostname = getHostnameFromEntity(entity); + const [owner, repo] = (projectName ?? '/').split('/'); + const [branch, setBranch] = useState('default'); + const [runs, setRuns] = useState([]); + const [searchTerm, setSearchTerm] = useState(''); + + const handleSearch = (event: ChangeEvent) => { + setSearchTerm(event.target.value); + }; + + const [ + { runs: runsData, branches, defaultBranch, ...cardProps }, + { retry, setPage, setPageSize }, + ] = useWorkflowRuns({ + hostname, + owner, + repo, + branch: branch === 'all' ? undefined : branch, + }); + + const githubHost = hostname || 'github.com'; + const hasNoRuns = !cardProps.loading && !runsData; + + const handleMenuChange = ( + event: ChangeEvent<{ name?: string; value: unknown }>, + ) => { + const selectedValue = event.target.value as string; + setBranch(selectedValue); + setPage(0); + retry(); + }; + + useEffect(() => { + setRuns(runsData); + }, [runsData, branch]); + + useEffect(() => { + setBranch(defaultBranch); + }, [defaultBranch]); + + return ( + + {hasNoRuns ? ( + + Create new Workflow + + } + /> + ) : ( + + + + {projectName} + + + + + + } + > + + + )} + + ); +}; + +export default WorkflowRunsCard; diff --git a/plugins/catalog-graphql/src/setupTests.ts b/plugins/github-actions/src/components/WorkflowRunsCard/index.ts similarity index 88% rename from plugins/catalog-graphql/src/setupTests.ts rename to plugins/github-actions/src/components/WorkflowRunsCard/index.ts index 8f32650781..77b4c85664 100644 --- a/plugins/catalog-graphql/src/setupTests.ts +++ b/plugins/github-actions/src/components/WorkflowRunsCard/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export {}; +export { WorkflowRunsCard, WorkflowRunsCardView } from './WorkflowRunsCard'; diff --git a/plugins/github-actions/src/components/useWorkflowRuns.ts b/plugins/github-actions/src/components/useWorkflowRuns.ts index 9ffbdad452..aacfabbe2f 100644 --- a/plugins/github-actions/src/components/useWorkflowRuns.ts +++ b/plugins/github-actions/src/components/useWorkflowRuns.ts @@ -17,6 +17,7 @@ import { useState } from 'react'; import useAsyncRetry from 'react-use/lib/useAsyncRetry'; import { githubActionsApiRef } from '../api/GithubActionsApi'; import { useApi, errorApiRef } from '@backstage/core-plugin-api'; +import { Branch } from '../api'; export type WorkflowRun = { workflowName?: string; @@ -41,12 +42,12 @@ export function useWorkflowRuns({ owner, repo, branch, - initialPageSize = 5, + initialPageSize = 6, }: { hostname?: string; owner: string; repo: string; - branch?: string; + branch?: string | undefined; initialPageSize?: number; }) { const api = useApi(githubActionsApiRef); @@ -56,6 +57,8 @@ export function useWorkflowRuns({ const [total, setTotal] = useState(0); const [page, setPage] = useState(0); const [pageSize, setPageSize] = useState(initialPageSize); + const [branches, setBranches] = useState([]); + const [defaultBranch, setDefaultBranch] = useState(''); const { loading, @@ -63,6 +66,43 @@ export function useWorkflowRuns({ retry, error, } = useAsyncRetry(async () => { + const fetchedDefaultBranch = await api.getDefaultBranch({ + hostname, + owner, + repo, + }); + + setDefaultBranch(fetchedDefaultBranch); + let selectedBranch = branch; + if (branch === 'default') { + selectedBranch = fetchedDefaultBranch; + } + + const fetchBranches = async () => { + let next = true; + let iteratePage = 0; + const branchSet: Branch[] = []; + + while (next) { + const branchesData = await api.listBranches({ + hostname, + owner, + repo, + page: iteratePage, + }); + if (branchesData.length === 0) { + next = false; + } + iteratePage++; + branchSet.push(...branchesData); + } + + return branchSet; + }; + + const branchSet = await fetchBranches(); + setBranches(branchSet); + // GitHub API pagination count starts from 1 const workflowRunsData = await api.listWorkflowRuns({ hostname, @@ -70,7 +110,7 @@ export function useWorkflowRuns({ repo, pageSize, page: page + 1, - branch, + branch: selectedBranch, }); setTotal(workflowRunsData.total_count); // Transformation here @@ -88,7 +128,7 @@ export function useWorkflowRuns({ }); } catch (e) { errorApi.post( - new Error(`Failed to rerun the workflow: ${e.message}`), + new Error(`Failed to rerun the workflow: ${(e as Error).message}`), ); } }, @@ -115,6 +155,8 @@ export function useWorkflowRuns({ pageSize, loading, runs, + branches, + defaultBranch, projectName: `${owner}/${repo}`, total, error, diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index 32739b5817..7cf3d34d42 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/plugin-github-deployments +## 0.1.59-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + +## 0.1.59-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.1.59-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.1.57 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index 4717ad590a..0aed35feda 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-deployments", "description": "A Backstage plugin that integrates towards GitHub Deployments", - "version": "0.1.57", + "version": "0.1.59-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-issues/CHANGELOG.md b/plugins/github-issues/CHANGELOG.md index 2384b17bf4..93a26f0267 100644 --- a/plugins/github-issues/CHANGELOG.md +++ b/plugins/github-issues/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-github-issues +## 0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + +## 0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.2.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.2.15 ### Patch Changes diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index 255599b266..80c117457d 100644 --- a/plugins/github-issues/package.json +++ b/plugins/github-issues/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-github-issues", - "version": "0.2.15", + "version": "0.2.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/github-pull-requests-board/CHANGELOG.md b/plugins/github-pull-requests-board/CHANGELOG.md index 350623935e..582bda0c5c 100644 --- a/plugins/github-pull-requests-board/CHANGELOG.md +++ b/plugins/github-pull-requests-board/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-github-pull-requests-board +## 0.1.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration@1.8.0-next.1 + +## 0.1.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.1.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.1.20 ### Patch Changes diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index 09b64e6a48..4f1808838d 100644 --- a/plugins/github-pull-requests-board/package.json +++ b/plugins/github-pull-requests-board/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-pull-requests-board", "description": "A Backstage plugin that allows you to see all open Pull Requests for all the repositories owned by your team", - "version": "0.1.20", + "version": "0.1.22-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gitops-profiles/CHANGELOG.md b/plugins/gitops-profiles/CHANGELOG.md index 4f8b0ec59c..8aed7b63cb 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-gitops-profiles +## 0.3.43-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.3.43-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + +## 0.3.43-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/config@1.1.1 + ## 0.3.42 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index 99d3257265..e1fbea8112 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gitops-profiles", "description": "A Backstage plugin that helps you manage GitOps profiles", - "version": "0.3.42", + "version": "0.3.43-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/gocd/CHANGELOG.md b/plugins/gocd/CHANGELOG.md index 4d418eb187..468e843212 100644 --- a/plugins/gocd/CHANGELOG.md +++ b/plugins/gocd/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-gocd +## 0.1.34-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.1.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.1.34-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.1.32 ### Patch Changes diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index 105294962c..3d597f1ef3 100644 --- a/plugins/gocd/package.json +++ b/plugins/gocd/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gocd", "description": "A Backstage plugin that integrates towards GoCD", - "version": "0.1.32", + "version": "0.1.34-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index c8ba623ff4..6b97494401 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,49 @@ # @backstage/plugin-graphiql +## 0.3.1-next.3 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 8f5d6c1: Updates to the `/alpha` exports to match the extension input wrapping change. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.3.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## 0.3.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + +## 0.3.1-next.0 + +### Patch Changes + +- 03d0b6dcdc: The `convertLegacyRouteRef` utility used by the alpha exports is now imported from `@backstage/core-compat-api`. +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + ## 0.3.0 ### Minor Changes diff --git a/plugins/graphiql/alpha-api-report.md b/plugins/graphiql/api-report-alpha.md similarity index 69% rename from plugins/graphiql/alpha-api-report.md rename to plugins/graphiql/api-report-alpha.md index 3362cf0a59..c5895067df 100644 --- a/plugins/graphiql/alpha-api-report.md +++ b/plugins/graphiql/api-report-alpha.md @@ -4,20 +4,21 @@ ```ts import { BackstagePlugin } from '@backstage/frontend-plugin-api'; -import { Extension } from '@backstage/frontend-plugin-api'; +import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { GraphQLEndpoint } from '@backstage/plugin-graphiql'; import { PortableSchema } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -export function createEndpointExtension(options: { - id: string; +export function createGraphiQLEndpointExtension(options: { + namespace?: string; + name?: string; configSchema?: PortableSchema; disabled?: boolean; factory: (options: { config: TConfig }) => { endpoint: GraphQLEndpoint; }; -}): Extension; +}): ExtensionDefinition; // @alpha (undocumented) const _default: BackstagePlugin< @@ -29,15 +30,15 @@ const _default: BackstagePlugin< export default _default; // @alpha (undocumented) -export const graphiqlBrowseApi: Extension<{}>; +export const graphiqlBrowseApi: ExtensionDefinition<{}>; // @alpha (undocumented) -export const GraphiqlPage: Extension<{ +export const GraphiqlPage: ExtensionDefinition<{ path: string; }>; // @alpha (undocumented) -export const graphiqlPageSidebarItem: Extension<{ +export const graphiqlPageSidebarItem: ExtensionDefinition<{ title: string; }>; diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index bd8de81087..0746180f76 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphiql", "description": "Backstage plugin for browsing GraphQL APIs", - "version": "0.3.0", + "version": "0.3.1-next.3", "publishConfig": { "access": "public" }, diff --git a/plugins/graphiql/src/alpha.tsx b/plugins/graphiql/src/alpha.tsx index 760bc77d8e..2fbd9235ac 100644 --- a/plugins/graphiql/src/alpha.tsx +++ b/plugins/graphiql/src/alpha.tsx @@ -34,19 +34,21 @@ import { } from '@backstage/plugin-graphiql'; import { createApiFactory, IconComponent } from '@backstage/core-plugin-api'; import { graphiQLRouteRef } from './route-refs'; -import { convertLegacyRouteRef } from '@backstage/core-compat-api'; +import { + compatWrapper, + convertLegacyRouteRef, +} from '@backstage/core-compat-api'; /** @alpha */ export const GraphiqlPage = createPageExtension({ - id: 'plugin.graphiql.page', defaultPath: '/graphiql', routeRef: convertLegacyRouteRef(graphiQLRouteRef), - loader: () => import('./components').then(m => ), + loader: () => + import('./components').then(m => compatWrapper()), }); /** @alpha */ export const graphiqlPageSidebarItem = createNavItemExtension({ - id: 'plugin.graphiql.nav.index', title: 'GraphiQL', icon: GraphiQLIcon as IconComponent, routeRef: convertLegacyRouteRef(graphiQLRouteRef), @@ -59,7 +61,7 @@ const endpointDataRef = createExtensionDataRef( /** @alpha */ export const graphiqlBrowseApi = createApiExtension({ - api: graphQlBrowseApiRef, // apis.plugin.graphiql.browse + api: graphQlBrowseApiRef, inputs: { endpoints: createExtensionInput({ endpoint: endpointDataRef, @@ -68,21 +70,24 @@ export const graphiqlBrowseApi = createApiExtension({ factory({ inputs }) { return createApiFactory( graphQlBrowseApiRef, - GraphQLEndpoints.from(inputs.endpoints.map(i => i.endpoint)), + GraphQLEndpoints.from(inputs.endpoints.map(i => i.output.endpoint)), ); }, }); /** @alpha */ -export function createEndpointExtension(options: { - id: string; +export function createGraphiQLEndpointExtension(options: { + namespace?: string; + name?: string; configSchema?: PortableSchema; disabled?: boolean; factory: (options: { config: TConfig }) => { endpoint: GraphQLEndpoint }; }) { return createExtension({ - id: `apis.plugin.graphiql.browse.${options.id}`, - attachTo: { id: 'apis.plugin.graphiql.browse', input: 'endpoints' }, + kind: 'graphiql-endpoint', + namespace: options.namespace, + name: options.name, + attachTo: { id: 'api:graphiql/browse', input: 'endpoints' }, configSchema: options.configSchema, disabled: options.disabled ?? false, output: { @@ -97,8 +102,8 @@ export function createEndpointExtension(options: { } /** @alpha */ -const gitlabGraphiQLBrowseExtension = createEndpointExtension({ - id: 'gitlab', +const gitlabGraphiQLBrowseExtension = createGraphiQLEndpointExtension({ + name: 'gitlab', disabled: true, configSchema: createSchemaFromZod(z => z diff --git a/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx b/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx index 40c2c168a8..cdd924a6d1 100644 --- a/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx +++ b/plugins/graphiql/src/components/GraphiQLBrowser/GraphiQLBrowser.tsx @@ -19,14 +19,13 @@ import { Tabs, Tab, makeStyles, Typography, Divider } from '@material-ui/core'; import 'graphiql/graphiql.css'; import { StorageBucket } from '../../lib/storage'; import { GraphQLEndpoint } from '../../lib/api'; -import { BackstageTheme } from '@backstage/theme'; import { Progress } from '@backstage/core-components'; const GraphiQL = React.lazy(() => import('graphiql').then(m => ({ default: m.GraphiQL })), ); -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ root: { height: '100%', display: 'flex', diff --git a/plugins/graphql-backend/CHANGELOG.md b/plugins/graphql-backend/CHANGELOG.md deleted file mode 100644 index 851f7b6d7f..0000000000 --- a/plugins/graphql-backend/CHANGELOG.md +++ /dev/null @@ -1,902 +0,0 @@ -# @backstage/plugin-graphql-backend - -## 0.2.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.9 - - @backstage/plugin-catalog-graphql@0.4.1 - - @backstage/config@1.1.1 - -## 0.2.1-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.9-next.2 - -## 0.2.1-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.9-next.1 - - @backstage/config@1.1.1 - - @backstage/plugin-catalog-graphql@0.4.1-next.0 - -## 0.2.1-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-catalog-graphql@0.4.1-next.0 - - @backstage/backend-common@0.19.9-next.0 - - @backstage/config@1.1.1 - -## 0.2.0 - -### Minor Changes - -- 9def1e95ab: This package has been deprecated, consider using [@frontside/backstage-plugin-graphql-backend](https://www.npmjs.com/package/@frontside/backstage-plugin-graphql-backend) instead. - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.8 - - @backstage/plugin-catalog-graphql@0.4.0 - - @backstage/config@1.1.1 - -## 0.1.44-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.8-next.2 - - @backstage/config@1.1.1-next.0 - - @backstage/plugin-catalog-graphql@0.3.24-next.0 - -## 0.1.43-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.7-next.1 - - @backstage/config@1.1.0 - - @backstage/plugin-catalog-graphql@0.3.23 - -## 0.1.43-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.7-next.0 - - @backstage/config@1.1.0 - - @backstage/plugin-catalog-graphql@0.3.23 - -## 0.1.41 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.5 - - @backstage/config@1.1.0 - - @backstage/plugin-catalog-graphql@0.3.23 - -## 0.1.41-next.3 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.1.0-next.2 - - @backstage/backend-common@0.19.5-next.3 - - @backstage/plugin-catalog-graphql@0.3.23-next.2 - -## 0.1.41-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.1.0-next.1 - - @backstage/backend-common@0.19.5-next.2 - - @backstage/plugin-catalog-graphql@0.3.23-next.1 - -## 0.1.41-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.1.0-next.0 - - @backstage/backend-common@0.19.5-next.1 - - @backstage/plugin-catalog-graphql@0.3.23-next.0 - -## 0.1.40-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.4-next.0 - - @backstage/config@1.0.8 - - @backstage/plugin-catalog-graphql@0.3.22 - -## 0.1.38 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.2 - - @backstage/config@1.0.8 - - @backstage/plugin-catalog-graphql@0.3.22 - -## 0.1.38-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.2-next.2 - -## 0.1.38-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.2-next.1 - - @backstage/config@1.0.8 - - @backstage/plugin-catalog-graphql@0.3.22 - -## 0.1.38-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.2-next.0 - - @backstage/config@1.0.8 - - @backstage/plugin-catalog-graphql@0.3.22 - -## 0.1.37 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.1 - - @backstage/config@1.0.8 - - @backstage/plugin-catalog-graphql@0.3.22 - -## 0.1.37-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.1-next.0 - - @backstage/config@1.0.8 - - @backstage/plugin-catalog-graphql@0.3.22-next.0 - -## 0.1.36 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.0 - - @backstage/config@1.0.8 - - @backstage/plugin-catalog-graphql@0.3.21 - -## 0.1.36-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.0-next.2 - - @backstage/config@1.0.7 - - @backstage/plugin-catalog-graphql@0.3.21-next.1 - -## 0.1.36-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.19.0-next.1 - - @backstage/plugin-catalog-graphql@0.3.21-next.0 - - @backstage/config@1.0.7 - -## 0.1.36-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.6-next.0 - - @backstage/config@1.0.7 - - @backstage/plugin-catalog-graphql@0.3.20 - -## 0.1.35 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.5 - - @backstage/config@1.0.7 - - @backstage/plugin-catalog-graphql@0.3.20 - -## 0.1.35-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.5-next.1 - - @backstage/config@1.0.7 - - @backstage/plugin-catalog-graphql@0.3.20 - -## 0.1.35-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.5-next.0 - - @backstage/config@1.0.7 - - @backstage/plugin-catalog-graphql@0.3.20 - -## 0.1.34 - -### Patch Changes - -- e47e69eadf0: Updated dependency `@apollo/server` to `^4.0.0`. -- Updated dependencies - - @backstage/backend-common@0.18.4 - - @backstage/plugin-catalog-graphql@0.3.20 - - @backstage/config@1.0.7 - -## 0.1.34-next.3 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.4-next.2 - - @backstage/config@1.0.7 - - @backstage/plugin-catalog-graphql@0.3.20-next.2 - -## 0.1.34-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.4-next.2 - - @backstage/config@1.0.7 - - @backstage/plugin-catalog-graphql@0.3.20-next.1 - -## 0.1.34-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-catalog-graphql@0.3.20-next.1 - - @backstage/backend-common@0.18.4-next.1 - - @backstage/config@1.0.7 - -## 0.1.34-next.0 - -### Patch Changes - -- e47e69eadf0: Updated dependency `@apollo/server` to `^4.0.0`. -- Updated dependencies - - @backstage/plugin-catalog-graphql@0.3.20-next.0 - - @backstage/backend-common@0.18.4-next.0 - - @backstage/config@1.0.7 - -## 0.1.33 - -### Patch Changes - -- 52b0022dab7: Updated dependency `msw` to `^1.0.0`. -- Updated dependencies - - @backstage/backend-common@0.18.3 - - @backstage/plugin-catalog-graphql@0.3.19 - - @backstage/config@1.0.7 - -## 0.1.33-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.3-next.2 - - @backstage/config@1.0.7-next.0 - - @backstage/plugin-catalog-graphql@0.3.19-next.1 - -## 0.1.33-next.1 - -### Patch Changes - -- 52b0022dab7: Updated dependency `msw` to `^1.0.0`. -- Updated dependencies - - @backstage/plugin-catalog-graphql@0.3.19-next.1 - - @backstage/backend-common@0.18.3-next.1 - - @backstage/config@1.0.7-next.0 - -## 0.1.33-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.3-next.0 - - @backstage/config@1.0.6 - - @backstage/plugin-catalog-graphql@0.3.19-next.0 - -## 0.1.32 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.2 - - @backstage/config@1.0.6 - - @backstage/plugin-catalog-graphql@0.3.18 - -## 0.1.32-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.2-next.2 - - @backstage/config@1.0.6 - - @backstage/plugin-catalog-graphql@0.3.18-next.1 - -## 0.1.32-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.2-next.1 - - @backstage/config@1.0.6 - - @backstage/plugin-catalog-graphql@0.3.18-next.0 - -## 0.1.32-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.2-next.0 - - @backstage/plugin-catalog-graphql@0.3.18-next.0 - -## 0.1.30 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.0 - - @backstage/config@1.0.6 - - @backstage/plugin-catalog-graphql@0.3.17 - -## 0.1.30-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.0-next.1 - - @backstage/config@1.0.6-next.0 - - @backstage/plugin-catalog-graphql@0.3.17-next.1 - -## 0.1.30-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.18.0-next.0 - - @backstage/config@1.0.6-next.0 - - @backstage/plugin-catalog-graphql@0.3.17-next.1 - -## 0.1.30-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.17.0 - - @backstage/config@1.0.5 - - @backstage/plugin-catalog-graphql@0.3.17-next.0 - -## 0.1.29 - -### Patch Changes - -- 3280711113: Updated dependency `msw` to `^0.49.0`. -- Updated dependencies - - @backstage/backend-common@0.17.0 - - @backstage/plugin-catalog-graphql@0.3.16 - - @backstage/config@1.0.5 - -## 0.1.29-next.3 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.17.0-next.3 - - @backstage/config@1.0.5-next.1 - - @backstage/plugin-catalog-graphql@0.3.16-next.1 - -## 0.1.29-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.17.0-next.2 - - @backstage/config@1.0.5-next.1 - - @backstage/plugin-catalog-graphql@0.3.16-next.1 - -## 0.1.29-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.17.0-next.1 - - @backstage/config@1.0.5-next.1 - - @backstage/plugin-catalog-graphql@0.3.16-next.1 - -## 0.1.29-next.0 - -### Patch Changes - -- 3280711113: Updated dependency `msw` to `^0.49.0`. -- Updated dependencies - - @backstage/backend-common@0.16.1-next.0 - - @backstage/plugin-catalog-graphql@0.3.16-next.0 - - @backstage/config@1.0.5-next.0 - -## 0.1.28 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.16.0 - - @backstage/config@1.0.4 - - @backstage/plugin-catalog-graphql@0.3.15 - -## 0.1.28-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.16.0-next.1 - - @backstage/config@1.0.4-next.0 - - @backstage/plugin-catalog-graphql@0.3.15-next.0 - -## 0.1.28-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.16.0-next.0 - - @backstage/config@1.0.4-next.0 - - @backstage/plugin-catalog-graphql@0.3.15-next.0 - -## 0.1.27 - -### Patch Changes - -- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` -- Updated dependencies - - @backstage/backend-common@0.15.2 - - @backstage/plugin-catalog-graphql@0.3.14 - - @backstage/config@1.0.3 - -## 0.1.27-next.2 - -### Patch Changes - -- 2d3a5f09ab: Use `response.json` rather than `response.send` where appropriate, as outlined in `SECURITY.md` -- Updated dependencies - - @backstage/backend-common@0.15.2-next.2 - - @backstage/config@1.0.3-next.2 - - @backstage/plugin-catalog-graphql@0.3.14-next.2 - -## 0.1.27-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.15.2-next.1 - - @backstage/config@1.0.3-next.1 - - @backstage/plugin-catalog-graphql@0.3.14-next.1 - -## 0.1.27-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/plugin-catalog-graphql@0.3.14-next.0 - - @backstage/backend-common@0.15.2-next.0 - - @backstage/config@1.0.3-next.0 - -## 0.1.26 - -### Patch Changes - -- d669d89206: Minor API signatures cleanup -- 60b85d8ade: Updated dependency `helmet` to `^6.0.0`. - - Please note that these policies are no longer applied by default: - - helmet.contentSecurityPolicy no longer sets block-all-mixed-content directive by default - helmet.expectCt is no longer set by default. It can, however, be explicitly enabled. It will be removed in Helmet 7. - -- 667d917488: Updated dependency `msw` to `^0.47.0`. -- 87ec2ba4d6: Updated dependency `msw` to `^0.46.0`. -- bf5e9030eb: Updated dependency `msw` to `^0.45.0`. -- Updated dependencies - - @backstage/backend-common@0.15.1 - - @backstage/config@1.0.2 - - @backstage/plugin-catalog-graphql@0.3.13 - -## 0.1.26-next.3 - -### Patch Changes - -- Updated dependencies - - @backstage/config@1.0.2-next.0 - - @backstage/backend-common@0.15.1-next.3 - - @backstage/plugin-catalog-graphql@0.3.13-next.3 - -## 0.1.26-next.2 - -### Patch Changes - -- 667d917488: Updated dependency `msw` to `^0.47.0`. -- 87ec2ba4d6: Updated dependency `msw` to `^0.46.0`. -- Updated dependencies - - @backstage/backend-common@0.15.1-next.2 - - @backstage/plugin-catalog-graphql@0.3.13-next.2 - -## 0.1.26-next.1 - -### Patch Changes - -- d669d89206: Minor API signatures cleanup -- 60b85d8ade: Updated dependency `helmet` to `^6.0.0`. - - Please note that these policies are no longer applied by default: - - helmet.contentSecurityPolicy no longer sets block-all-mixed-content directive by default - helmet.expectCt is no longer set by default. It can, however, be explicitly enabled. It will be removed in Helmet 7. - -- Updated dependencies - - @backstage/backend-common@0.15.1-next.1 - - @backstage/plugin-catalog-graphql@0.3.13-next.1 - -## 0.1.26-next.0 - -### Patch Changes - -- bf5e9030eb: Updated dependency `msw` to `^0.45.0`. -- Updated dependencies - - @backstage/backend-common@0.15.1-next.0 - - @backstage/plugin-catalog-graphql@0.3.13-next.0 - -## 0.1.25 - -### Patch Changes - -- fa3eeee92d: Updated dependency `@graphql-tools/schema` to `^9.0.0`. -- Updated dependencies - - @backstage/backend-common@0.15.0 - - @backstage/plugin-catalog-graphql@0.3.12 - -## 0.1.25-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.15.0-next.0 - -## 0.1.24 - -### Patch Changes - -- a70869e775: Updated dependency `msw` to `^0.43.0`. -- 8006d0f9bf: Updated dependency `msw` to `^0.44.0`. -- Updated dependencies - - @backstage/backend-common@0.14.1 - - @backstage/plugin-catalog-graphql@0.3.11 - -## 0.1.24-next.1 - -### Patch Changes - -- a70869e775: Updated dependency `msw` to `^0.43.0`. -- Updated dependencies - - @backstage/backend-common@0.14.1-next.3 - - @backstage/plugin-catalog-graphql@0.3.11-next.1 - -## 0.1.24-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.14.1-next.0 - - @backstage/plugin-catalog-graphql@0.3.11-next.0 - -## 0.1.23 - -### Patch Changes - -- 8f7b1835df: Updated dependency `msw` to `^0.41.0`. -- Updated dependencies - - @backstage/backend-common@0.14.0 - - @backstage/plugin-catalog-graphql@0.3.10 - -## 0.1.23-next.2 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.14.0-next.2 - -## 0.1.23-next.1 - -### Patch Changes - -- 8f7b1835df: Updated dependency `msw` to `^0.41.0`. -- Updated dependencies - - @backstage/backend-common@0.13.6-next.1 - - @backstage/plugin-catalog-graphql@0.3.10-next.0 - -## 0.1.23-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.13.6-next.0 - -## 0.1.22 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.13.3 - - @backstage/config@1.0.1 - - @backstage/plugin-catalog-graphql@0.3.9 - -## 0.1.22-next.1 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.13.3-next.2 - - @backstage/config@1.0.1-next.0 - - @backstage/plugin-catalog-graphql@0.3.9-next.0 - -## 0.1.22-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.13.3-next.0 - -## 0.1.21 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.13.2 - - @backstage/plugin-catalog-graphql@0.3.8 - -## 0.1.21-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.13.2-next.0 - - @backstage/plugin-catalog-graphql@0.3.8-next.0 - -## 0.1.20 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.13.1 - - @backstage/plugin-catalog-graphql@0.3.7 - - @backstage/config@1.0.0 - -## 0.1.19 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.13.0 - - @backstage/plugin-catalog-graphql@0.3.6 - -## 0.1.19-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.13.0-next.0 - - @backstage/plugin-catalog-graphql@0.3.6-next.0 - -## 0.1.18 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.12.0 - - @backstage/plugin-catalog-graphql@0.3.5 - -## 0.1.17 - -### Patch Changes - -- 68913af4ff: chore(deps): bump `graphql-modules` from 1.4.4 to 2.0.0 -- Updated dependencies - - @backstage/backend-common@0.11.0 - - @backstage/plugin-catalog-graphql@0.3.4 - -## 0.1.16 - -### Patch Changes - -- Fix for the previous release with missing type declarations. -- Updated dependencies - - @backstage/backend-common@0.10.9 - - @backstage/config@0.1.15 - - @backstage/plugin-catalog-graphql@0.3.3 - -## 0.1.15 - -### Patch Changes - -- c77c5c7eb6: Added `backstage.role` to `package.json` -- 0107c9aa08: chore(deps): bump `helmet` from 4.4.1 to 5.0.2 -- Updated dependencies - - @backstage/backend-common@0.10.8 - - @backstage/plugin-catalog-graphql@0.3.2 - - @backstage/config@0.1.14 - -## 0.1.14 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.10.7 - -## 0.1.14-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.10.7-next.0 - -## 0.1.13 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.10.6 - -## 0.1.13-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.10.6-next.0 - -## 0.1.12 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.10.4 - - @backstage/config@0.1.13 - - @backstage/plugin-catalog-graphql@0.3.1 - -## 0.1.12-next.0 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.10.4-next.0 - - @backstage/config@0.1.13-next.0 - - @backstage/plugin-catalog-graphql@0.3.1-next.0 - -## 0.1.11 - -### Patch Changes - -- 0fb17da164: chore: bumping dependencies in the GraphQL modules and bringing them up to date with the latest `graphql-modules` library -- Updated dependencies - - @backstage/config@0.1.12 - - @backstage/backend-common@0.10.3 - - @backstage/plugin-catalog-graphql@0.3.0 - -## 0.1.10 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.10.0 - -## 0.1.9 - -### Patch Changes - -- Updated dependencies - - @backstage/backend-common@0.9.0 - - @backstage/config@0.1.8 - - @backstage/plugin-catalog-graphql@0.2.12 - -## 0.1.8 - -### Patch Changes - -- Updated dependencies [3be844496] -- Updated dependencies [22fd8ce2a] -- Updated dependencies [f9fb4a205] - - @backstage/plugin-catalog-graphql@0.2.9 - - @backstage/backend-common@0.8.0 - -## 0.1.7 - -### Patch Changes - -- Updated dependencies [e0bfd3d44] -- Updated dependencies [38ca05168] -- Updated dependencies [d8b81fd28] - - @backstage/backend-common@0.7.0 - - @backstage/config@0.1.5 - - @backstage/plugin-catalog-graphql@0.2.8 - -## 0.1.6 - -### Patch Changes - -- Updated dependencies [8686eb38c] -- Updated dependencies [0434853a5] -- Updated dependencies [8686eb38c] - - @backstage/backend-common@0.6.0 - - @backstage/config@0.1.4 - - @backstage/plugin-catalog-graphql@0.2.7 - -## 0.1.5 - -### Patch Changes - -- Updated dependencies [0b135e7e0] -- Updated dependencies [294a70cab] -- Updated dependencies [0ea032763] -- Updated dependencies [5345a1f98] -- Updated dependencies [09a370426] - - @backstage/backend-common@0.5.0 - - @backstage/plugin-catalog-graphql@0.2.6 - -## 0.1.4 - -### Patch Changes - -- Updated dependencies [38e24db00] -- Updated dependencies [e3bd9fc2f] -- Updated dependencies [12bbd748c] -- Updated dependencies [e3bd9fc2f] - - @backstage/backend-common@0.4.0 - - @backstage/config@0.1.2 - - @backstage/plugin-catalog-graphql@0.2.4 - -## 0.1.3 - -### Patch Changes - -- Updated dependencies [1722cb53c] -- Updated dependencies [1722cb53c] -- Updated dependencies [7b37e6834] -- Updated dependencies [8e2effb53] - - @backstage/backend-common@0.3.0 - - @backstage/plugin-catalog-graphql@0.2.1 - -## 0.1.2 - -### Patch Changes - -- Updated dependencies [28edd7d29] -- Updated dependencies [5249594c5] -- Updated dependencies [56e4eb589] -- Updated dependencies [e37c0a005] -- Updated dependencies [f00ca3cb8] -- Updated dependencies [6579769df] -- Updated dependencies [8c2b76e45] -- Updated dependencies [440a17b39] -- Updated dependencies [8afce088a] -- Updated dependencies [7bbeb049f] - - @backstage/plugin-catalog-graphql@0.2.0 - - @backstage/backend-common@0.2.0 diff --git a/plugins/graphql-backend/README.md b/plugins/graphql-backend/README.md deleted file mode 100644 index 7e9f6c772e..0000000000 --- a/plugins/graphql-backend/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# GraphQL Backend - -This package has been deprecated, consider using [@frontside/backstage-plugin-graphql-backend](https://www.npmjs.com/package/@frontside/backstage-plugin-graphql-backend) instead. diff --git a/plugins/graphql-backend/api-report.md b/plugins/graphql-backend/api-report.md deleted file mode 100644 index a787c4f209..0000000000 --- a/plugins/graphql-backend/api-report.md +++ /dev/null @@ -1,20 +0,0 @@ -## API Report File for "@backstage/plugin-graphql-backend" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { Config } from '@backstage/config'; -import express from 'express'; -import { Logger } from 'winston'; - -// @public (undocumented) -export function createRouter(options: RouterOptions): Promise; - -// @public (undocumented) -export interface RouterOptions { - // (undocumented) - config: Config; - // (undocumented) - logger: Logger; -} -``` diff --git a/plugins/graphql-backend/catalog-info.yaml b/plugins/graphql-backend/catalog-info.yaml deleted file mode 100644 index 4545c0def5..0000000000 --- a/plugins/graphql-backend/catalog-info.yaml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: backstage.io/v1alpha1 -kind: Component -metadata: - name: backstage-plugin-graphql-backend - title: '@backstage/plugin-graphql-backend' - description: An experimental Backstage backend plugin for GraphQL -spec: - lifecycle: experimental - type: backstage-backend-plugin - owner: maintainers diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json deleted file mode 100644 index 1660e7154b..0000000000 --- a/plugins/graphql-backend/package.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "name": "@backstage/plugin-graphql-backend", - "description": "Deprecated, consider using @frontside/backstage-plugin-graphql-backend instead", - "version": "0.2.1", - "main": "src/index.ts", - "types": "src/index.ts", - "license": "Apache-2.0", - "publishConfig": { - "access": "public", - "main": "dist/index.cjs.js", - "types": "dist/index.d.ts" - }, - "backstage": { - "role": "backend-plugin" - }, - "homepage": "https://backstage.io", - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "plugins/graphql-backend" - }, - "keywords": [ - "backstage", - "graphql" - ], - "scripts": { - "start": "backstage-cli package start", - "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", - "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack", - "clean": "backstage-cli package clean" - }, - "dependencies": { - "@apollo/server": "^4.0.0", - "@backstage/backend-common": "workspace:^", - "@backstage/config": "workspace:^", - "@backstage/plugin-catalog-graphql": "workspace:^", - "@graphql-tools/schema": "^9.0.0", - "@types/express": "^4.17.6", - "express": "^4.17.1", - "express-promise-router": "^4.1.0", - "graphql": "^16.0.0", - "graphql-modules": "^2.0.0", - "helmet": "^6.0.0", - "reflect-metadata": "^0.1.13", - "winston": "^3.2.1", - "yn": "^4.0.0" - }, - "devDependencies": { - "@backstage/cli": "workspace:^", - "@types/supertest": "^2.0.8", - "msw": "^1.0.0", - "supertest": "^6.1.3" - }, - "files": [ - "dist", - "schema.gql" - ] -} diff --git a/plugins/graphql-backend/schema.gql b/plugins/graphql-backend/schema.gql deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/plugins/graphql-backend/src/service/router.test.ts b/plugins/graphql-backend/src/service/router.test.ts deleted file mode 100644 index 37dc25ebc6..0000000000 --- a/plugins/graphql-backend/src/service/router.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { createRouter } from './router'; -import supertest from 'supertest'; -import { ConfigReader } from '@backstage/config'; -import { createLogger } from 'winston'; -import express from 'express'; - -describe('Router', () => { - describe('/health', () => { - it('should return ok', async () => { - const config = new ConfigReader({ backend: { baseUrl: 'lol' } }); - - const router = await createRouter({ config, logger: createLogger() }); - const app = express().use(router); - - const { body } = await supertest(app).get('/health'); - - expect(body).toEqual({ status: 'ok' }); - }); - }); -}); diff --git a/plugins/graphql-backend/src/service/router.ts b/plugins/graphql-backend/src/service/router.ts deleted file mode 100644 index fbddee435f..0000000000 --- a/plugins/graphql-backend/src/service/router.ts +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { errorHandler } from '@backstage/backend-common'; -import express from 'express'; -import Router from 'express-promise-router'; -import { Logger } from 'winston'; -import { createApplication } from 'graphql-modules'; -import { ApolloServer } from '@apollo/server'; -import { expressMiddleware } from '@apollo/server/express4'; -import { createModule as createCatalogModule } from '@backstage/plugin-catalog-graphql'; -import { Config } from '@backstage/config'; -import helmet from 'helmet'; -import { makeExecutableSchema } from '@graphql-tools/schema'; - -/** @public */ -export interface RouterOptions { - logger: Logger; - config: Config; -} - -/** @public */ -export async function createRouter( - options: RouterOptions, -): Promise { - const catalogModule = await createCatalogModule(options); - - const { createSchemaForApollo } = createApplication({ - modules: [catalogModule], - schemaBuilder(input) { - return makeExecutableSchema({ - ...input, - inheritResolversFromInterfaces: true, - }); - }, - }); - - const server = new ApolloServer({ - schema: createSchemaForApollo(), - logger: options.logger, - introspection: true, - }); - - await server.start(); - - const router = Router(); - - router.get('/health', (_, response) => { - response.json({ status: 'ok' }); - }); - - if (process.env.NODE_ENV === 'development') - router.use( - helmet.contentSecurityPolicy({ - directives: { - defaultSrc: ["'self'", "'unsafe-inline'", 'http://*'], - }, - }), - ); - - router.use(expressMiddleware(server)); - router.use(errorHandler()); - - return router; -} diff --git a/plugins/graphql-voyager/CHANGELOG.md b/plugins/graphql-voyager/CHANGELOG.md index 4cd233102c..9979c83b57 100644 --- a/plugins/graphql-voyager/CHANGELOG.md +++ b/plugins/graphql-voyager/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-graphql-voyager +## 0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## 0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + ## 0.1.9 ### Patch Changes diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index b50e8b6dd5..02239ad24e 100644 --- a/plugins/graphql-voyager/package.json +++ b/plugins/graphql-voyager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-voyager", "description": "Backstage plugin for GraphQL Voyager", - "version": "0.1.9", + "version": "0.1.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx index d2f9262983..772c70b0fa 100644 --- a/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx +++ b/plugins/graphql-voyager/src/components/GraphQLVoyagerBrowser/GraphQLVoyagerBrowser.tsx @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { GraphQLVoyagerEndpoint, introspectionQuery, @@ -20,18 +21,17 @@ import { import { useState } from 'react'; import { makeStyles, Tab, Tabs, Typography } from '@material-ui/core'; import React, { Suspense } from 'react'; -import { BackstageTheme } from '@backstage/theme'; import { Content, ErrorPanel, Progress } from '@backstage/core-components'; import { Voyager } from 'graphql-voyager'; import useAsync from 'react-use/lib/useAsync'; -const useStyles = makeStyles(() => ({ +const useStyles = makeStyles({ root: { height: '100%', display: 'flex', flexFlow: 'column nowrap', }, -})); +}); type GraphQLVoyagerBrowserProps = { endpoints: GraphQLVoyagerEndpoint[]; diff --git a/plugins/home-react/CHANGELOG.md b/plugins/home-react/CHANGELOG.md index 2a95a64f47..ca7a0a66f7 100644 --- a/plugins/home-react/CHANGELOG.md +++ b/plugins/home-react/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-home-react +## 0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.1.6-next.1 + +### Patch Changes + +- 2b725913c1: Updated dependency `@rjsf/utils` to `5.14.3`. + Updated dependency `@rjsf/core` to `5.14.3`. + Updated dependency `@rjsf/material-ui` to `5.14.3`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.3`. +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.1.6-next.0 + +### Patch Changes + +- 6cd12f277b: Updated dependency `@rjsf/utils` to `5.14.1`. + Updated dependency `@rjsf/core` to `5.14.1`. + Updated dependency `@rjsf/material-ui` to `5.14.1`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.1`. +- 63c494ef22: Updated dependency `@rjsf/utils` to `5.14.2`. + Updated dependency `@rjsf/core` to `5.14.2`. + Updated dependency `@rjsf/material-ui` to `5.14.2`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.2`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + ## 0.1.5 ### Patch Changes diff --git a/plugins/home-react/package.json b/plugins/home-react/package.json index 6289959ee8..f2b1b94e48 100644 --- a/plugins/home-react/package.json +++ b/plugins/home-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-home-react", "description": "A Backstage plugin that contains react components helps you build a home page", - "version": "0.1.5", + "version": "0.1.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,7 +38,7 @@ "@backstage/core-plugin-api": "workspace:^", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", - "@rjsf/utils": "5.13.6", + "@rjsf/utils": "5.14.3", "@types/react": "^16.13.1 || ^17.0.0" }, "peerDependencies": { diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index a6c8636dbf..c842969c35 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,76 @@ # @backstage/plugin-home +## 0.6.0-next.2 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 8f5d6c1: Updates to the `/alpha` exports to match the extension input wrapping change. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-home-react@0.1.6-next.2 + +## 0.6.0-next.1 + +### Minor Changes + +- 5a317f59c0: Added view of entities grouped by kind to make it easier to distinguish entities with different kind but same name + +### Patch Changes + +- 2b725913c1: Updated dependency `@rjsf/utils` to `5.14.3`. + Updated dependency `@rjsf/core` to `5.14.3`. + Updated dependency `@rjsf/material-ui` to `5.14.3`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.3`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/plugin-home-react@0.1.6-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + +## 0.5.12-next.0 + +### Patch Changes + +- 6cd12f277b: Updated dependency `@rjsf/utils` to `5.14.1`. + Updated dependency `@rjsf/core` to `5.14.1`. + Updated dependency `@rjsf/material-ui` to `5.14.1`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.1`. +- 63c494ef22: Updated dependency `@rjsf/utils` to `5.14.2`. + Updated dependency `@rjsf/core` to `5.14.2`. + Updated dependency `@rjsf/material-ui` to `5.14.2`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.2`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-home-react@0.1.6-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.5.10 ### Patch Changes diff --git a/plugins/home/alpha-api-report.md b/plugins/home/api-report-alpha.md similarity index 100% rename from plugins/home/alpha-api-report.md rename to plugins/home/api-report-alpha.md diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index 18049cae84..dd6e22c57d 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -148,7 +148,7 @@ export const HomePageRecentlyVisited: ( // @public export const HomePageStarredEntities: ( - props: CardExtensionProps_2, + props: CardExtensionProps_2>, ) => JSX_2.Element; // @public @@ -192,6 +192,12 @@ export const SettingsModal: (props: { children: JSX.Element; }) => JSX_2.Element; +// @public +export type StarredEntitiesProps = { + noStarredEntitiesMessage?: React_2.ReactNode | undefined; + groupByKind?: boolean; +}; + // @public (undocumented) export const TemplateBackstageLogo: (props: { classes: { diff --git a/plugins/home/package.json b/plugins/home/package.json index 71d5cf28c6..489105866c 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-home", "description": "A Backstage plugin that helps you build a home page", - "version": "0.5.10", + "version": "0.6.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -51,6 +51,7 @@ "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/core-app-api": "workspace:^", + "@backstage/core-compat-api": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/frontend-plugin-api": "workspace:^", @@ -61,10 +62,10 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", - "@rjsf/core": "5.13.6", - "@rjsf/material-ui": "5.13.6", - "@rjsf/utils": "5.13.6", - "@rjsf/validator-ajv8": "5.13.6", + "@rjsf/core": "5.14.3", + "@rjsf/material-ui": "5.14.3", + "@rjsf/utils": "5.14.3", + "@rjsf/validator-ajv8": "5.14.3", "@types/react": "^16.13.1 || ^17.0.0", "lodash": "^4.17.21", "luxon": "^3.4.3", diff --git a/plugins/home/src/alpha.tsx b/plugins/home/src/alpha.tsx index c8308f7c0a..631f4293be 100644 --- a/plugins/home/src/alpha.tsx +++ b/plugins/home/src/alpha.tsx @@ -24,6 +24,7 @@ import { createPlugin, createRouteRef, } from '@backstage/frontend-plugin-api'; +import { compatWrapper } from '@backstage/core-compat-api'; const rootRouteRef = createRouteRef(); @@ -33,7 +34,6 @@ const rootRouteRef = createRouteRef(); export const titleExtensionDataRef = createExtensionDataRef('title'); const HomepageCompositionRootExtension = createPageExtension({ - id: 'home', defaultPath: '/home', routeRef: rootRouteRef, inputs: { @@ -50,12 +50,14 @@ const HomepageCompositionRootExtension = createPageExtension({ ), }, loader: ({ inputs }) => - import('./components/').then(m => ( - - )), + import('./components/').then(m => + compatWrapper( + , + ), + ), }); /** diff --git a/plugins/home/src/components/StarredEntityListItem/StarredEntityListItem.tsx b/plugins/home/src/components/StarredEntityListItem/StarredEntityListItem.tsx new file mode 100644 index 0000000000..2a8960e469 --- /dev/null +++ b/plugins/home/src/components/StarredEntityListItem/StarredEntityListItem.tsx @@ -0,0 +1,60 @@ +/* + * 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. + */ +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; +import { entityRouteParams } from '@backstage/plugin-catalog-react'; +import { + ListItem, + ListItemIcon, + Tooltip, + IconButton, + ListItemText, +} from '@material-ui/core'; +import React from 'react'; +import { Link } from 'react-router-dom'; +import { entityRouteRef } from '@backstage/plugin-catalog-react'; +import { useRouteRef } from '@backstage/core-plugin-api'; +import StarIcon from '@material-ui/icons/Star'; + +type EntityListItemProps = { + entity: Entity; + onToggleStarredEntity: (entity: Entity) => void; +}; + +export const StarredEntityListItem = ({ + entity, + onToggleStarredEntity, +}: EntityListItemProps) => { + const catalogEntityRoute = useRouteRef(entityRouteRef); + + return ( + + + + onToggleStarredEntity(entity)} + > + + + + + + + + + ); +}; diff --git a/plugins/home/src/components/StarredEntityListItem/index.ts b/plugins/home/src/components/StarredEntityListItem/index.ts new file mode 100644 index 0000000000..5419e0cdf7 --- /dev/null +++ b/plugins/home/src/components/StarredEntityListItem/index.ts @@ -0,0 +1,17 @@ +/* + * 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 { StarredEntityListItem } from './StarredEntityListItem'; diff --git a/plugins/home/src/homePageComponents/FeaturedDocsCard/Content.tsx b/plugins/home/src/homePageComponents/FeaturedDocsCard/Content.tsx index dfa83ce074..eb8d78b0cc 100644 --- a/plugins/home/src/homePageComponents/FeaturedDocsCard/Content.tsx +++ b/plugins/home/src/homePageComponents/FeaturedDocsCard/Content.tsx @@ -27,7 +27,7 @@ import { catalogApiRef, CatalogApi } from '@backstage/plugin-catalog-react'; import { useApi } from '@backstage/core-plugin-api'; import { EntityFilterQuery } from '@backstage/catalog-client'; -import { makeStyles, Theme, Typography } from '@material-ui/core'; +import { makeStyles, Typography } from '@material-ui/core'; /** * Props customizing the component. @@ -47,7 +47,7 @@ export type FeaturedDocsCardProps = { subLinkText?: string; }; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ docDescription: { fontSize: theme.typography.body1.fontSize, diff --git a/plugins/home/src/homePageComponents/StarredEntities/Content.tsx b/plugins/home/src/homePageComponents/StarredEntities/Content.tsx index 4654a7f860..ed5eec857b 100644 --- a/plugins/home/src/homePageComponents/StarredEntities/Content.tsx +++ b/plugins/home/src/homePageComponents/StarredEntities/Content.tsx @@ -17,24 +17,18 @@ import { catalogApiRef, useStarredEntities, - entityRouteParams, - entityRouteRef, } from '@backstage/plugin-catalog-react'; -import { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model'; -import { useApi, useRouteRef } from '@backstage/core-plugin-api'; -import { Link, Progress, ResponseErrorPanel } from '@backstage/core-components'; import { - List, - ListItem, - ListItemSecondaryAction, - IconButton, - ListItemText, - Tooltip, - Typography, -} from '@material-ui/core'; -import StarIcon from '@material-ui/icons/Star'; + Entity, + parseEntityRef, + stringifyEntityRef, +} from '@backstage/catalog-model'; +import { useApi } from '@backstage/core-plugin-api'; +import { Progress, ResponseErrorPanel } from '@backstage/core-components'; +import { List, Typography, Tabs, Tab } from '@material-ui/core'; import React from 'react'; import useAsync from 'react-use/lib/useAsync'; +import { StarredEntityListItem } from '../../components/StarredEntityListItem/StarredEntityListItem'; /** * A component to display a list of starred entities for the user. @@ -42,12 +36,18 @@ import useAsync from 'react-use/lib/useAsync'; * @public */ -export const Content = (props: { +export type StarredEntitiesProps = { noStarredEntitiesMessage?: React.ReactNode | undefined; -}) => { + groupByKind?: boolean; +}; + +export const Content = ({ + noStarredEntitiesMessage, + groupByKind, +}: StarredEntitiesProps) => { const catalogApi = useApi(catalogApiRef); - const catalogEntityRoute = useRouteRef(entityRouteRef); const { starredEntities, toggleStarredEntity } = useStarredEntities(); + const [activeTab, setActiveTab] = React.useState(0); // Grab starred entities from catalog to ensure they still exist and also retrieve display titles const entities = useAsync(async () => { @@ -79,7 +79,7 @@ export const Content = (props: { if (starredEntities.size === 0) return ( - {props.noStarredEntitiesMessage || + {noStarredEntitiesMessage || 'Click the star beside an entity name to add it to this list!'} ); @@ -88,36 +88,73 @@ export const Content = (props: { return ; } + const groupedEntities: { [kind: string]: Entity[] } = {}; + entities.value?.forEach(entity => { + const kind = entity.kind; + if (!groupedEntities[kind]) { + groupedEntities[kind] = []; + } + groupedEntities[kind].push(entity); + }); + + const groupByKindEntries = Object.entries(groupedEntities); + return entities.error ? ( ) : ( - - {entities.value - ?.sort((a, b) => - (a.metadata.title ?? a.metadata.name).localeCompare( - b.metadata.title ?? b.metadata.name, - ), - ) - .map(entity => ( - - - + {!groupByKind && ( + + {entities.value + ?.sort((a, b) => + (a.metadata.title ?? a.metadata.name).localeCompare( + b.metadata.title ?? b.metadata.name, + ), + ) + .map(entity => ( + - - - - toggleStarredEntity(entity)} - > - - - - - + ))} + + )} + + {groupByKind && ( + setActiveTab(newValue)} + variant="scrollable" + scrollButtons="auto" + aria-label="entity-tabs" + > + {groupByKindEntries.map(([kind]) => ( + + ))} + + )} + + {groupByKind && + groupByKindEntries.map(([kind, entitiesByKind], index) => ( + ))} - + ); }; diff --git a/plugins/home/src/homePageComponents/StarredEntities/index.ts b/plugins/home/src/homePageComponents/StarredEntities/index.ts index 1faa9a2426..32e9213ea6 100644 --- a/plugins/home/src/homePageComponents/StarredEntities/index.ts +++ b/plugins/home/src/homePageComponents/StarredEntities/index.ts @@ -13,5 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - export { Content } from './Content'; +export type { StarredEntitiesProps } from './Content'; diff --git a/plugins/home/src/homePageComponents/index.ts b/plugins/home/src/homePageComponents/index.ts index dc611291fb..e260982e8e 100644 --- a/plugins/home/src/homePageComponents/index.ts +++ b/plugins/home/src/homePageComponents/index.ts @@ -19,3 +19,4 @@ export type { ClockConfig } from './HeaderWorldClock'; export type { WelcomeTitleLanguageProps } from './WelcomeTitle'; export type { VisitedByTypeProps, VisitedByTypeKind } from './VisitedByType'; export type { FeaturedDocsCardProps } from './FeaturedDocsCard'; +export type { StarredEntitiesProps } from './StarredEntities'; diff --git a/plugins/home/src/plugin.ts b/plugins/home/src/plugin.ts index 5361ecd9c0..cb9f129a72 100644 --- a/plugins/home/src/plugin.ts +++ b/plugins/home/src/plugin.ts @@ -30,6 +30,7 @@ import { } from './homePageComponents'; import { rootRouteRef } from './routes'; import { VisitsStorageApi, visitsApiRef } from './api'; +import { StarredEntitiesProps } from './homePageComponents/StarredEntities/Content'; /** @public */ export const homePlugin = createPlugin({ @@ -168,7 +169,7 @@ export const HomePageToolkit = homePlugin.provide( * @public */ export const HomePageStarredEntities = homePlugin.provide( - createCardExtension({ + createCardExtension>({ name: 'HomePageStarredEntities', title: 'Your Starred Entities', components: () => import('./homePageComponents/StarredEntities'), diff --git a/plugins/ilert/CHANGELOG.md b/plugins/ilert/CHANGELOG.md index 546b906426..7204e88a35 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-ilert +## 0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.2.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.2.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.2.15 ### Patch Changes diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 957d72cfb5..baab866298 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-ilert", "description": "A Backstage plugin that integrates towards iLert", - "version": "0.2.15", + "version": "0.2.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/ilert/src/components/ILertCard/ILertCardEmptyState.tsx b/plugins/ilert/src/components/ILertCard/ILertCardEmptyState.tsx index 966caea079..f81cfbc0a4 100644 --- a/plugins/ilert/src/components/ILertCard/ILertCardEmptyState.tsx +++ b/plugins/ilert/src/components/ILertCard/ILertCardEmptyState.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; import Card from '@material-ui/core/Card'; import CardContent from '@material-ui/core/CardContent'; import CardHeader from '@material-ui/core/CardHeader'; @@ -37,7 +36,7 @@ spec: lifecycle: production owner: guest`; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ code: { borderRadius: 6, margin: theme.spacing(2, 0), diff --git a/plugins/jenkins-backend/CHANGELOG.md b/plugins/jenkins-backend/CHANGELOG.md index 4576695e50..b71ee98880 100644 --- a/plugins/jenkins-backend/CHANGELOG.md +++ b/plugins/jenkins-backend/CHANGELOG.md @@ -1,5 +1,56 @@ # @backstage/plugin-jenkins-backend +## 0.3.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-jenkins-common@0.1.21 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## 0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-jenkins-common@0.1.21 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + +## 0.3.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-jenkins-common@0.1.21 + - @backstage/plugin-permission-common@0.7.10 + ## 0.3.1 ### Patch Changes diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index da4e95694a..0da77035c5 100644 --- a/plugins/jenkins-backend/package.json +++ b/plugins/jenkins-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins-backend", "description": "A Backstage backend plugin that integrates towards Jenkins", - "version": "0.3.1", + "version": "0.3.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index 35cd02e23e..79d1ba0252 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-jenkins +## 0.9.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-jenkins-common@0.1.21 + +## 0.9.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-jenkins-common@0.1.21 + +## 0.9.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-jenkins-common@0.1.21 + ## 0.9.1 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index e91e5b8ef0..f48e582d56 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins", "description": "A Backstage plugin that integrates towards Jenkins", - "version": "0.9.1", + "version": "0.9.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/jenkins/src/components/Cards/Cards.tsx b/plugins/jenkins/src/components/Cards/Cards.tsx index 44bbc06f65..1cbc3e5d9f 100644 --- a/plugins/jenkins/src/components/Cards/Cards.tsx +++ b/plugins/jenkins/src/components/Cards/Cards.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { LinearProgress, makeStyles, Theme } from '@material-ui/core'; +import { LinearProgress, makeStyles } from '@material-ui/core'; import ExternalLinkIcon from '@material-ui/icons/Launch'; import { DateTime, Duration } from 'luxon'; import React from 'react'; @@ -29,7 +29,7 @@ import { } from '@backstage/core-components'; import { Project } from '../../api/JenkinsApi'; -const useStyles = makeStyles({ +const useStyles = makeStyles({ externalLinkIcon: { fontSize: 'inherit', verticalAlign: 'bottom', diff --git a/plugins/kafka-backend/CHANGELOG.md b/plugins/kafka-backend/CHANGELOG.md index 6cc0673ce8..7e2b20ef10 100644 --- a/plugins/kafka-backend/CHANGELOG.md +++ b/plugins/kafka-backend/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-kafka-backend +## 0.3.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## 0.3.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## 0.3.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.3.5 ### Patch Changes diff --git a/plugins/kafka-backend/alpha-api-report.md b/plugins/kafka-backend/api-report-alpha.md similarity index 100% rename from plugins/kafka-backend/alpha-api-report.md rename to plugins/kafka-backend/api-report-alpha.md diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index 399f898792..2af508e167 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka-backend", "description": "A Backstage backend plugin that integrates towards Kafka", - "version": "0.3.5", + "version": "0.3.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kafka/CHANGELOG.md b/plugins/kafka/CHANGELOG.md index 83bc3f5b97..ec2931df26 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-kafka +## 0.3.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.3.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + +## 0.3.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + ## 0.3.26 ### Patch Changes diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index fba1f1ccb9..5b4941d12a 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka", "description": "A Backstage plugin that integrates towards Kafka", - "version": "0.3.26", + "version": "0.3.28-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index e936ec5ee1..70260944eb 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,87 @@ # @backstage/plugin-kubernetes-backend +## 0.14.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/plugin-kubernetes-node@0.1.2-next.2 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## 0.14.0-next.1 + +### Patch Changes + +- ae94d3ce6f: Updated dependency `@aws-crypto/sha256-js` to `^5.0.0`. +- 99fb54183b: Updated dependency `@azure/identity` to `^4.0.0`. +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-kubernetes-node@0.1.2-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + +## 0.14.0-next.0 + +### Minor Changes + +- 52050ada6e: You can now select `single` kubernetes cluster that the entity is part-of from all your defined kubernetes clusters, by passing `backstage.io/kubernetes-cluster` annotation with the defined cluster name. + + If you do not specify the annotation by `default it fetches all` defined kubernetes cluster. + + To apply + + catalog-info.yaml + + ```diff + annotations: + 'backstage.io/kubernetes-id': dice-roller + 'backstage.io/kubernetes-namespace': dice-space + + 'backstage.io/kubernetes-cluster': dice-cluster + 'backstage.io/kubernetes-label-selector': 'app=my-app,component=front-end' + ``` + +### Patch Changes + +- 706fc3a7e1: Updated dependency `@kubernetes/client-node` to `0.20.0`. +- 42c1aee741: Updated dependency `@google-cloud/container` to `^5.0.0`. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-kubernetes-common@0.7.2-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/types@1.1.1 + - @backstage/plugin-kubernetes-node@0.1.2-next.0 + - @backstage/plugin-permission-common@0.7.10 + ## 0.13.1 ### Patch Changes diff --git a/plugins/kubernetes-backend/alpha-api-report.md b/plugins/kubernetes-backend/api-report-alpha.md similarity index 100% rename from plugins/kubernetes-backend/alpha-api-report.md rename to plugins/kubernetes-backend/api-report-alpha.md diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index 9b8ec309da..bb20057e92 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-backend", "description": "A Backstage backend plugin that integrates towards Kubernetes", - "version": "0.13.1", + "version": "0.14.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -47,10 +47,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/sha256-js": "^5.0.0", "@aws-sdk/credential-providers": "^3.350.0", "@aws-sdk/signature-v4": "^3.347.0", - "@azure/identity": "^3.2.1", + "@azure/identity": "^4.0.0", "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", @@ -65,9 +65,9 @@ "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-permission-node": "workspace:^", "@backstage/types": "workspace:^", - "@google-cloud/container": "^4.0.0", + "@google-cloud/container": "^5.0.0", "@jest-mock/express": "^2.0.1", - "@kubernetes/client-node": "0.19.0", + "@kubernetes/client-node": "0.20.0", "@types/express": "^4.17.6", "@types/http-proxy-middleware": "^0.19.3", "@types/luxon": "^3.0.0", diff --git a/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts b/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts index b8254d781c..6d69606316 100644 --- a/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts +++ b/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts @@ -107,7 +107,7 @@ describe('resourcesRoutes', () => { import('@backstage/plugin-kubernetes-backend/alpha'), createBackendModule({ pluginId: 'kubernetes', - moduleId: 'testObjectsProvider', + moduleId: 'test-objects-provider', register(env) { env.registerInit({ deps: { extension: kubernetesObjectsProviderExtensionPoint }, diff --git a/plugins/kubernetes-cluster/CHANGELOG.md b/plugins/kubernetes-cluster/CHANGELOG.md index ac466a8920..12f22f4927 100644 --- a/plugins/kubernetes-cluster/CHANGELOG.md +++ b/plugins/kubernetes-cluster/CHANGELOG.md @@ -1,5 +1,50 @@ # @backstage/plugin-kubernetes-cluster +## 0.0.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-kubernetes-react@0.2.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + +## 0.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/plugin-kubernetes-react@0.1.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.0.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-kubernetes-react@0.1.2-next.0 + - @backstage/plugin-kubernetes-common@0.7.2-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.0.2 ### Patch Changes diff --git a/plugins/kubernetes-cluster/package.json b/plugins/kubernetes-cluster/package.json index 82ebf1b316..c3fb1e2bf8 100644 --- a/plugins/kubernetes-cluster/package.json +++ b/plugins/kubernetes-cluster/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-cluster", "description": "A Backstage plugin that shows details of Kubernetes clusters", - "version": "0.0.2", + "version": "0.0.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-common/CHANGELOG.md b/plugins/kubernetes-common/CHANGELOG.md index 69655e50fb..b46fdd9a64 100644 --- a/plugins/kubernetes-common/CHANGELOG.md +++ b/plugins/kubernetes-common/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-kubernetes-common +## 0.7.2-next.1 + +### Patch Changes + +- 5d796829bb: Remove unused dependency +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + +## 0.7.2-next.0 + +### Patch Changes + +- 706fc3a7e1: Updated dependency `@kubernetes/client-node` to `0.20.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + ## 0.7.1 ### Patch Changes diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index de265ec69b..318024535f 100644 --- a/plugins/kubernetes-common/package.json +++ b/plugins/kubernetes-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-common", "description": "Common functionalities for kubernetes, to be shared between kubernetes and kubernetes-backend plugin", - "version": "0.7.1", + "version": "0.7.2-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -40,11 +40,10 @@ }, "dependencies": { "@backstage/catalog-model": "workspace:^", - "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/types": "workspace:^", - "@kubernetes/client-node": "0.19.0", + "@kubernetes/client-node": "0.20.0", "kubernetes-models": "^4.3.1", "lodash": "^4.17.21", "luxon": "^3.0.0" diff --git a/plugins/kubernetes-node/CHANGELOG.md b/plugins/kubernetes-node/CHANGELOG.md index 7ae9d5ab51..449b0288bf 100644 --- a/plugins/kubernetes-node/CHANGELOG.md +++ b/plugins/kubernetes-node/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-kubernetes-node +## 0.1.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + +## 0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-kubernetes-common@0.7.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.1.1 ### Patch Changes diff --git a/plugins/kubernetes-node/package.json b/plugins/kubernetes-node/package.json index 608953fe5c..43f8b341f1 100644 --- a/plugins/kubernetes-node/package.json +++ b/plugins/kubernetes-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-node", "description": "Node.js library for the kubernetes plugin", - "version": "0.1.1", + "version": "0.1.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/kubernetes-react/CHANGELOG.md b/plugins/kubernetes-react/CHANGELOG.md index 1c7ca5bad6..fd7dc3a1cb 100644 --- a/plugins/kubernetes-react/CHANGELOG.md +++ b/plugins/kubernetes-react/CHANGELOG.md @@ -1,5 +1,50 @@ # @backstage/plugin-kubernetes-react +## 0.2.0-next.2 + +### Minor Changes + +- 899d71a: Change `formatClusterLink` to be an API and make it async for further customization possibilities. + + **BREAKING** + If you have a custom k8s page and used `formatClusterLink` directly, you need to migrate to new `kubernetesClusterLinkFormatterApiRef` + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + +## 0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## 0.1.2-next.0 + +### Patch Changes + +- b5ae2e5a62: Add ID property to the table displaying kubernetes pods to avoid closing the info sidebar when the data reloads and needs to rerender. +- 706fc3a7e1: Updated dependency `@kubernetes/client-node` to `0.20.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-kubernetes-common@0.7.2-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.1.1 ### Patch Changes diff --git a/plugins/kubernetes-react/api-report.md b/plugins/kubernetes-react/api-report.md index ca1df34b40..cf9f6de664 100644 --- a/plugins/kubernetes-react/api-report.md +++ b/plugins/kubernetes-react/api-report.md @@ -22,7 +22,7 @@ import { IContainerStatus } from 'kubernetes-models/v1'; import { IdentityApi } from '@backstage/core-plugin-api'; import { IIoK8sApimachineryPkgApisMetaV1ObjectMeta } from '@kubernetes-models/apimachinery/apis/meta/v1/ObjectMeta'; import { IObjectMeta } from '@kubernetes-models/apimachinery/apis/meta/v1/ObjectMeta'; -import type { JsonObject } from '@backstage/types'; +import { JsonObject } from '@backstage/types'; import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; import { OAuthApi } from '@backstage/core-plugin-api'; import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common'; @@ -38,6 +38,12 @@ import { V1ObjectMeta } from '@kubernetes/client-node'; import { V1Pod } from '@kubernetes/client-node'; import { WorkloadsByEntityRequest } from '@backstage/plugin-kubernetes-common'; +// @public (undocumented) +export class AksClusterLinksFormatter implements ClusterLinksFormatter { + // (undocumented) + formatClusterLink(options: ClusterLinksFormatterOptions): Promise; +} + // @public (undocumented) export class AksKubernetesAuthProvider implements KubernetesAuthProvider { constructor(microsoftAuthApi: OAuthApi); @@ -61,9 +67,10 @@ export const Cluster: ({ export const ClusterContext: React_2.Context; // @public (undocumented) -export type ClusterLinksFormatter = ( - options: ClusterLinksFormatterOptions, -) => URL; +export interface ClusterLinksFormatter { + // (undocumented) + formatClusterLink(options: ClusterLinksFormatterOptions): Promise; +} // @public (undocumented) export interface ClusterLinksFormatterOptions { @@ -77,9 +84,6 @@ export interface ClusterLinksFormatterOptions { object: any; } -// @public (undocumented) -export const clusterLinksFormatters: Record; - // @public export type ClusterProps = { clusterObjects: ClusterObjects; @@ -125,9 +129,18 @@ export interface CustomResourcesProps { children?: React_2.ReactNode; } +// @public (undocumented) +export const DEFAULT_FORMATTER_NAME = 'standard'; + // @public export const DetectedErrorsContext: React_2.Context; +// @public (undocumented) +export class EksClusterLinksFormatter implements ClusterLinksFormatter { + // (undocumented) + formatClusterLink(_options: ClusterLinksFormatterOptions): Promise; +} + // @public export const ErrorList: ({ podAndErrors, @@ -228,11 +241,6 @@ export interface FixDialogProps { pod: Pod_2; } -// @public (undocumented) -export function formatClusterLink( - options: FormatClusterLinkOptions, -): string | undefined; - // @public (undocumented) export type FormatClusterLinkOptions = { dashboardUrl?: string; @@ -242,6 +250,18 @@ export type FormatClusterLinkOptions = { kind: string; }; +// @public (undocumented) +export function getDefaultFormatters(_deps: {}): Record< + string, + ClusterLinksFormatter +>; + +// @public (undocumented) +export class GkeClusterLinksFormatter implements ClusterLinksFormatter { + // (undocumented) + formatClusterLink(options: ClusterLinksFormatterOptions): Promise; +} + // @public (undocumented) export class GoogleKubernetesAuthProvider implements KubernetesAuthProvider { constructor(authProvider: OAuthApi); @@ -415,6 +435,31 @@ export class KubernetesBackendClient implements KubernetesApi { }): Promise; } +// @public (undocumented) +export class KubernetesClusterLinkFormatter + implements KubernetesClusterLinkFormatterApi +{ + constructor(options: { + formatters: Record; + defaultFormatterName: string; + }); + // (undocumented) + formatClusterLink( + options: FormatClusterLinkOptions, + ): Promise; +} + +// @public (undocumented) +export interface KubernetesClusterLinkFormatterApi { + // (undocumented) + formatClusterLink( + options: FormatClusterLinkOptions, + ): Promise; +} + +// @public (undocumented) +export const kubernetesClusterLinkFormatterApiRef: ApiRef; + // @public export const KubernetesDrawer: ({ open, @@ -587,6 +632,12 @@ export class OidcKubernetesAuthProvider implements KubernetesAuthProvider { providerName: string; } +// @public (undocumented) +export class OpenshiftClusterLinksFormatter { + // (undocumented) + formatClusterLink(options: ClusterLinksFormatterOptions): Promise; +} + // @public export const PendingPodContent: ({ pod, @@ -716,6 +767,12 @@ export type PodsTablesProps = { children?: React_2.ReactNode; }; +// @public (undocumented) +export class RancherClusterLinksFormatter implements ClusterLinksFormatter { + // (undocumented) + formatClusterLink(options: ClusterLinksFormatterOptions): Promise; +} + // @public (undocumented) export const READY_COLUMNS: PodColumns; @@ -763,6 +820,12 @@ export const ServicesAccordions: ({}: ServicesAccordionsProps) => React_2.JSX.El // @public (undocumented) export type ServicesAccordionsProps = {}; +// @public (undocumented) +export class StandardClusterLinksFormatter implements ClusterLinksFormatter { + // (undocumented) + formatClusterLink(options: ClusterLinksFormatterOptions): Promise; +} + // @public export const useCustomResources: ( entity: Entity, diff --git a/plugins/kubernetes-react/package.json b/plugins/kubernetes-react/package.json index 20d88e222d..27be86c436 100644 --- a/plugins/kubernetes-react/package.json +++ b/plugins/kubernetes-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-react", "description": "Web library for the kubernetes-react plugin", - "version": "0.1.1", + "version": "0.2.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,7 +32,7 @@ "@backstage/types": "workspace:^", "@kubernetes-models/apimachinery": "^1.1.0", "@kubernetes-models/base": "^4.0.1", - "@kubernetes/client-node": "^0.19.0", + "@kubernetes/client-node": "^0.20.0", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.11.3", "@material-ui/lab": "^4.0.0-alpha.61", diff --git a/plugins/kubernetes-react/src/api/KubernetesClusterLinkFormatter.test.ts b/plugins/kubernetes-react/src/api/KubernetesClusterLinkFormatter.test.ts new file mode 100644 index 0000000000..05b1709c75 --- /dev/null +++ b/plugins/kubernetes-react/src/api/KubernetesClusterLinkFormatter.test.ts @@ -0,0 +1,76 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { KubernetesClusterLinkFormatter } from './KubernetesClusterLinkFormatter'; + +const dashboardUrl = new URL('http://dashboard/url'); +describe('KubernetesClusterLinkFormatter', () => { + const formatter = new KubernetesClusterLinkFormatter({ + formatters: { + standard: { formatClusterLink: async _ => dashboardUrl }, + }, + defaultFormatterName: 'standard', + }); + describe('formatter.formatClusterLink', () => { + it('should not return an url when there is no dashboard url', async () => { + const url = await formatter.formatClusterLink({ + object: {}, + kind: 'foo', + }); + expect(url).toBeUndefined(); + }); + it('should return an url even when there is no object', async () => { + const url = await formatter.formatClusterLink({ + dashboardUrl: 'https://k8s.foo.com', + object: undefined, + kind: 'foo', + }); + expect(url).toBe('https://k8s.foo.com'); + }); + it('should throw when the app is not recognized', async () => { + await expect( + formatter.formatClusterLink({ + dashboardUrl: 'https://k8s.foo.com', + dashboardApp: 'unknownapp', + object: { + metadata: { + name: 'foobar', + namespace: 'bar', + }, + }, + kind: 'Deployment', + }), + ).rejects.toThrow( + "Could not find Kubernetes dashboard app named 'unknownapp'", + ); + }); + + describe('default app', () => { + it('should use default app', async () => { + const url = await formatter.formatClusterLink({ + dashboardUrl: 'https://k8s.foo.com/', + object: { + metadata: { + name: 'foobar', + namespace: 'bar', + }, + }, + kind: 'Deployment', + }); + expect(url).toBe(dashboardUrl.toString()); + }); + }); + }); +}); diff --git a/plugins/kubernetes-react/src/api/KubernetesClusterLinkFormatter.ts b/plugins/kubernetes-react/src/api/KubernetesClusterLinkFormatter.ts new file mode 100644 index 0000000000..45dd6e6fa1 --- /dev/null +++ b/plugins/kubernetes-react/src/api/KubernetesClusterLinkFormatter.ts @@ -0,0 +1,59 @@ +/* + * 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. + */ + +import { + KubernetesClusterLinkFormatterApi, + FormatClusterLinkOptions, +} from './types'; +import { ClusterLinksFormatter } from '../types'; + +/** @public */ +export class KubernetesClusterLinkFormatter + implements KubernetesClusterLinkFormatterApi +{ + private readonly formatters: Record; + private readonly defaultFormatterName: string; + + constructor(options: { + formatters: Record; + defaultFormatterName: string; + }) { + this.formatters = options.formatters; + this.defaultFormatterName = options.defaultFormatterName; + } + async formatClusterLink(options: FormatClusterLinkOptions) { + if (!options.dashboardUrl && !options.dashboardParameters) { + return undefined; + } + if (options.dashboardUrl && !options.object) { + return options.dashboardUrl; + } + const app = options.dashboardApp ?? this.defaultFormatterName; + const formatter = this.formatters[app]; + if (!formatter) { + throw new Error(`Could not find Kubernetes dashboard app named '${app}'`); + } + const url = await formatter.formatClusterLink({ + dashboardUrl: options.dashboardUrl + ? new URL(options.dashboardUrl) + : undefined, + dashboardParameters: options.dashboardParameters, + object: options.object, + kind: options.kind, + }); + return url.toString(); + } +} diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/aks.test.ts b/plugins/kubernetes-react/src/api/formatters/AksClusterLinksFormatter.test.ts similarity index 82% rename from plugins/kubernetes-react/src/utils/clusterLinks/formatters/aks.test.ts rename to plugins/kubernetes-react/src/api/formatters/AksClusterLinksFormatter.test.ts index 18db618686..b7bdc3d7e8 100644 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/aks.test.ts +++ b/plugins/kubernetes-react/src/api/formatters/AksClusterLinksFormatter.test.ts @@ -13,12 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { aksFormatter } from './aks'; +import { AksClusterLinksFormatter } from './AksClusterLinksFormatter'; describe('clusterLinks - AKS formatter', () => { - it('should provide a dashboardParameters in the options', () => { - expect(() => - aksFormatter({ + const formatter = new AksClusterLinksFormatter(); + it('should provide a dashboardParameters in the options', async () => { + await expect(() => + formatter.formatClusterLink({ object: { metadata: { name: 'foobar', @@ -27,11 +28,11 @@ describe('clusterLinks - AKS formatter', () => { }, kind: 'Deployment', }), - ).toThrow('AKS dashboard requires a dashboardParameters option'); + ).rejects.toThrow('AKS dashboard requires a dashboardParameters option'); }); - it('should provide a subscriptionId in the dashboardParameters options', () => { - expect(() => - aksFormatter({ + it('should provide a subscriptionId in the dashboardParameters options', async () => { + await expect( + formatter.formatClusterLink({ dashboardParameters: { resourceGroup: 'rg-1', clusterName: 'cluster-1', @@ -44,13 +45,13 @@ describe('clusterLinks - AKS formatter', () => { }, kind: 'Deployment', }), - ).toThrow( + ).rejects.toThrow( 'AKS dashboard requires a "subscriptionId" of type string in the dashboardParameters option', ); }); - it('should provide a resourceGroup in the dashboardParameters options', () => { - expect(() => - aksFormatter({ + it('should provide a resourceGroup in the dashboardParameters options', async () => { + await expect( + formatter.formatClusterLink({ dashboardParameters: { subscriptionId: '1234-GUID-5678', clusterName: 'cluster-1', @@ -63,13 +64,13 @@ describe('clusterLinks - AKS formatter', () => { }, kind: 'Deployment', }), - ).toThrow( + ).rejects.toThrow( 'AKS dashboard requires a "resourceGroup" of type string in the dashboardParameters option', ); }); - it('should provide a clusterName in the dashboardParameters options', () => { - expect(() => - aksFormatter({ + it('should provide a clusterName in the dashboardParameters options', async () => { + await expect( + formatter.formatClusterLink({ dashboardParameters: { subscriptionId: '1234-GUID-5678', resourceGroup: 'us-east1-c', @@ -82,12 +83,12 @@ describe('clusterLinks - AKS formatter', () => { }, kind: 'Deployment', }), - ).toThrow( + ).rejects.toThrow( 'AKS dashboard requires a "clusterName" of type string in the dashboardParameters option', ); }); - it('should return an url on the cluster with object details', () => { - const url = aksFormatter({ + it('should return an url on the cluster with object details', async () => { + const url = await formatter.formatClusterLink({ dashboardParameters: { subscriptionId: '1234-GUID-5678', resourceGroup: 'rg-1', diff --git a/plugins/kubernetes-react/src/api/formatters/AksClusterLinksFormatter.ts b/plugins/kubernetes-react/src/api/formatters/AksClusterLinksFormatter.ts new file mode 100644 index 0000000000..1e7bb0ff9e --- /dev/null +++ b/plugins/kubernetes-react/src/api/formatters/AksClusterLinksFormatter.ts @@ -0,0 +1,59 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + ClusterLinksFormatter, + ClusterLinksFormatterOptions, +} from '../../types'; + +const basePath = + 'https://portal.azure.com/#blade/Microsoft_Azure_ContainerService/AksK8ResourceMenuBlade/overview-Deployment/aksClusterId'; + +const requiredParams = ['subscriptionId', 'resourceGroup', 'clusterName']; + +/** @public */ +export class AksClusterLinksFormatter implements ClusterLinksFormatter { + async formatClusterLink(options: ClusterLinksFormatterOptions) { + if (!options.dashboardParameters) { + throw new Error('AKS dashboard requires a dashboardParameters option'); + } + const args = options.dashboardParameters; + for (const param of requiredParams) { + if (typeof args[param] !== 'string') { + throw new Error( + `AKS dashboard requires a "${param}" of type string in the dashboardParameters option`, + ); + } + } + + const path = `/subscriptions/${args.subscriptionId}/resourceGroups/${args.resourceGroup}/providers/Microsoft.ContainerService/managedClusters/${args.clusterName}`; + + const { name, namespace, uid } = options.object.metadata; + const { selector } = options.object.spec; + const params = { + kind: options.kind, + metadata: { name, namespace, uid }, + spec: { + selector, + }, + }; + + return new URL( + `${basePath}/${encodeURIComponent(path)}/resource/${encodeURIComponent( + JSON.stringify(params), + )}`, + ); + } +} diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/eks.test.ts b/plugins/kubernetes-react/src/api/formatters/EksClusterLinksFormatter.test.ts similarity index 75% rename from plugins/kubernetes-react/src/utils/clusterLinks/formatters/eks.test.ts rename to plugins/kubernetes-react/src/api/formatters/EksClusterLinksFormatter.test.ts index d0ae73753f..738da9fb94 100644 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/eks.test.ts +++ b/plugins/kubernetes-react/src/api/formatters/EksClusterLinksFormatter.test.ts @@ -13,12 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { eksFormatter } from './eks'; + +import { EksClusterLinksFormatter } from './EksClusterLinksFormatter'; describe('clusterLinks - EKS formatter', () => { - it('should return an url on the workloads when there is a namespace only', () => { - expect(() => - eksFormatter({ + const formatter = new EksClusterLinksFormatter(); + it('should return an url on the workloads when there is a namespace only', async () => { + await expect( + formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com'), object: { metadata: { @@ -28,6 +30,8 @@ describe('clusterLinks - EKS formatter', () => { }, kind: 'Deployment', }), - ).toThrow('EKS formatter is not yet implemented. Please, contribute!'); + ).rejects.toThrow( + 'EKS formatter is not yet implemented. Please, contribute!', + ); }); }); diff --git a/plugins/kubernetes-react/src/api/formatters/EksClusterLinksFormatter.ts b/plugins/kubernetes-react/src/api/formatters/EksClusterLinksFormatter.ts new file mode 100644 index 0000000000..d65b619639 --- /dev/null +++ b/plugins/kubernetes-react/src/api/formatters/EksClusterLinksFormatter.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + ClusterLinksFormatter, + ClusterLinksFormatterOptions, +} from '../../types'; + +/** @public */ +export class EksClusterLinksFormatter implements ClusterLinksFormatter { + async formatClusterLink( + _options: ClusterLinksFormatterOptions, + ): Promise { + throw new Error( + 'EKS formatter is not yet implemented. Please, contribute!', + ); + } +} diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/gke.test.ts b/plugins/kubernetes-react/src/api/formatters/GkeClusterLinksFormatter.test.ts similarity index 80% rename from plugins/kubernetes-react/src/utils/clusterLinks/formatters/gke.test.ts rename to plugins/kubernetes-react/src/api/formatters/GkeClusterLinksFormatter.test.ts index 7fd0814267..250be75214 100644 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/gke.test.ts +++ b/plugins/kubernetes-react/src/api/formatters/GkeClusterLinksFormatter.test.ts @@ -13,12 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { gkeFormatter } from './gke'; + +import { GkeClusterLinksFormatter } from './GkeClusterLinksFormatter'; describe('clusterLinks - GKE formatter', () => { - it('should provide a dashboardParameters in the options', () => { - expect(() => - gkeFormatter({ + const formatter = new GkeClusterLinksFormatter(); + + it('should provide a dashboardParameters in the options', async () => { + await expect( + formatter.formatClusterLink({ object: { metadata: { name: 'foobar', @@ -27,11 +30,11 @@ describe('clusterLinks - GKE formatter', () => { }, kind: 'Deployment', }), - ).toThrow('GKE dashboard requires a dashboardParameters option'); + ).rejects.toThrow('GKE dashboard requires a dashboardParameters option'); }); - it('should provide a projectId in the dashboardParameters options', () => { - expect(() => - gkeFormatter({ + it('should provide a projectId in the dashboardParameters options', async () => { + await expect( + formatter.formatClusterLink({ dashboardParameters: { region: 'us-east1-c', clusterName: 'cluster-1', @@ -44,13 +47,13 @@ describe('clusterLinks - GKE formatter', () => { }, kind: 'Deployment', }), - ).toThrow( + ).rejects.toThrow( 'GKE dashboard requires a "projectId" of type string in the dashboardParameters option', ); }); - it('should provide a region in the dashboardParameters options', () => { - expect(() => - gkeFormatter({ + it('should provide a region in the dashboardParameters options', async () => { + await expect( + formatter.formatClusterLink({ dashboardParameters: { projectId: 'foobar-333614', clusterName: 'cluster-1', @@ -63,13 +66,13 @@ describe('clusterLinks - GKE formatter', () => { }, kind: 'Deployment', }), - ).toThrow( + ).rejects.toThrow( 'GKE dashboard requires a "region" of type string in the dashboardParameters option', ); }); - it('should provide a clusterName in the dashboardParameters options', () => { - expect(() => - gkeFormatter({ + it('should provide a clusterName in the dashboardParameters options', async () => { + await expect(() => + formatter.formatClusterLink({ dashboardParameters: { projectId: 'foobar-333614', region: 'us-east1-c', @@ -82,12 +85,12 @@ describe('clusterLinks - GKE formatter', () => { }, kind: 'Deployment', }), - ).toThrow( + ).rejects.toThrow( 'GKE dashboard requires a "clusterName" of type string in the dashboardParameters option', ); }); - it('should return an url on the cluster when there is a namespace only', () => { - const url = gkeFormatter({ + it('should return an url on the cluster when there is a namespace only', async () => { + const url = await formatter.formatClusterLink({ dashboardParameters: { projectId: 'foobar-333614', region: 'us-east1-c', @@ -104,8 +107,8 @@ describe('clusterLinks - GKE formatter', () => { 'https://console.cloud.google.com/kubernetes/clusters/details/us-east1-c/cluster-1/details?project=foobar-333614', ); }); - it('should return an url on the cluster when the kind is not recognizeed', () => { - const url = gkeFormatter({ + it('should return an url on the cluster when the kind is not recognizeed', async () => { + const url = await formatter.formatClusterLink({ dashboardParameters: { projectId: 'foobar-333614', region: 'us-east1-c', @@ -123,8 +126,8 @@ describe('clusterLinks - GKE formatter', () => { 'https://console.cloud.google.com/kubernetes/clusters/details/us-east1-c/cluster-1/details?project=foobar-333614', ); }); - it('should return an url on the deployment', () => { - const url = gkeFormatter({ + it('should return an url on the deployment', async () => { + const url = await formatter.formatClusterLink({ dashboardParameters: { projectId: 'foobar-333614', region: 'us-east1-c', @@ -143,8 +146,8 @@ describe('clusterLinks - GKE formatter', () => { ); }); - it('should return an url on the service', () => { - const url = gkeFormatter({ + it('should return an url on the service', async () => { + const url = await formatter.formatClusterLink({ dashboardParameters: { projectId: 'foobar-333614', region: 'us-east1-c', @@ -162,8 +165,8 @@ describe('clusterLinks - GKE formatter', () => { 'https://console.cloud.google.com/kubernetes/service/us-east1-c/cluster-1/bar/foobar/overview?project=foobar-333614', ); }); - it('should return an url on the pod', () => { - const url = gkeFormatter({ + it('should return an url on the pod', async () => { + const url = await formatter.formatClusterLink({ dashboardParameters: { projectId: 'foobar-333614', region: 'us-east1-c', @@ -181,8 +184,8 @@ describe('clusterLinks - GKE formatter', () => { 'https://console.cloud.google.com/kubernetes/pod/us-east1-c/cluster-1/bar/foobar/details?project=foobar-333614', ); }); - it('should return an url on the ingress', () => { - const url = gkeFormatter({ + it('should return an url on the ingress', async () => { + const url = await formatter.formatClusterLink({ dashboardParameters: { projectId: 'foobar-333614', region: 'us-east1-c', @@ -200,8 +203,8 @@ describe('clusterLinks - GKE formatter', () => { 'https://console.cloud.google.com/kubernetes/ingress/us-east1-c/cluster-1/bar/foobar/details?project=foobar-333614', ); }); - it('should return an url on the deployment for a hpa', () => { - const url = gkeFormatter({ + it('should return an url on the deployment for a hpa', async () => { + const url = await formatter.formatClusterLink({ dashboardParameters: { projectId: 'foobar-333614', region: 'us-east1-c', diff --git a/plugins/kubernetes-react/src/api/formatters/GkeClusterLinksFormatter.ts b/plugins/kubernetes-react/src/api/formatters/GkeClusterLinksFormatter.ts new file mode 100644 index 0000000000..c8dec85f71 --- /dev/null +++ b/plugins/kubernetes-react/src/api/formatters/GkeClusterLinksFormatter.ts @@ -0,0 +1,73 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + ClusterLinksFormatter, + ClusterLinksFormatterOptions, +} from '../../types'; + +const kindMappings: Record = { + deployment: 'deployment', + pod: 'pod', + ingress: 'ingress', + service: 'service', + horizontalpodautoscaler: 'deployment', +}; + +/** @public */ +export class GkeClusterLinksFormatter implements ClusterLinksFormatter { + async formatClusterLink(options: ClusterLinksFormatterOptions): Promise { + if (!options.dashboardParameters) { + throw new Error('GKE dashboard requires a dashboardParameters option'); + } + const args = options.dashboardParameters; + if (typeof args.projectId !== 'string') { + throw new Error( + 'GKE dashboard requires a "projectId" of type string in the dashboardParameters option', + ); + } + if (typeof args.region !== 'string') { + throw new Error( + 'GKE dashboard requires a "region" of type string in the dashboardParameters option', + ); + } + if (typeof args.clusterName !== 'string') { + throw new Error( + 'GKE dashboard requires a "clusterName" of type string in the dashboardParameters option', + ); + } + const basePath = new URL('https://console.cloud.google.com/'); + const region = encodeURIComponent(args.region); + const clusterName = encodeURIComponent(args.clusterName); + const name = encodeURIComponent(options.object.metadata?.name ?? ''); + const namespace = encodeURIComponent( + options.object.metadata?.namespace ?? '', + ); + const validKind = kindMappings[options.kind.toLocaleLowerCase('en-US')]; + let path: string; + if (namespace && name && validKind) { + const kindsWithDetails = ['ingress', 'pod']; + const landingPage = kindsWithDetails.includes(validKind) + ? 'details' + : 'overview'; + path = `kubernetes/${validKind}/${region}/${clusterName}/${namespace}/${name}/${landingPage}`; + } else { + path = `kubernetes/clusters/details/${region}/${clusterName}/details`; + } + const result = new URL(path, basePath); + result.searchParams.set('project', args.projectId); + return result; + } +} diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/openshift.test.ts b/plugins/kubernetes-react/src/api/formatters/OpenshiftClusterLinksFormatter.test.ts similarity index 75% rename from plugins/kubernetes-react/src/utils/clusterLinks/formatters/openshift.test.ts rename to plugins/kubernetes-react/src/api/formatters/OpenshiftClusterLinksFormatter.test.ts index 945553e340..1adb688757 100644 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/openshift.test.ts +++ b/plugins/kubernetes-react/src/api/formatters/OpenshiftClusterLinksFormatter.test.ts @@ -13,12 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { openshiftFormatter } from './openshift'; + +import { OpenshiftClusterLinksFormatter } from './OpenshiftClusterLinksFormatter'; describe('clusterLinks - OpenShift formatter', () => { - it('should provide a dashboardUrl in the options', () => { - expect(() => - openshiftFormatter({ + const formatter = new OpenshiftClusterLinksFormatter(); + it('should provide a dashboardUrl in the options', async () => { + await expect(() => + formatter.formatClusterLink({ object: { metadata: { name: 'foobar', @@ -27,10 +29,10 @@ describe('clusterLinks - OpenShift formatter', () => { }, kind: 'Deployment', }), - ).toThrow('OpenShift dashboard requires a dashboardUrl option'); + ).rejects.toThrow('OpenShift dashboard requires a dashboardUrl option'); }); - it('should return an url on the workloads when there is a namespace only', () => { - const url = openshiftFormatter({ + it('should return an url on the workloads when there is a namespace only', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com'), object: { metadata: { @@ -41,8 +43,8 @@ describe('clusterLinks - OpenShift formatter', () => { }); expect(url.href).toBe('https://k8s.foo.com/k8s/cluster/projects/bar'); }); - it('should return an url on the workloads when the kind is not recognizeed', () => { - const url = openshiftFormatter({ + it('should return an url on the workloads when the kind is not recognizeed', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com'), object: { metadata: { @@ -54,8 +56,8 @@ describe('clusterLinks - OpenShift formatter', () => { }); expect(url.href).toBe('https://k8s.foo.com/k8s/cluster/projects/bar'); }); - it('should return an url on the deployment', () => { - const url = openshiftFormatter({ + it('should return an url on the deployment', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { @@ -67,8 +69,8 @@ describe('clusterLinks - OpenShift formatter', () => { }); expect(url.href).toBe('https://k8s.foo.com/k8s/ns/bar/deployments/foobar'); }); - it('should return an url on the deployment and keep the path prefix 1', () => { - const url = openshiftFormatter({ + it('should return an url on the deployment and keep the path prefix 1', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/some/prefix/'), object: { metadata: { @@ -82,8 +84,8 @@ describe('clusterLinks - OpenShift formatter', () => { 'https://k8s.foo.com/some/prefix/k8s/ns/bar/deployments/foobar', ); }); - it('should return an url on the deployment and keep the path prefix 2', () => { - const url = openshiftFormatter({ + it('should return an url on the deployment and keep the path prefix 2', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/some/prefix'), object: { metadata: { @@ -97,8 +99,8 @@ describe('clusterLinks - OpenShift formatter', () => { 'https://k8s.foo.com/some/prefix/k8s/ns/bar/deployments/foobar', ); }); - it('should return an url on the service', () => { - const url = openshiftFormatter({ + it('should return an url on the service', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { @@ -110,8 +112,8 @@ describe('clusterLinks - OpenShift formatter', () => { }); expect(url.href).toBe('https://k8s.foo.com/k8s/ns/bar/services/foobar'); }); - it('should return an url on the ingress', () => { - const url = openshiftFormatter({ + it('should return an url on the ingress', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { @@ -123,8 +125,8 @@ describe('clusterLinks - OpenShift formatter', () => { }); expect(url.href).toBe('https://k8s.foo.com/k8s/ns/bar/ingresses/foobar'); }); - it('should return an url on the deployment for a hpa', () => { - const url = openshiftFormatter({ + it('should return an url on the deployment for a hpa', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { @@ -138,8 +140,8 @@ describe('clusterLinks - OpenShift formatter', () => { 'https://k8s.foo.com/k8s/ns/bar/horizontalpodautoscalers/foobar', ); }); - it('should return an url on the PV', () => { - const url = openshiftFormatter({ + it('should return an url on the PV', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { diff --git a/plugins/kubernetes-react/src/api/formatters/OpenshiftClusterLinksFormatter.ts b/plugins/kubernetes-react/src/api/formatters/OpenshiftClusterLinksFormatter.ts new file mode 100644 index 0000000000..228ff3d1ac --- /dev/null +++ b/plugins/kubernetes-react/src/api/formatters/OpenshiftClusterLinksFormatter.ts @@ -0,0 +1,60 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ClusterLinksFormatterOptions } from '../../types'; + +const kindMappings: Record = { + deployment: 'deployments', + ingress: 'ingresses', + service: 'services', + horizontalpodautoscaler: 'horizontalpodautoscalers', + persistentvolume: 'persistentvolumes', +}; + +/** @public */ +export class OpenshiftClusterLinksFormatter { + async formatClusterLink(options: ClusterLinksFormatterOptions): Promise { + if (!options.dashboardUrl) { + throw new Error('OpenShift dashboard requires a dashboardUrl option'); + } + const basePath = new URL(options.dashboardUrl.href); + const name = encodeURIComponent(options.object.metadata?.name ?? ''); + const namespace = encodeURIComponent( + options.object.metadata?.namespace ?? '', + ); + const validKind = kindMappings[options.kind.toLocaleLowerCase('en-US')]; + if (!basePath.pathname.endsWith('/')) { + // a dashboard url with a path should end with a slash otherwise + // the new combined URL will replace the last segment with the appended path! + // https://foobar.com/abc/def + k8s/cluster/projects/test --> https://foobar.com/abc/k8s/cluster/projects/test + // https://foobar.com/abc/def/ + k8s/cluster/projects/test --> https://foobar.com/abc/def/k8s/cluster/projects/test + basePath.pathname += '/'; + } + let path = ''; + if (namespace) { + if (name && validKind) { + path = `k8s/ns/${namespace}/${validKind}/${name}`; + } else { + path = `k8s/cluster/projects/${namespace}`; + } + } else if (validKind) { + path = `k8s/cluster/${validKind}`; + if (name) { + path += `/${name}`; + } + } + return new URL(path, basePath); + } +} diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/rancher.test.ts b/plugins/kubernetes-react/src/api/formatters/RancherClusterLinksFormatter.test.ts similarity index 74% rename from plugins/kubernetes-react/src/utils/clusterLinks/formatters/rancher.test.ts rename to plugins/kubernetes-react/src/api/formatters/RancherClusterLinksFormatter.test.ts index bb26da3ab0..228340eb16 100644 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/rancher.test.ts +++ b/plugins/kubernetes-react/src/api/formatters/RancherClusterLinksFormatter.test.ts @@ -13,12 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { rancherFormatter } from './rancher'; + +import { RancherClusterLinksFormatter } from './RancherClusterLinksFormatter'; describe('clusterLinks - rancher formatter', () => { - it('should provide a dashboardUrl in the options', () => { - expect(() => - rancherFormatter({ + const formatter = new RancherClusterLinksFormatter(); + it('should provide a dashboardUrl in the options', async () => { + await expect(() => + formatter.formatClusterLink({ object: { metadata: { name: 'foobar', @@ -27,10 +29,10 @@ describe('clusterLinks - rancher formatter', () => { }, kind: 'Deployment', }), - ).toThrow('Rancher dashboard requires a dashboardUrl option'); + ).rejects.toThrow('Rancher dashboard requires a dashboardUrl option'); }); - it('should return a url on the workloads when there is a namespace only', () => { - const url = rancherFormatter({ + it('should return a url on the workloads when there is a namespace only', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com'), object: { metadata: { @@ -41,8 +43,8 @@ describe('clusterLinks - rancher formatter', () => { }); expect(url.href).toBe('https://k8s.foo.com/explorer/workload'); }); - it('should return a url on the workloads when the kind is not recognized', () => { - const url = rancherFormatter({ + it('should return a url on the workloads when the kind is not recognized', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com'), object: { metadata: { @@ -54,8 +56,8 @@ describe('clusterLinks - rancher formatter', () => { }); expect(url.href).toBe('https://k8s.foo.com/explorer/workload'); }); - it('should return a url on the deployment', () => { - const url = rancherFormatter({ + it('should return a url on the deployment', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { @@ -69,8 +71,8 @@ describe('clusterLinks - rancher formatter', () => { 'https://k8s.foo.com/explorer/apps.deployment/bar/foobar', ); }); - it('should return a url on the service', () => { - const url = rancherFormatter({ + it('should return a url on the service', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { @@ -82,8 +84,8 @@ describe('clusterLinks - rancher formatter', () => { }); expect(url.href).toBe('https://k8s.foo.com/explorer/service/bar/foobar'); }); - it('should return a url on the ingress', () => { - const url = rancherFormatter({ + it('should return a url on the ingress', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { @@ -97,8 +99,8 @@ describe('clusterLinks - rancher formatter', () => { 'https://k8s.foo.com/explorer/networking.k8s.io.ingress/bar/foobar', ); }); - it('should return a url on the deployment for a hpa', () => { - const url = rancherFormatter({ + it('should return a url on the deployment for a hpa', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { @@ -112,8 +114,8 @@ describe('clusterLinks - rancher formatter', () => { 'https://k8s.foo.com/explorer/autoscaling.horizontalpodautoscaler/bar/foobar', ); }); - it('should support subpaths in dashboardUrl', () => { - const url = rancherFormatter({ + it('should support subpaths in dashboardUrl', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/dashboard/c/c-28a4b/'), object: { metadata: { diff --git a/plugins/kubernetes-react/src/api/formatters/RancherClusterLinksFormatter.ts b/plugins/kubernetes-react/src/api/formatters/RancherClusterLinksFormatter.ts new file mode 100644 index 0000000000..e607d98972 --- /dev/null +++ b/plugins/kubernetes-react/src/api/formatters/RancherClusterLinksFormatter.ts @@ -0,0 +1,55 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + ClusterLinksFormatter, + ClusterLinksFormatterOptions, +} from '../../types'; + +const kindMappings: Record = { + deployment: 'apps.deployment', + ingress: 'networking.k8s.io.ingress', + service: 'service', + horizontalpodautoscaler: 'autoscaling.horizontalpodautoscaler', +}; + +/** @public */ +export class RancherClusterLinksFormatter implements ClusterLinksFormatter { + async formatClusterLink(options: ClusterLinksFormatterOptions): Promise { + if (!options.dashboardUrl) { + throw new Error('Rancher dashboard requires a dashboardUrl option'); + } + const basePath = new URL(options.dashboardUrl.href); + const name = encodeURIComponent(options.object.metadata?.name ?? ''); + const namespace = encodeURIComponent( + options.object.metadata?.namespace ?? '', + ); + const validKind = kindMappings[options.kind.toLocaleLowerCase('en-US')]; + if (!basePath.pathname.endsWith('/')) { + // a dashboard url with a path should end with a slash otherwise + // the new combined URL will replace the last segment with the appended path! + // https://foobar.com/abc/def + explorer/service/test --> https://foobar.com/abc/explorer/service/test + // https://foobar.com/abc/def/ + explorer/service/test --> https://foobar.com/abc/def/explorer/service/test + basePath.pathname += '/'; + } + let path = ''; + if (validKind && name && namespace) { + path = `explorer/${validKind}/${namespace}/${name}`; + } else if (namespace) { + path = 'explorer/workload'; + } + return new URL(path, basePath); + } +} diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/standard.test.ts b/plugins/kubernetes-react/src/api/formatters/StandardClusterLinksFormatter.test.ts similarity index 76% rename from plugins/kubernetes-react/src/utils/clusterLinks/formatters/standard.test.ts rename to plugins/kubernetes-react/src/api/formatters/StandardClusterLinksFormatter.test.ts index 280de6bfde..fe1b2be4f5 100644 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/standard.test.ts +++ b/plugins/kubernetes-react/src/api/formatters/StandardClusterLinksFormatter.test.ts @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { standardFormatter } from './standard'; + +import { StandardClusterLinksFormatter } from './StandardClusterLinksFormatter'; function formatUrl(url: URL) { // Note that we can't rely on 'url.href' since it will put the search before the hash @@ -23,9 +24,10 @@ function formatUrl(url: URL) { } describe('clusterLinks - standard formatter', () => { - it('should provide a dashboardUrl in the options', () => { - expect(() => - standardFormatter({ + const formatter = new StandardClusterLinksFormatter(); + it('should provide a dashboardUrl in the options', async () => { + await expect(() => + formatter.formatClusterLink({ object: { metadata: { name: 'foobar', @@ -34,10 +36,10 @@ describe('clusterLinks - standard formatter', () => { }, kind: 'Deployment', }), - ).toThrow('standard dashboard requires a dashboardUrl option'); + ).rejects.toThrow('standard dashboard requires a dashboardUrl option'); }); - it('should return an url on the workloads when there is a namespace only', () => { - const url = standardFormatter({ + it('should return an url on the workloads when there is a namespace only', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com'), object: { metadata: { @@ -50,8 +52,8 @@ describe('clusterLinks - standard formatter', () => { 'https://k8s.foo.com/#/workloads?namespace=bar', ); }); - it('should return an url on the workloads when the kind is not recognizeed', () => { - const url = standardFormatter({ + it('should return an url on the workloads when the kind is not recognizeed', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com'), object: { metadata: { @@ -65,8 +67,8 @@ describe('clusterLinks - standard formatter', () => { 'https://k8s.foo.com/#/workloads?namespace=bar', ); }); - it('should return an url on the deployment', () => { - const url = standardFormatter({ + it('should return an url on the deployment', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { @@ -80,8 +82,8 @@ describe('clusterLinks - standard formatter', () => { 'https://k8s.foo.com/#/deployment/bar/foobar?namespace=bar', ); }); - it('should return an url on the pod', () => { - const url = standardFormatter({ + it('should return an url on the pod', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { @@ -95,8 +97,8 @@ describe('clusterLinks - standard formatter', () => { 'https://k8s.foo.com/#/pod/bar/foobar?namespace=bar', ); }); - it('should return an url on the deployment with a prefix 1', () => { - const url = standardFormatter({ + it('should return an url on the deployment with a prefix 1', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/some/prefix'), object: { metadata: { @@ -110,8 +112,8 @@ describe('clusterLinks - standard formatter', () => { 'https://k8s.foo.com/some/prefix/#/deployment/bar/foobar?namespace=bar', ); }); - it('should return an url on the deployment with a prefix 2', () => { - const url = standardFormatter({ + it('should return an url on the deployment with a prefix 2', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/some/prefix/'), object: { metadata: { @@ -125,8 +127,8 @@ describe('clusterLinks - standard formatter', () => { 'https://k8s.foo.com/some/prefix/#/deployment/bar/foobar?namespace=bar', ); }); - it('should return an url on the deployment properly url encoded', () => { - const url = standardFormatter({ + it('should return an url on the deployment properly url encoded', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { @@ -140,8 +142,8 @@ describe('clusterLinks - standard formatter', () => { 'https://k8s.foo.com/#/deployment/bar%20bar/foobar?namespace=bar%20bar', ); }); - it('should return an url on the service', () => { - const url = standardFormatter({ + it('should return an url on the service', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { @@ -155,8 +157,8 @@ describe('clusterLinks - standard formatter', () => { 'https://k8s.foo.com/#/service/bar/foobar?namespace=bar', ); }); - it('should return an url on the ingress', () => { - const url = standardFormatter({ + it('should return an url on the ingress', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { @@ -170,8 +172,8 @@ describe('clusterLinks - standard formatter', () => { 'https://k8s.foo.com/#/ingress/bar/foobar?namespace=bar', ); }); - it('should return an url on the deployment for a hpa', () => { - const url = standardFormatter({ + it('should return an url on the deployment for a hpa', async () => { + const url = await formatter.formatClusterLink({ dashboardUrl: new URL('https://k8s.foo.com/'), object: { metadata: { diff --git a/plugins/kubernetes-react/src/api/formatters/StandardClusterLinksFormatter.ts b/plugins/kubernetes-react/src/api/formatters/StandardClusterLinksFormatter.ts new file mode 100644 index 0000000000..76537c5a4e --- /dev/null +++ b/plugins/kubernetes-react/src/api/formatters/StandardClusterLinksFormatter.ts @@ -0,0 +1,56 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + ClusterLinksFormatter, + ClusterLinksFormatterOptions, +} from '../../types'; + +const kindMappings: Record = { + deployment: 'deployment', + pod: 'pod', + ingress: 'ingress', + service: 'service', + horizontalpodautoscaler: 'deployment', + statefulset: 'statefulset', +}; + +/** @public */ +export class StandardClusterLinksFormatter implements ClusterLinksFormatter { + async formatClusterLink(options: ClusterLinksFormatterOptions): Promise { + if (!options.dashboardUrl) { + throw new Error('standard dashboard requires a dashboardUrl option'); + } + const result = new URL(options.dashboardUrl.href); + const name = encodeURIComponent(options.object.metadata?.name ?? ''); + const namespace = encodeURIComponent( + options.object.metadata?.namespace ?? '', + ); + const validKind = kindMappings[options.kind.toLocaleLowerCase('en-US')]; + if (!result.pathname.endsWith('/')) { + result.pathname += '/'; + } + if (validKind && name && namespace) { + result.hash = `/${validKind}/${namespace}/${name}`; + } else if (namespace) { + result.hash = '/workloads'; + } + if (namespace) { + // Note that Angular SPA requires a hash and the query parameter should be part of it + result.hash += `?namespace=${namespace}`; + } + return result; + } +} diff --git a/plugins/kubernetes-react/src/api/formatters/index.ts b/plugins/kubernetes-react/src/api/formatters/index.ts new file mode 100644 index 0000000000..97a3140d50 --- /dev/null +++ b/plugins/kubernetes-react/src/api/formatters/index.ts @@ -0,0 +1,50 @@ +/* + * 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. + */ + +import { AksClusterLinksFormatter } from './AksClusterLinksFormatter'; +import { ClusterLinksFormatter } from '../../types'; +import { EksClusterLinksFormatter } from './EksClusterLinksFormatter'; +import { GkeClusterLinksFormatter } from './GkeClusterLinksFormatter'; +import { StandardClusterLinksFormatter } from './StandardClusterLinksFormatter'; +import { OpenshiftClusterLinksFormatter } from './OpenshiftClusterLinksFormatter'; +import { RancherClusterLinksFormatter } from './RancherClusterLinksFormatter'; + +export { + StandardClusterLinksFormatter, + AksClusterLinksFormatter, + EksClusterLinksFormatter, + GkeClusterLinksFormatter, + OpenshiftClusterLinksFormatter, + RancherClusterLinksFormatter, +}; + +/** @public */ +export const DEFAULT_FORMATTER_NAME = 'standard'; + +/** @public */ +export function getDefaultFormatters(_deps: {}): Record< + string, + ClusterLinksFormatter +> { + return { + standard: new StandardClusterLinksFormatter(), + aks: new AksClusterLinksFormatter(), + eks: new EksClusterLinksFormatter(), + gke: new GkeClusterLinksFormatter(), + openshift: new OpenshiftClusterLinksFormatter(), + rancher: new RancherClusterLinksFormatter(), + }; +} diff --git a/plugins/kubernetes-react/src/api/index.ts b/plugins/kubernetes-react/src/api/index.ts index ec8843937a..42fbcf1618 100644 --- a/plugins/kubernetes-react/src/api/index.ts +++ b/plugins/kubernetes-react/src/api/index.ts @@ -14,7 +14,18 @@ * limitations under the License. */ -export { kubernetesApiRef, kubernetesProxyApiRef } from './types'; -export type { KubernetesApi, KubernetesProxyApi } from './types'; +export { + kubernetesApiRef, + kubernetesProxyApiRef, + kubernetesClusterLinkFormatterApiRef, +} from './types'; +export type { + KubernetesApi, + KubernetesProxyApi, + FormatClusterLinkOptions, + KubernetesClusterLinkFormatterApi, +} from './types'; export { KubernetesBackendClient } from './KubernetesBackendClient'; +export { KubernetesClusterLinkFormatter } from './KubernetesClusterLinkFormatter'; export { KubernetesProxyClient } from './KubernetesProxyClient'; +export * from './formatters'; diff --git a/plugins/kubernetes-react/src/api/types.ts b/plugins/kubernetes-react/src/api/types.ts index 28cf2dde55..cc27bf9dd4 100644 --- a/plugins/kubernetes-react/src/api/types.ts +++ b/plugins/kubernetes-react/src/api/types.ts @@ -22,6 +22,7 @@ import { } from '@backstage/plugin-kubernetes-common'; import { createApiRef } from '@backstage/core-plugin-api'; import { Event } from 'kubernetes-models/v1'; +import { JsonObject } from '@backstage/types'; /** @public */ export const kubernetesApiRef = createApiRef({ @@ -33,6 +34,12 @@ export const kubernetesProxyApiRef = createApiRef({ id: 'plugin.kubernetes.proxy-service', }); +/** @public */ +export const kubernetesClusterLinkFormatterApiRef = + createApiRef({ + id: 'plugin.kubernetes.cluster-link-formatter-service', + }); + /** @public */ export interface KubernetesApi { getObjectsByEntity( @@ -82,3 +89,21 @@ export interface KubernetesProxyApi { namespace: string; }): Promise; } + +/** + * @public + */ +export type FormatClusterLinkOptions = { + dashboardUrl?: string; + dashboardApp?: string; + dashboardParameters?: JsonObject; + object: any; + kind: string; +}; + +/** @public */ +export interface KubernetesClusterLinkFormatterApi { + formatClusterLink( + options: FormatClusterLinkOptions, + ): Promise; +} diff --git a/plugins/kubernetes-react/src/components/CronJobsAccordions/CronJobsDrawer.test.tsx b/plugins/kubernetes-react/src/components/CronJobsAccordions/CronJobsDrawer.test.tsx index b16e83ee50..75506476ea 100644 --- a/plugins/kubernetes-react/src/components/CronJobsAccordions/CronJobsDrawer.test.tsx +++ b/plugins/kubernetes-react/src/components/CronJobsAccordions/CronJobsDrawer.test.tsx @@ -15,16 +15,20 @@ */ import React from 'react'; import * as oneCronJobsFixture from '../../__fixtures__/1-cronjobs.json'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { CronJobDrawer } from './CronJobsDrawer'; +import { kubernetesClusterLinkFormatterApiRef } from '../../api'; describe('CronJobDrawer', () => { it('should render cronJob drawer', async () => { const { getByText, getAllByText } = await renderInTestApp( - , + + + , + , ); expect(getAllByText('dice-roller-cronjob')).toHaveLength(2); diff --git a/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx b/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx index f221a36cee..1e8515f81a 100644 --- a/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx +++ b/plugins/kubernetes-react/src/components/DeploymentsAccordions/DeploymentDrawer.test.tsx @@ -16,16 +16,24 @@ import React from 'react'; import * as deployments from '../../__fixtures__/2-deployments.json'; -import { renderInTestApp, textContentMatcher } from '@backstage/test-utils'; +import { + renderInTestApp, + TestApiProvider, + textContentMatcher, +} from '@backstage/test-utils'; import { DeploymentDrawer } from './DeploymentDrawer'; +import { kubernetesClusterLinkFormatterApiRef } from '../../api'; describe('DeploymentDrawer', () => { it('should render deployment drawer', async () => { const { getByText, getAllByText } = await renderInTestApp( - , + + + , + , ); expect(getAllByText('dice-roller')).toHaveLength(2); @@ -53,13 +61,16 @@ describe('DeploymentDrawer', () => { it('should render deployment drawer without namespace', async () => { const deployment = (deployments as any).deployments[0]; const { queryByText } = await renderInTestApp( - , + + + , + , ); expect(queryByText('namespace: default')).not.toBeInTheDocument(); diff --git a/plugins/kubernetes-react/src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.test.tsx b/plugins/kubernetes-react/src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.test.tsx index beb0db1e2b..6599a2041f 100644 --- a/plugins/kubernetes-react/src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.test.tsx +++ b/plugins/kubernetes-react/src/components/HorizontalPodAutoscalers/HorizontalPodAutoscalerDrawer.test.tsx @@ -17,15 +17,18 @@ import React from 'react'; import { screen } from '@testing-library/react'; import * as hpas from './__fixtures__/horizontalpodautoscalers.json'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { HorizontalPodAutoscalerDrawer } from './HorizontalPodAutoscalerDrawer'; +import { kubernetesClusterLinkFormatterApiRef } from '../../api'; describe('HorizontalPodAutoscalersDrawer', () => { it('should render hpa drawer', async () => { await renderInTestApp( - -

CHILD

-
, + + +

CHILD

+
+
, ); expect(screen.getByText('dice-roller')).toBeInTheDocument(); diff --git a/plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.test.tsx b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.test.tsx index 8619e362b7..cfacb24ee4 100644 --- a/plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.test.tsx +++ b/plugins/kubernetes-react/src/components/IngressesAccordions/IngressDrawer.test.tsx @@ -14,16 +14,23 @@ * limitations under the License. */ -import { renderInTestApp, textContentMatcher } from '@backstage/test-utils'; +import { + renderInTestApp, + TestApiProvider, + textContentMatcher, +} from '@backstage/test-utils'; import { screen } from '@testing-library/react'; import React from 'react'; import { IngressDrawer } from './IngressDrawer'; import * as ingresses from './__fixtures__/2-ingresses.json'; +import { kubernetesClusterLinkFormatterApiRef } from '../../api'; describe('IngressDrawer', () => { it('should render ingress drawer', async () => { await renderInTestApp( - , + + + , ); expect(screen.getAllByText('awesome-service')).toHaveLength(4); diff --git a/plugins/kubernetes-react/src/components/JobsAccordions/JobsDrawer.test.tsx b/plugins/kubernetes-react/src/components/JobsAccordions/JobsDrawer.test.tsx index 48a4e6fe7e..23f49a2118 100644 --- a/plugins/kubernetes-react/src/components/JobsAccordions/JobsDrawer.test.tsx +++ b/plugins/kubernetes-react/src/components/JobsAccordions/JobsDrawer.test.tsx @@ -15,13 +15,16 @@ */ import React from 'react'; import * as oneCronJobsFixture from '../../__fixtures__/1-cronjobs.json'; -import { renderInTestApp } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { JobDrawer } from './JobsDrawer'; +import { kubernetesClusterLinkFormatterApiRef } from '../../api'; describe('JobDrawer', () => { it('should render job drawer', async () => { const { getByText, getAllByText } = await renderInTestApp( - , + + , + , ); expect(getAllByText('dice-roller-cronjob-1637025000')).toHaveLength(2); diff --git a/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx b/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx index 65001c658e..0b6cfa26b4 100644 --- a/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx +++ b/plugins/kubernetes-react/src/components/KubernetesDrawer/KubernetesStructuredMetadataTableDrawer.tsx @@ -37,10 +37,11 @@ import { WarningPanel, } from '@backstage/core-components'; import { ClusterContext } from '../../hooks'; -import { formatClusterLink } from '../../utils/clusterLinks'; import { ClusterAttributes } from '@backstage/plugin-kubernetes-common'; -import { FormatClusterLinkOptions } from '../../utils/clusterLinks/formatClusterLink'; import { ManifestYaml } from './ManifestYaml'; +import { useApi } from '@backstage/core-plugin-api'; +import { kubernetesClusterLinkFormatterApiRef } from '../../api'; +import useAsync from 'react-use/lib/useAsync'; const useDrawerStyles = makeStyles((theme: Theme) => createStyles({ @@ -147,20 +148,6 @@ function replaceNullsWithUndefined(someObj: any) { return JSON.parse(JSON.stringify(someObj, replacer)); } -function tryFormatClusterLink(options: FormatClusterLinkOptions) { - try { - return { - clusterLink: formatClusterLink(options), - errorMessage: '', - }; - } catch (err) { - return { - clusterLink: '', - errorMessage: err.message || err.toString(), - }; - } -} - const KubernetesStructuredMetadataTableDrawerContent = < T extends KubernetesDrawerable, >({ @@ -171,15 +158,20 @@ const KubernetesStructuredMetadataTableDrawerContent = < }: KubernetesStructuredMetadataTableDrawerContentProps) => { const [isYaml, setIsYaml] = useState(false); + const formatter = useApi(kubernetesClusterLinkFormatterApiRef); const classes = useDrawerContentStyles(); const cluster = useContext(ClusterContext); - const { clusterLink, errorMessage } = tryFormatClusterLink({ - dashboardUrl: cluster.dashboardUrl, - dashboardApp: cluster.dashboardApp, - dashboardParameters: cluster.dashboardParameters, - object, - kind, - }); + const { value: clusterLink, error } = useAsync( + async () => + formatter.formatClusterLink({ + dashboardUrl: cluster.dashboardUrl, + dashboardApp: cluster.dashboardApp, + dashboardParameters: cluster.dashboardParameters, + object, + kind, + }), + [cluster, object, kind, formatter], + ); return ( <> @@ -221,9 +213,12 @@ const KubernetesStructuredMetadataTableDrawerContent = < - {errorMessage && ( + {error && (
- +
)}
diff --git a/plugins/kubernetes-react/src/components/Pods/PodsTable.tsx b/plugins/kubernetes-react/src/components/Pods/PodsTable.tsx index f7c2660c84..d83aebb210 100644 --- a/plugins/kubernetes-react/src/components/Pods/PodsTable.tsx +++ b/plugins/kubernetes-react/src/components/Pods/PodsTable.tsx @@ -125,6 +125,11 @@ const Memory = ({ clusterName, pod }: { clusterName: string; pod: Pod }) => { export const PodsTable = ({ pods, extraColumns = [] }: PodsTablesProps) => { const cluster = useContext(ClusterContext); const defaultColumns: TableColumn[] = [ + { + title: 'ID', + field: 'metadata.uid', + hidden: true, + }, { title: 'name', highlight: true, @@ -176,7 +181,14 @@ export const PodsTable = ({ pods, extraColumns = [] }: PodsTablesProps) => {
({ + ...pod, + id: pod?.metadata?.uid, + })) as any as Pod[] + } columns={columns} /> diff --git a/plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.test.tsx b/plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.test.tsx index dda5e300eb..7eec2926c4 100644 --- a/plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.test.tsx +++ b/plugins/kubernetes-react/src/components/ServicesAccordions/ServiceDrawer.test.tsx @@ -17,13 +17,20 @@ import React from 'react'; import { screen } from '@testing-library/react'; import * as services from './__fixtures__/2-services.json'; -import { textContentMatcher, renderInTestApp } from '@backstage/test-utils'; +import { + textContentMatcher, + renderInTestApp, + TestApiProvider, +} from '@backstage/test-utils'; import { ServiceDrawer } from './ServiceDrawer'; +import { kubernetesClusterLinkFormatterApiRef } from '../../api'; describe('ServiceDrawer', () => { it('should render deployment drawer', async () => { await renderInTestApp( - , + + , + , ); expect(screen.getAllByText('awesome-service-grpc')).toHaveLength(2); diff --git a/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx b/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx index c187c7d05d..d69ab15f1a 100644 --- a/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx +++ b/plugins/kubernetes-react/src/components/StatefulSetsAccordions/StatefulSetDrawer.test.tsx @@ -16,16 +16,24 @@ import React from 'react'; import * as statefulsets from '../../__fixtures__/2-statefulsets.json'; -import { renderInTestApp, textContentMatcher } from '@backstage/test-utils'; +import { + renderInTestApp, + TestApiProvider, + textContentMatcher, +} from '@backstage/test-utils'; import { StatefulSetDrawer } from './StatefulSetDrawer'; +import { kubernetesClusterLinkFormatterApiRef } from '../../api'; describe('StatefulSetDrawer', () => { it('should render statefulset drawer', async () => { const { getByText, getAllByText } = await renderInTestApp( - , + + + , + , ); expect(getAllByText('dice-roller')).toHaveLength(4); @@ -55,13 +63,16 @@ describe('StatefulSetDrawer', () => { it('should render statefulset drawer without namespace', async () => { const statefulset = (statefulsets as any).statefulsets[0]; const { queryByText } = await renderInTestApp( - , + + + , + , ); expect(queryByText('namespace: default')).not.toBeInTheDocument(); diff --git a/plugins/kubernetes-react/src/index.ts b/plugins/kubernetes-react/src/index.ts index 4fb8614091..326b363b05 100644 --- a/plugins/kubernetes-react/src/index.ts +++ b/plugins/kubernetes-react/src/index.ts @@ -27,5 +27,4 @@ export * from './hooks'; export * from './api'; export * from './kubernetes-auth-provider'; export * from './components'; -export * from './utils'; export * from './types'; diff --git a/plugins/kubernetes-react/src/types/types.ts b/plugins/kubernetes-react/src/types/types.ts index ad8df040ac..5db2e281f4 100644 --- a/plugins/kubernetes-react/src/types/types.ts +++ b/plugins/kubernetes-react/src/types/types.ts @@ -29,6 +29,6 @@ export interface ClusterLinksFormatterOptions { /** * @public */ -export type ClusterLinksFormatter = ( - options: ClusterLinksFormatterOptions, -) => URL; +export interface ClusterLinksFormatter { + formatClusterLink(options: ClusterLinksFormatterOptions): Promise; +} diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatClusterLink.test.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatClusterLink.test.ts deleted file mode 100644 index 254b9fc51b..0000000000 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatClusterLink.test.ts +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { formatClusterLink } from './formatClusterLink'; - -describe('clusterLinks', () => { - describe('formatClusterLink', () => { - it('should not return an url when there is no dashboard url', () => { - const url = formatClusterLink({ object: {}, kind: 'foo' }); - expect(url).toBeUndefined(); - }); - it('should return an url even when there is no object', () => { - const url = formatClusterLink({ - dashboardUrl: 'https://k8s.foo.com', - object: undefined, - kind: 'foo', - }); - expect(url).toBe('https://k8s.foo.com'); - }); - it('should throw when the app is not recognized', () => { - expect(() => - formatClusterLink({ - dashboardUrl: 'https://k8s.foo.com', - dashboardApp: 'unknownapp', - object: { - metadata: { - name: 'foobar', - namespace: 'bar', - }, - }, - kind: 'Deployment', - }), - ).toThrow("Could not find Kubernetes dashboard app named 'unknownapp'"); - }); - - describe('default app', () => { - it('should return an url on the deployment', () => { - const url = formatClusterLink({ - dashboardUrl: 'https://k8s.foo.com/', - object: { - metadata: { - name: 'foobar', - namespace: 'bar', - }, - }, - kind: 'Deployment', - }); - expect(url).toBe( - 'https://k8s.foo.com/#/deployment/bar/foobar?namespace=bar', - ); - }); - it('should return an url on the service', () => { - const url = formatClusterLink({ - dashboardUrl: 'https://k8s.foo.com/', - object: { - metadata: { - name: 'foobar', - namespace: 'bar', - }, - }, - kind: 'Service', - }); - expect(url).toBe( - 'https://k8s.foo.com/#/service/bar/foobar?namespace=bar', - ); - }); - }); - - describe('standard app', () => { - it('should return an url on the deployment', () => { - const url = formatClusterLink({ - dashboardUrl: 'https://k8s.foo.com/', - dashboardApp: 'standard', - object: { - metadata: { - name: 'foobar', - namespace: 'bar', - }, - }, - kind: 'Deployment', - }); - expect(url).toBe( - 'https://k8s.foo.com/#/deployment/bar/foobar?namespace=bar', - ); - }); - it('should return an url on the service', () => { - const url = formatClusterLink({ - dashboardUrl: 'https://k8s.foo.com/', - dashboardApp: 'standard', - object: { - metadata: { - name: 'foobar', - namespace: 'bar', - }, - }, - kind: 'Service', - }); - expect(url).toBe( - 'https://k8s.foo.com/#/service/bar/foobar?namespace=bar', - ); - }); - }); - describe('GKE app', () => { - it('should return an url on the deployment', () => { - const url = formatClusterLink({ - dashboardApp: 'gke', - dashboardParameters: { - projectId: 'foobar-333614', - region: 'us-east1-c', - clusterName: 'cluster-1', - }, - object: { - metadata: { - name: 'foobar', - namespace: 'bar', - }, - }, - kind: 'Deployment', - }); - expect(url).toBe( - 'https://console.cloud.google.com/kubernetes/deployment/us-east1-c/cluster-1/bar/foobar/overview?project=foobar-333614', - ); - }); - it('should return an url on the service', () => { - const url = formatClusterLink({ - dashboardApp: 'gke', - dashboardParameters: { - projectId: 'foobar-333614', - region: 'us-east1-c', - clusterName: 'cluster-1', - }, - object: { - metadata: { - name: 'foobar', - namespace: 'bar', - }, - }, - kind: 'Service', - }); - expect(url).toBe( - 'https://console.cloud.google.com/kubernetes/service/us-east1-c/cluster-1/bar/foobar/overview?project=foobar-333614', - ); - }); - }); - }); -}); diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatClusterLink.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatClusterLink.ts deleted file mode 100644 index 8f7e43a121..0000000000 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatClusterLink.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { JsonObject } from '@backstage/types'; -import { defaultFormatterName, clusterLinksFormatters } from './formatters'; - -/** - * @public - */ -export type FormatClusterLinkOptions = { - dashboardUrl?: string; - dashboardApp?: string; - dashboardParameters?: JsonObject; - object: any; - kind: string; -}; - -/** - * @public - */ -export function formatClusterLink(options: FormatClusterLinkOptions) { - if (!options.dashboardUrl && !options.dashboardParameters) { - return undefined; - } - if (options.dashboardUrl && !options.object) { - return options.dashboardUrl; - } - const app = options.dashboardApp || defaultFormatterName; - const formatter = clusterLinksFormatters[app]; - if (!formatter) { - throw new Error(`Could not find Kubernetes dashboard app named '${app}'`); - } - const url = formatter({ - dashboardUrl: options.dashboardUrl - ? new URL(options.dashboardUrl) - : undefined, - dashboardParameters: options.dashboardParameters, - object: options.object, - kind: options.kind, - }); - return url.toString(); -} diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/aks.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/aks.ts deleted file mode 100644 index 71fffb00e6..0000000000 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/aks.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { ClusterLinksFormatterOptions } from '../../../types/types'; - -const basePath = - 'https://portal.azure.com/#blade/Microsoft_Azure_ContainerService/AksK8ResourceMenuBlade/overview-Deployment/aksClusterId'; - -const requiredParams = ['subscriptionId', 'resourceGroup', 'clusterName']; - -export function aksFormatter(options: ClusterLinksFormatterOptions): URL { - if (!options.dashboardParameters) { - throw new Error('AKS dashboard requires a dashboardParameters option'); - } - const args = options.dashboardParameters; - for (const param of requiredParams) { - if (typeof args[param] !== 'string') { - throw new Error( - `AKS dashboard requires a "${param}" of type string in the dashboardParameters option`, - ); - } - } - - const path = `/subscriptions/${args.subscriptionId}/resourceGroups/${args.resourceGroup}/providers/Microsoft.ContainerService/managedClusters/${args.clusterName}`; - - const { name, namespace, uid } = options.object.metadata; - const { selector } = options.object.spec; - const params = { - kind: options.kind, - metadata: { name, namespace, uid }, - spec: { - selector, - }, - }; - - return new URL( - `${basePath}/${encodeURIComponent(path)}/resource/${encodeURIComponent( - JSON.stringify(params), - )}`, - ); -} diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/gke.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/gke.ts deleted file mode 100644 index 957032e6e2..0000000000 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/gke.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { ClusterLinksFormatterOptions } from '../../../types/types'; - -const kindMappings: Record = { - deployment: 'deployment', - pod: 'pod', - ingress: 'ingress', - service: 'service', - horizontalpodautoscaler: 'deployment', -}; - -export function gkeFormatter(options: ClusterLinksFormatterOptions): URL { - if (!options.dashboardParameters) { - throw new Error('GKE dashboard requires a dashboardParameters option'); - } - const args = options.dashboardParameters; - if (typeof args.projectId !== 'string') { - throw new Error( - 'GKE dashboard requires a "projectId" of type string in the dashboardParameters option', - ); - } - if (typeof args.region !== 'string') { - throw new Error( - 'GKE dashboard requires a "region" of type string in the dashboardParameters option', - ); - } - if (typeof args.clusterName !== 'string') { - throw new Error( - 'GKE dashboard requires a "clusterName" of type string in the dashboardParameters option', - ); - } - const basePath = new URL('https://console.cloud.google.com/'); - const region = encodeURIComponent(args.region); - const clusterName = encodeURIComponent(args.clusterName); - const name = encodeURIComponent(options.object.metadata?.name ?? ''); - const namespace = encodeURIComponent( - options.object.metadata?.namespace ?? '', - ); - const validKind = kindMappings[options.kind.toLocaleLowerCase('en-US')]; - let path = ''; - if (namespace && name && validKind) { - const kindsWithDetails = ['ingress', 'pod']; - const landingPage = kindsWithDetails.includes(validKind) - ? 'details' - : 'overview'; - path = `kubernetes/${validKind}/${region}/${clusterName}/${namespace}/${name}/${landingPage}`; - } else { - path = `kubernetes/clusters/details/${region}/${clusterName}/details`; - } - const result = new URL(path, basePath); - result.searchParams.set('project', args.projectId); - return result; -} diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/index.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/index.ts deleted file mode 100644 index b75e45cc7f..0000000000 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { ClusterLinksFormatter } from '../../../types/types'; -import { standardFormatter } from './standard'; -import { rancherFormatter } from './rancher'; -import { openshiftFormatter } from './openshift'; -import { aksFormatter } from './aks'; -import { eksFormatter } from './eks'; -import { gkeFormatter } from './gke'; - -/** - * @public - */ -export const clusterLinksFormatters: Record = { - standard: standardFormatter, - rancher: rancherFormatter, - openshift: openshiftFormatter, - aks: aksFormatter, - eks: eksFormatter, - gke: gkeFormatter, -}; -export const defaultFormatterName = 'standard'; diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/openshift.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/openshift.ts deleted file mode 100644 index c5b7313061..0000000000 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/openshift.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { ClusterLinksFormatterOptions } from '../../../types/types'; - -const kindMappings: Record = { - deployment: 'deployments', - ingress: 'ingresses', - service: 'services', - horizontalpodautoscaler: 'horizontalpodautoscalers', - persistentvolume: 'persistentvolumes', -}; - -export function openshiftFormatter(options: ClusterLinksFormatterOptions): URL { - if (!options.dashboardUrl) { - throw new Error('OpenShift dashboard requires a dashboardUrl option'); - } - const basePath = new URL(options.dashboardUrl.href); - const name = encodeURIComponent(options.object.metadata?.name ?? ''); - const namespace = encodeURIComponent( - options.object.metadata?.namespace ?? '', - ); - const validKind = kindMappings[options.kind.toLocaleLowerCase('en-US')]; - if (!basePath.pathname.endsWith('/')) { - // a dashboard url with a path should end with a slash otherwise - // the new combined URL will replace the last segment with the appended path! - // https://foobar.com/abc/def + k8s/cluster/projects/test --> https://foobar.com/abc/k8s/cluster/projects/test - // https://foobar.com/abc/def/ + k8s/cluster/projects/test --> https://foobar.com/abc/def/k8s/cluster/projects/test - basePath.pathname += '/'; - } - let path = ''; - if (namespace) { - if (name && validKind) { - path = `k8s/ns/${namespace}/${validKind}/${name}`; - } else { - path = `k8s/cluster/projects/${namespace}`; - } - } else if (validKind) { - path = `k8s/cluster/${validKind}`; - if (name) { - path += `/${name}`; - } - } - return new URL(path, basePath); -} diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/rancher.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/rancher.ts deleted file mode 100644 index 6c72730181..0000000000 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/rancher.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { ClusterLinksFormatterOptions } from '../../../types/types'; - -const kindMappings: Record = { - deployment: 'apps.deployment', - ingress: 'networking.k8s.io.ingress', - service: 'service', - horizontalpodautoscaler: 'autoscaling.horizontalpodautoscaler', -}; - -export function rancherFormatter(options: ClusterLinksFormatterOptions): URL { - if (!options.dashboardUrl) { - throw new Error('Rancher dashboard requires a dashboardUrl option'); - } - const basePath = new URL(options.dashboardUrl.href); - const name = encodeURIComponent(options.object.metadata?.name ?? ''); - const namespace = encodeURIComponent( - options.object.metadata?.namespace ?? '', - ); - const validKind = kindMappings[options.kind.toLocaleLowerCase('en-US')]; - if (!basePath.pathname.endsWith('/')) { - // a dashboard url with a path should end with a slash otherwise - // the new combined URL will replace the last segment with the appended path! - // https://foobar.com/abc/def + explorer/service/test --> https://foobar.com/abc/explorer/service/test - // https://foobar.com/abc/def/ + explorer/service/test --> https://foobar.com/abc/def/explorer/service/test - basePath.pathname += '/'; - } - let path = ''; - if (validKind && name && namespace) { - path = `explorer/${validKind}/${namespace}/${name}`; - } else if (namespace) { - path = 'explorer/workload'; - } - return new URL(path, basePath); -} diff --git a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/standard.ts b/plugins/kubernetes-react/src/utils/clusterLinks/formatters/standard.ts deleted file mode 100644 index e26adf98e6..0000000000 --- a/plugins/kubernetes-react/src/utils/clusterLinks/formatters/standard.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { ClusterLinksFormatterOptions } from '../../../types/types'; - -const kindMappings: Record = { - deployment: 'deployment', - pod: 'pod', - ingress: 'ingress', - service: 'service', - horizontalpodautoscaler: 'deployment', - statefulset: 'statefulset', -}; - -export function standardFormatter(options: ClusterLinksFormatterOptions) { - if (!options.dashboardUrl) { - throw new Error('standard dashboard requires a dashboardUrl option'); - } - const result = new URL(options.dashboardUrl.href); - const name = encodeURIComponent(options.object.metadata?.name ?? ''); - const namespace = encodeURIComponent( - options.object.metadata?.namespace ?? '', - ); - const validKind = kindMappings[options.kind.toLocaleLowerCase('en-US')]; - if (!result.pathname.endsWith('/')) { - result.pathname += '/'; - } - if (validKind && name && namespace) { - result.hash = `/${validKind}/${namespace}/${name}`; - } else if (namespace) { - result.hash = '/workloads'; - } - if (namespace) { - // Note that Angular SPA requires a hash and the query parameter should be part of it - result.hash += `?namespace=${namespace}`; - } - return result; -} diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 1e10e287d3..f637aa6f21 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,59 @@ # @backstage/plugin-kubernetes +## 0.11.3-next.2 + +### Patch Changes + +- 899d71a: Change `formatClusterLink` to be an API and make it async for further customization possibilities. + + **BREAKING** + If you have a custom k8s page and used `formatClusterLink` directly, you need to migrate to new `kubernetesClusterLinkFormatterApiRef` + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-kubernetes-react@0.2.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + +## 0.11.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-kubernetes-common@0.7.2-next.1 + - @backstage/plugin-kubernetes-react@0.1.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + +## 0.11.3-next.0 + +### Patch Changes + +- 706fc3a7e1: Updated dependency `@kubernetes/client-node` to `0.20.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-kubernetes-react@0.1.2-next.0 + - @backstage/plugin-kubernetes-common@0.7.2-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.11.1 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 37dde1127e..d1cd6d9f2b 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes", "description": "A Backstage plugin that integrates towards Kubernetes", - "version": "0.11.1", + "version": "0.11.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -46,7 +46,7 @@ "@backstage/types": "workspace:^", "@kubernetes-models/apimachinery": "^1.1.0", "@kubernetes-models/base": "^4.0.1", - "@kubernetes/client-node": "0.19.0", + "@kubernetes/client-node": "0.20.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", diff --git a/plugins/kubernetes/src/plugin.ts b/plugins/kubernetes/src/plugin.ts index ac55dbbf23..c479f99aa0 100644 --- a/plugins/kubernetes/src/plugin.ts +++ b/plugins/kubernetes/src/plugin.ts @@ -20,6 +20,10 @@ import { kubernetesAuthProvidersApiRef, KubernetesAuthProviders, KubernetesProxyClient, + kubernetesClusterLinkFormatterApiRef, + getDefaultFormatters, + KubernetesClusterLinkFormatter, + DEFAULT_FORMATTER_NAME, } from '@backstage/plugin-kubernetes-react'; import { createApiFactory, @@ -97,6 +101,17 @@ export const kubernetesPlugin = createPlugin({ }); }, }), + createApiFactory({ + api: kubernetesClusterLinkFormatterApiRef, + deps: {}, + factory: deps => { + const formatters = getDefaultFormatters(deps); + return new KubernetesClusterLinkFormatter({ + formatters, + defaultFormatterName: DEFAULT_FORMATTER_NAME, + }); + }, + }), ], routes: { entityContent: rootCatalogKubernetesRouteRef, diff --git a/plugins/lighthouse-backend/CHANGELOG.md b/plugins/lighthouse-backend/CHANGELOG.md index eab0f0a228..4eb0649118 100644 --- a/plugins/lighthouse-backend/CHANGELOG.md +++ b/plugins/lighthouse-backend/CHANGELOG.md @@ -1,5 +1,54 @@ # @backstage/plugin-lighthouse-backend +## 0.4.0-next.2 + +### Minor Changes + +- 7f0dbfd: Fixed crashes faced with custom schedule configuration. The configuration schema has been update to leverage the TaskScheduleDefinition interface. It is highly recommended to move the `lighthouse.shedule` and `lighthouse.timeout` respectively to `lighthouse.schedule.frequency` and `lighthouse.schedule.timeout`. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4 + +## 0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-lighthouse-common@0.1.4 + +## 0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4 + ## 0.3.4 ### Patch Changes diff --git a/plugins/lighthouse-backend/README.md b/plugins/lighthouse-backend/README.md index 28845d3c73..687467f1d5 100644 --- a/plugins/lighthouse-backend/README.md +++ b/plugins/lighthouse-backend/README.md @@ -19,13 +19,19 @@ import { PluginEnvironment } from '../types'; import { CatalogClient } from '@backstage/catalog-client'; export default async function createPlugin(env: PluginEnvironment) { - const { logger, scheduler, config } = env; + const { logger, scheduler, config, tokenManager } = env; const catalogClient = new CatalogClient({ discoveryApi: env.discovery, }); - await createScheduler({ logger, scheduler, config, catalogClient }); + await createScheduler({ + logger, + scheduler, + config, + catalogClient, + tokenManager, + }); } ``` @@ -80,5 +86,8 @@ You can define how often and when the scheduler should run the audits: ```yaml lighthouse: schedule: - days: 1 + frequency: + hours: 12 # Default: 1 day + timeout: + minutes: 30 # Default: 10 minutes ``` diff --git a/plugins/lighthouse-backend/config.d.ts b/plugins/lighthouse-backend/config.d.ts new file mode 100644 index 0000000000..2d49f188b6 --- /dev/null +++ b/plugins/lighthouse-backend/config.d.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { TaskScheduleDefinitionConfig } from '@backstage/backend-tasks'; +import { HumanDuration } from '@backstage/types'; + +export interface Config { + /** + * Configuration options for the Lighthouse backend plugin. + */ + lighthouse?: { + /** + * Schedule of the audit + */ + schedule?: HumanDuration | TaskScheduleDefinitionConfig; + }; +} diff --git a/plugins/lighthouse-backend/package.json b/plugins/lighthouse-backend/package.json index 1be19e1252..3e1f608fa2 100644 --- a/plugins/lighthouse-backend/package.json +++ b/plugins/lighthouse-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse-backend", "description": "Backend functionalities for lighthouse", - "version": "0.3.4", + "version": "0.4.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -24,8 +24,10 @@ "lighthouse" ], "files": [ - "dist" + "dist", + "config.d.ts" ], + "configSchema": "config.d.ts", "scripts": { "build": "backstage-cli package build", "lint": "backstage-cli package lint", diff --git a/plugins/lighthouse-backend/src/config.ts b/plugins/lighthouse-backend/src/config.ts index bea1c35661..736a4e569d 100644 --- a/plugins/lighthouse-backend/src/config.ts +++ b/plugins/lighthouse-backend/src/config.ts @@ -13,56 +13,66 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { LoggerService } from '@backstage/backend-plugin-api'; +import { + TaskScheduleDefinition, + readTaskScheduleDefinitionFromConfig, +} from '@backstage/backend-tasks'; +import { Config, readDurationFromConfig } from '@backstage/config'; +import { HumanDuration } from '@backstage/types'; -import { Config } from '@backstage/config'; -import { HumanDuration as HumanDuration } from '@backstage/types'; - -export interface LighthouseAuditScheduleConfig { - schedule: HumanDuration; - timeout: HumanDuration; - auditDetail: HumanDuration; -} - -/** @public */ -export type LighthouseAuditSchedule = { - getSchedule: () => HumanDuration; - getTimeout: () => HumanDuration; +type Options = { + logger: LoggerService; }; /** @public */ -export class LighthouseAuditScheduleImpl implements LighthouseAuditSchedule { - static fromConfig(config: Config) { - const lighthouse = config.getOptionalConfig('lighthouse'); +export class LighthouseAuditScheduleImpl implements TaskScheduleDefinition { + /** + * Looks at the `lighthouse.schedule` section in the application configuration + * and returns a TaskScheduleDefinition. + * Defaults to `{ frequency: { days: 1 }, timeout: {}, initialDelay: { minutes; 15 } }` + * + * @returns a TaskScheduleDefinition + */ + static fromConfig(config: Config, options: Options): TaskScheduleDefinition { + const { logger } = options; - let schedule: HumanDuration = { days: 1 }; - let timeout: HumanDuration = {}; + let lighthouse: TaskScheduleDefinition = { + frequency: { days: 1 }, + timeout: { minutes: 10 }, + initialDelay: { minutes: 15 }, + }; - if (lighthouse) { - const scheduleConfig = lighthouse.getOptionalConfig('schedule'); - const timeoutConfig = lighthouse.getOptionalConfig('timeout'); + if (config.has('lighthouse.schedule.frequency')) { + lighthouse = readTaskScheduleDefinitionFromConfig( + config.getConfig('lighthouse.schedule'), + ); + } else if (config.has('lighthouse.schedule')) { + logger.warn( + `[Deprecation] Please migrate the schedule configuration to 'lighthouse.schedule.frequency'`, + ); - if (scheduleConfig) { - schedule = scheduleConfig as HumanDuration; - } - - if (timeoutConfig) { - timeout = timeoutConfig as HumanDuration; - } + lighthouse.frequency = readDurationFromConfig( + config.getConfig('lighthouse.schedule'), + ); } - return new LighthouseAuditScheduleImpl(schedule, timeout); + if (config.has('lighthouse.timeout')) { + logger.warn( + `[Deprecation] Please migrate the timeout configuration to 'lighthouse.schedule.timeout'`, + ); + + lighthouse.timeout = readDurationFromConfig( + config.getConfig('lighthouse.timeout'), + ); + } + + return lighthouse; } constructor( - private schedule: HumanDuration, - private timeout: HumanDuration, + public frequency: HumanDuration, + public timeout: HumanDuration, + public initialDelay: HumanDuration, ) {} - - getSchedule(): HumanDuration { - return this.schedule; - } - - getTimeout(): HumanDuration { - return this.timeout; - } } diff --git a/plugins/lighthouse-backend/src/service/createScheduler.ts b/plugins/lighthouse-backend/src/service/createScheduler.ts index 498e459a09..45a3e88149 100644 --- a/plugins/lighthouse-backend/src/service/createScheduler.ts +++ b/plugins/lighthouse-backend/src/service/createScheduler.ts @@ -39,7 +39,9 @@ export async function createScheduler( const { logger, scheduler, catalogClient, config, tokenManager } = options; const lighthouseApi = LighthouseRestApi.fromConfig(config); - const lighthouseAuditConfig = LighthouseAuditScheduleImpl.fromConfig(config); + const lighthouseAuditConfig = LighthouseAuditScheduleImpl.fromConfig(config, { + logger, + }); const formFactorToScreenEmulationMap = { // the default is mobile, so no need to override mobile: undefined, @@ -56,16 +58,16 @@ export async function createScheduler( logger.info( `Running with Scheduler Config ${JSON.stringify( - lighthouseAuditConfig.getSchedule(), - )} and timeout ${JSON.stringify(lighthouseAuditConfig.getTimeout())}`, + lighthouseAuditConfig.frequency, + )} and timeout ${JSON.stringify(lighthouseAuditConfig.timeout)}`, ); if (scheduler) { await scheduler.scheduleTask({ id: 'lighthouse_audit', - frequency: lighthouseAuditConfig.getSchedule(), - timeout: lighthouseAuditConfig.getTimeout(), - initialDelay: { minutes: 15 }, + frequency: lighthouseAuditConfig.frequency, + timeout: lighthouseAuditConfig.timeout, + initialDelay: lighthouseAuditConfig.initialDelay, fn: async () => { const filter: Record = { kind: 'Component', diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index 511426709f..aaf69f195f 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-lighthouse +## 0.4.13-next.2 + +### Patch Changes + +- ffbf656: Updated README +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-lighthouse-common@0.1.4 + +## 0.4.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-lighthouse-common@0.1.4 + +## 0.4.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4 + ## 0.4.11 ### Patch Changes diff --git a/plugins/lighthouse/README.md b/plugins/lighthouse/README.md index 1d2385e4c4..e834ad39c1 100644 --- a/plugins/lighthouse/README.md +++ b/plugins/lighthouse/README.md @@ -47,6 +47,10 @@ const routes = ( Then configure the `lighthouse-audit-service` URL in your [`app-config.yaml`](https://github.com/backstage/backstage/blob/master/app-config.yaml). ```yaml +backend: + csp: + frame-src: + - http://your-service-url lighthouse: baseUrl: http://your-service-url ``` diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index a54573df7c..ec15c89b22 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse", "description": "A Backstage plugin that integrates towards Lighthouse", - "version": "0.4.11", + "version": "0.4.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/linguist-backend/CHANGELOG.md b/plugins/linguist-backend/CHANGELOG.md index 1b7606681f..c983efe3ac 100644 --- a/plugins/linguist-backend/CHANGELOG.md +++ b/plugins/linguist-backend/CHANGELOG.md @@ -1,5 +1,56 @@ # @backstage/plugin-linguist-backend +## 0.5.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-linguist-common@0.1.2 + +## 0.5.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-linguist-common@0.1.2 + +## 0.5.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-linguist-common@0.1.2 + ## 0.5.4 ### Patch Changes diff --git a/plugins/linguist-backend/package.json b/plugins/linguist-backend/package.json index c30c666566..ed22dd5490 100644 --- a/plugins/linguist-backend/package.json +++ b/plugins/linguist-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-linguist-backend", - "version": "0.5.4", + "version": "0.5.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/linguist/CHANGELOG.md b/plugins/linguist/CHANGELOG.md index 9cbf383dcb..f57f43ac2e 100644 --- a/plugins/linguist/CHANGELOG.md +++ b/plugins/linguist/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-linguist +## 0.1.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-linguist-common@0.1.2 + +## 0.1.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-linguist-common@0.1.2 + +## 0.1.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-linguist-common@0.1.2 + ## 0.1.11 ### Patch Changes diff --git a/plugins/linguist/package.json b/plugins/linguist/package.json index de5c5139f6..102b9bff18 100644 --- a/plugins/linguist/package.json +++ b/plugins/linguist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-linguist", - "version": "0.1.11", + "version": "0.1.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/microsoft-calendar/CHANGELOG.md b/plugins/microsoft-calendar/CHANGELOG.md index 1ba5917853..e6bad4915b 100644 --- a/plugins/microsoft-calendar/CHANGELOG.md +++ b/plugins/microsoft-calendar/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-microsoft-calendar +## 0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/errors@1.2.3 + ## 0.1.9 ### Patch Changes diff --git a/plugins/microsoft-calendar/package.json b/plugins/microsoft-calendar/package.json index 547c5249ef..201f8597a7 100644 --- a/plugins/microsoft-calendar/package.json +++ b/plugins/microsoft-calendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-microsoft-calendar", - "version": "0.1.9", + "version": "0.1.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/newrelic-dashboard/CHANGELOG.md b/plugins/newrelic-dashboard/CHANGELOG.md index 16b03e444e..02f911e9c2 100644 --- a/plugins/newrelic-dashboard/CHANGELOG.md +++ b/plugins/newrelic-dashboard/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-newrelic-dashboard +## 0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## 0.3.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.3.1 ### Patch Changes diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index 1d9cba9cf4..fdb6bfd773 100644 --- a/plugins/newrelic-dashboard/package.json +++ b/plugins/newrelic-dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-newrelic-dashboard", - "version": "0.3.1", + "version": "0.3.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/newrelic/CHANGELOG.md b/plugins/newrelic/CHANGELOG.md index ee2cffa240..a383872f77 100644 --- a/plugins/newrelic/CHANGELOG.md +++ b/plugins/newrelic/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-newrelic +## 0.3.43-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.3.43-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## 0.3.43-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + ## 0.3.42 ### Patch Changes diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 8e2c6d1bb1..5c9ecef1e8 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-newrelic", "description": "A Backstage plugin that integrates towards New Relic", - "version": "0.3.42", + "version": "0.3.43-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/nomad-backend/CHANGELOG.md b/plugins/nomad-backend/CHANGELOG.md index c5cfaadf82..b0f600672e 100644 --- a/plugins/nomad-backend/CHANGELOG.md +++ b/plugins/nomad-backend/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-nomad-backend +## 0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## 0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## 0.1.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.1.9 ### Patch Changes diff --git a/plugins/nomad-backend/package.json b/plugins/nomad-backend/package.json index 2c1a5a8cc0..5f109fd142 100644 --- a/plugins/nomad-backend/package.json +++ b/plugins/nomad-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-nomad-backend", - "version": "0.1.9", + "version": "0.1.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/nomad/CHANGELOG.md b/plugins/nomad/CHANGELOG.md index 3f1a018e7a..4626f99381 100644 --- a/plugins/nomad/CHANGELOG.md +++ b/plugins/nomad/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-nomad +## 0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + +## 0.1.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + ## 0.1.7 ### Patch Changes diff --git a/plugins/nomad/package.json b/plugins/nomad/package.json index 4d699dfa63..a29a41ef54 100644 --- a/plugins/nomad/package.json +++ b/plugins/nomad/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-nomad", - "version": "0.1.7", + "version": "0.1.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/octopus-deploy/CHANGELOG.md b/plugins/octopus-deploy/CHANGELOG.md index 80e96f7051..dcd86b5017 100644 --- a/plugins/octopus-deploy/CHANGELOG.md +++ b/plugins/octopus-deploy/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-octopus-deploy +## 0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.2.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.2.8 ### Patch Changes diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index 2831821446..4fb1531c81 100644 --- a/plugins/octopus-deploy/package.json +++ b/plugins/octopus-deploy/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-octopus-deploy", - "version": "0.2.8", + "version": "0.2.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/opencost/CHANGELOG.md b/plugins/opencost/CHANGELOG.md index fdf1b1e404..89c3196aa4 100644 --- a/plugins/opencost/CHANGELOG.md +++ b/plugins/opencost/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-opencost +## 0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## 0.2.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + ## 0.2.2 ### Patch Changes diff --git a/plugins/opencost/package.json b/plugins/opencost/package.json index 3d3664e9ce..661bbe7d30 100644 --- a/plugins/opencost/package.json +++ b/plugins/opencost/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-opencost", - "version": "0.2.2", + "version": "0.2.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/org-react/CHANGELOG.md b/plugins/org-react/CHANGELOG.md index 6b65c66f57..46a35be48f 100644 --- a/plugins/org-react/CHANGELOG.md +++ b/plugins/org-react/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-org-react +## 0.1.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.1.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + ## 0.1.15 ### Patch Changes diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index f7d9d84851..5dcd90f16c 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org-react", - "version": "0.1.15", + "version": "0.1.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index ab4ee63f0b..7e52a97fbd 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-org +## 0.6.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.6.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.6.18-next.0 + +### Patch Changes + +- 3a65d9c4d7: Support member list scrollable when parent has specified height +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.6.16 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index f80fc43503..3e006fb958 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-org", "description": "A Backstage plugin that helps you create entity pages for your organization", - "version": "0.6.16", + "version": "0.6.18-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx index 6613aa5b6a..cd5801ac71 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx @@ -31,7 +31,7 @@ import { mockedCatalogApiSupportingGroups, } from '../../../../__testUtils__/catalogMocks'; import { permissionApiRef } from '@backstage/plugin-permission-react'; -import { EntityLayout } from '@backstage/plugin-catalog'; +import { EntityLayout, catalogPlugin } from '@backstage/plugin-catalog'; import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { Observable } from '@backstage/types'; @@ -63,6 +63,8 @@ const mockedStarredEntitiesApi: Partial = { }, }; +const rootRouteRef = catalogPlugin.routes.catalogIndex; + describe('MemberTab Test', () => { const groupEntity: GroupEntity = { apiVersion: 'backstage.io/v1alpha1', @@ -122,6 +124,7 @@ describe('MemberTab Test', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -151,6 +154,7 @@ describe('MemberTab Test', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -179,6 +183,7 @@ describe('MemberTab Test', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -206,6 +211,7 @@ describe('MemberTab Test', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -231,6 +237,7 @@ describe('MemberTab Test', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -265,6 +272,7 @@ describe('MemberTab Test', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); @@ -299,6 +307,7 @@ describe('MemberTab Test', () => { { mountedRoutes: { '/catalog/:namespace/:kind/:name': entityRouteRef, + '/catalog': rootRouteRef, }, }, ); diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx index 3716af5522..701feb0b73 100644 --- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx +++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx @@ -119,6 +119,15 @@ const MemberComponent = (props: { member: UserEntity }) => { ); }; +const useListStyles = makeStyles(() => ({ + root: { + height: '100%', + }, + cardContent: { + overflow: 'auto', + }, +})); + /** @public */ export const MembersListCard = (props: { memberDisplayTitle?: string; @@ -130,6 +139,7 @@ export const MembersListCard = (props: { pageSize = 50, showAggregateMembersToggle, } = props; + const classes = useListStyles(); const { entity: groupEntity } = useEntity(); const { @@ -210,13 +220,15 @@ export const MembersListCard = (props: { ); return ( - + {showAggregateMembersToggle && ( <> diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index 41e9ffb4c3..239b7cc44d 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-pagerduty +## 0.7.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-home-react@0.1.6-next.2 + +## 0.7.0-next.1 + +### Minor Changes + +- 5fca16fdf6: This package has been deprecated, consider using [@pagerduty/backstage-plugin](https://github.com/pagerduty/backstage-plugin) instead. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-home-react@0.1.6-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.6.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-home-react@0.1.6-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.6.7 ### Patch Changes diff --git a/plugins/pagerduty/README.md b/plugins/pagerduty/README.md index bf748439c9..c1079004e3 100644 --- a/plugins/pagerduty/README.md +++ b/plugins/pagerduty/README.md @@ -1,217 +1,3 @@ # PagerDuty + Backstage Integration Benefits -- Display relevant PagerDuty information about an entity within Backstage, such as the escalation policy, if there are any active incidents, and recent changes -- Trigger an incident to the currently on-call responder(s) for a service - -## How it Works - -- The Backstage PagerDuty plugin allows PagerDuty information about a Backstage entity to be displayed within Backstage. This includes active incidents, recent change events, as well as the current on-call responders' names, email addresses, and links to their profiles in PagerDuty. -- Incidents can be manually triggered via the plugin with a user-provided description, which will in turn notify the current on-call responders (Alternatively, the plugin can be configured with an optional `readOnly` property to suppress the ability to trigger incidents from the plugin). - - _Note: This feature is only available when providing the `pagerduty.com/integration-key` annotation_ -- Change events will be displayed in a separate tab. If the change event payload has additional links the first link only will be rendered. - -## Requirements - -- Setup of the PagerDuty plugin for Backstage requires a PagerDuty Admin role in order to generate the necessary authorizations, such as the API token. If you do not have this role, please reach out to an Admin or Account Owner within your organization to request configuration of this plugin. - -## Feature Overview - -### View any open incidents - -![PagerDuty plugin showing no incidents and the on-call rotation](doc/pd1.png) - -### Email link, and view contact information for staff on call - -![PagerDuty plugin showing on-call rotation contact information](doc/pd2.png) - -### Trigger an incident for a service - -![PagerDuty plugin popup modal for creating an incident](doc/pd3.png) - -![PagerDuty plugin showing an active incident](doc/pd4.png) - -## Support - -If you need help with this plugin, please reach out on the [Backstage Discord server](https://discord.gg/backstage-687207715902193673). - -## Integration Walk-through - -### In PagerDuty - -#### Integrating With a PagerDuty Service - -1. From the **Configuration** menu, select **Services**. -2. There are two ways to add an integration to a service: - - **If you are adding your integration to an existing service**: Click the **name** of the service you want to add the integration to. Then, select the **Integrations** tab and click the **New Integration** button. - - **If you are creating a new service for your integration**: Please read the documentation in section [Configuring Services and Integrations](https://support.pagerduty.com/docs/services-and-integrations#section-configuring-services-and-integrations) and follow the steps outlined in the [Create a New Service](https://support.pagerduty.com/docs/services-and-integrations#section-create-a-new-service) section, selecting **Backstage** as the **Integration Type** in step 4. Continue with the **In Backstage** section (below) once you have finished these steps. -3. Enter an **Integration Name** in the format `monitoring-tool-service-name` (e.g. `Backstage-Shopping-Cart`) and select **Backstage** from the Integration Type menu. -4. Click the **Add Integration** button to save your new integration. You will be redirected to the Integrations tab for your service. -5. An **Integration Key** will be generated on this screen. Keep this key saved in a safe place, as it will be used when you configure the integration with **Backstage** in the next section. - ![](https://pdpartner.s3.amazonaws.com/ig-template-copy-integration-key.png) - -### In Backstage - -#### Install the plugin - -The file paths mentioned in the following steps are relative to your app's root directory — for example, the directory created by following the [Getting Started](https://backstage.io/docs/getting-started/) guide and creating your app with `npx @backstage/create-app`. - -First, install the PagerDuty plugin via a CLI: - -```bash -# From your Backstage root directory -yarn add --cwd packages/app @backstage/plugin-pagerduty -``` - -Next, add the plugin to `EntityPage.tsx` in `packages/app/src/components/catalog` by adding the following code snippets. - -Add the following imports to the top of the file: - -```ts -import { - isPluginApplicableToEntity as isPagerDutyAvailable, - EntityPagerDutyCard, -} from '@backstage/plugin-pagerduty'; -``` - -Find `const overviewContent` in `EntityPage.tsx`, and add the following snippet inside the outermost `Grid` defined there, just before the closing `` tag: - -```ts - - - - - - - -``` - -When you're done, the `overviewContent` definition should look something like this: - -```ts -const overviewContent = ( - - ... - - - - - - - - -); -``` - -#### Configure the plugin - -First, [annotate](https://backstage.io/docs/features/software-catalog/descriptor-format#annotations-optional) the appropriate entity with the PagerDuty integration key in its `.yaml` configuration file: - -```yaml -annotations: - pagerduty.com/integration-key: [INTEGRATION_KEY] -``` - -#### The homepage component - -You may also add the component to the homepage of Backstage. Edit the `HomePage.tsx` file, import `PagerDutyHomepageCard` and add it to the home page. e.g. - -```typescript jsx -... -export const homePage = ( - - ... - - - ... - - - - -); -``` - -Next, provide the [API token](https://support.pagerduty.com/docs/generating-api-keys#generating-a-general-access-rest-api-key) that the client will use to make requests to the [PagerDuty API](https://developer.pagerduty.com/docs/rest-api-v2/rest-api/). - -Add the proxy configuration in `app-config.yaml`: - -```yaml -proxy: - ... - '/pagerduty': - target: https://api.pagerduty.com - headers: - Authorization: Token token=${PAGERDUTY_TOKEN} -``` - -Then, start the backend, passing the PagerDuty API token as an environment variable: - -```bash -$ PAGERDUTY_TOKEN='' yarn start -``` - -This will proxy the request by adding an `Authorization` header with the provided token. - -#### Optional configuration - -##### Annotating with Service ID - -If you want to integrate a PagerDuty service with Backstage but don't want to use an integration key, you can also [annotate](https://backstage.io/docs/features/software-catalog/descriptor-format#annotations-optional) the appropriate entity with a PagerDuty Service ID instead - -```yaml -annotations: - pagerduty.com/service-id: [SERVICE_ID] -``` - -This service ID can be found by navigating to a Service within PagerDuty and pulling the ID value out of the URL. - -1. From the **Configuration** menu within PagerDuty, select **Services**. -2. Click the **name** of the service you want to represent for your Entity. - -Your browser URL should now be located at `https://pagerduty.com/service-directory/[SERVICE_ID]`. - -_Note: When annotating with `pagerduty.com/service-id`, the feature to Create Incidents is not currently supported_ - -##### Custom Events URL - -If you want to override the default URL used for events, you can add it to `app-config.yaml`: - -```yaml -pagerDuty: - eventsBaseUrl: 'https://events.pagerduty.com/v2' -``` - -To suppress the rendering of the actionable incident-creation button, the `PagerDutyCard` can also be instantiated in `readOnly` mode: - -```ts - -``` - -**WARNING**: In current implementation, the PagerDuty plugin requires the `/pagerduty` proxy endpoint be exposed by the Backstage backend as an unprotected endpoint, in effect enabling PagerDuty API access using the configured `PAGERDUTY_TOKEN` for any user or process with access to the `/pagerduty` Backstage backend endpoint. If you regard this as problematic, consider using the plugin in `readOnly` mode (``) using the following proxy configuration: - -```yaml -proxy: - '/pagerduty': - target: https://api.pagerduty.com - headers: - Authorization: Token token=${PAGERDUTY_TOKEN} - # prohibit the `/pagerduty` proxy endpoint from servicing non-GET requests - allowedMethods: ['GET'] -``` - -## How to Uninstall - -1. Remove any configuration added in Backstage yaml files, such as the proxy configuration in `app-config.yaml` and the integration key in an entity's annotations. -2. Remove the added code snippets from `EntityPage.tsx` -3. Remove the plugin package: - -```bash -# From your Backstage root directory -yarn remove --cwd packages/app @backstage/plugin-pagerduty -``` - -4. [Delete the integration](https://support.pagerduty.com/docs/services-and-integrations#delete-an-integration-from-a-service) from the service in PagerDuty +This package has been deprecated, consider using [@pagerduty/backstage-plugin](https://github.com/pagerduty/backstage-plugin) instead. diff --git a/plugins/pagerduty/api-report.md b/plugins/pagerduty/api-report.md index db73259dd5..a96cab1af1 100644 --- a/plugins/pagerduty/api-report.md +++ b/plugins/pagerduty/api-report.md @@ -16,7 +16,7 @@ import { JSX as JSX_2 } from 'react'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; -// @public (undocumented) +// @public @deprecated (undocumented) export const EntityPagerDutyCard: ( props: EntityPagerDutyCardProps, ) => JSX_2.Element; @@ -27,7 +27,7 @@ export type EntityPagerDutyCardProps = { disableChangeEvents?: boolean; }; -// @public (undocumented) +// @public @deprecated (undocumented) export const HomePagePagerDutyCard: ( props: CardExtensionProps, ) => JSX_2.Element; @@ -138,7 +138,7 @@ export type PagerDutyClientApiDependencies = { fetchApi: FetchApi; }; -// @public (undocumented) +// @public @deprecated (undocumented) export type PagerDutyEntity = { integrationKey?: string; serviceId?: string; @@ -176,7 +176,7 @@ export type PagerDutyOnCallsResponse = { oncalls: PagerDutyOnCall[]; }; -// @public (undocumented) +// @public @deprecated (undocumented) const pagerDutyPlugin: BackstagePlugin<{}, {}>; export { pagerDutyPlugin }; export { pagerDutyPlugin as plugin }; diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index e56e4d2d8d..b719a6e11d 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-pagerduty", - "description": "A Backstage plugin that integrates towards PagerDuty", - "version": "0.6.7", + "description": "This plugin has been deprecated, consider using [@pagerduty/backstage-plugin](https://github.com/pagerduty/backstage-plugin) instead.", + "version": "0.7.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/pagerduty/src/components/ChangeEvents/ChangeEventListItem.tsx b/plugins/pagerduty/src/components/ChangeEvents/ChangeEventListItem.tsx index 7b531bf1de..8dc5bf1f33 100644 --- a/plugins/pagerduty/src/components/ChangeEvents/ChangeEventListItem.tsx +++ b/plugins/pagerduty/src/components/ChangeEvents/ChangeEventListItem.tsx @@ -28,9 +28,8 @@ import { import { DateTime, Duration } from 'luxon'; import { PagerDutyChangeEvent } from '../types'; import OpenInBrowserIcon from '@material-ui/icons/OpenInBrowser'; -import { BackstageTheme } from '@backstage/theme'; -const useStyles = makeStyles({ +const useStyles = makeStyles({ denseListIcon: { marginRight: 0, display: 'flex', diff --git a/plugins/pagerduty/src/components/Incident/IncidentListItem.tsx b/plugins/pagerduty/src/components/Incident/IncidentListItem.tsx index b23fcb8490..3ee92f1470 100644 --- a/plugins/pagerduty/src/components/Incident/IncidentListItem.tsx +++ b/plugins/pagerduty/src/components/Incident/IncidentListItem.tsx @@ -30,10 +30,9 @@ import Warning from '@material-ui/icons/Warning'; import { DateTime, Duration } from 'luxon'; import { PagerDutyIncident } from '../types'; import OpenInBrowserIcon from '@material-ui/icons/OpenInBrowser'; -import { BackstageTheme } from '@backstage/theme'; import { Link } from '@backstage/core-components'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ denseListIcon: { marginRight: 0, display: 'flex', diff --git a/plugins/pagerduty/src/components/TriggerButton/index.tsx b/plugins/pagerduty/src/components/TriggerButton/index.tsx index 1c12103d73..60adbd38c0 100644 --- a/plugins/pagerduty/src/components/TriggerButton/index.tsx +++ b/plugins/pagerduty/src/components/TriggerButton/index.tsx @@ -13,14 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import React, { useCallback, ReactNode, useState } from 'react'; import { makeStyles, Button } from '@material-ui/core'; -import { BackstageTheme } from '@backstage/theme'; - import { usePagerdutyEntity } from '../../hooks'; import { TriggerDialog } from '../TriggerDialog'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ buttonStyle: { backgroundColor: theme.palette.error.main, color: theme.palette.error.contrastText, diff --git a/plugins/pagerduty/src/plugin.ts b/plugins/pagerduty/src/plugin.ts index 59cc5cd8cc..4144eb5878 100644 --- a/plugins/pagerduty/src/plugin.ts +++ b/plugins/pagerduty/src/plugin.ts @@ -30,7 +30,10 @@ export const rootRouteRef = createRouteRef({ id: 'pagerduty', }); -/** @public */ +/** + * @public + * @deprecated This plugin will be removed in a future release. Please use \@pagerduty/backstage-plugin plugin instead (https://www.npmjs.com/package/\@pagerduty/backstage-plugin). + */ export const pagerDutyPlugin = createPlugin({ id: 'pagerduty', apis: [ @@ -47,7 +50,10 @@ export const pagerDutyPlugin = createPlugin({ ], }); -/** @public */ +/** + * @public + * @deprecated This plugin and it's cards will be removed in a future release. Please use \@pagerduty/backstage-plugin plugin instead (https://www.npmjs.com/package/\@pagerduty/backstage-plugin). + */ export const EntityPagerDutyCard = pagerDutyPlugin.provide( createComponentExtension({ name: 'EntityPagerDutyCard', @@ -60,7 +66,10 @@ export const EntityPagerDutyCard = pagerDutyPlugin.provide( }), ); -/** @public */ +/** + * @public + * @deprecated This plugin and it's cards will be removed in a future release. Please use \@pagerduty/backstage-plugin plugin instead (https://www.npmjs.com/package/\@pagerduty/backstage-plugin). + */ export const HomePagePagerDutyCard = pagerDutyPlugin.provide( createCardExtension({ name: 'HomePagePagerDutyCard', diff --git a/plugins/pagerduty/src/types.ts b/plugins/pagerduty/src/types.ts index 9f38b429ef..e026a6ffbe 100644 --- a/plugins/pagerduty/src/types.ts +++ b/plugins/pagerduty/src/types.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -/** @public */ +/** + * @public + * @deprecated This plugin and it's types will be removed in a future release. Please use \@pagerduty/backstage-plugin plugin instead (https://www.npmjs.com/package/\@pagerduty/backstage-plugin). + */ export type PagerDutyEntity = { integrationKey?: string; serviceId?: string; diff --git a/plugins/periskop-backend/CHANGELOG.md b/plugins/periskop-backend/CHANGELOG.md index 150f1df7a6..1bf2436a66 100644 --- a/plugins/periskop-backend/CHANGELOG.md +++ b/plugins/periskop-backend/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-periskop-backend +## 0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + +## 0.2.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + +## 0.2.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + ## 0.2.5 ### Patch Changes diff --git a/plugins/periskop-backend/alpha-api-report.md b/plugins/periskop-backend/api-report-alpha.md similarity index 100% rename from plugins/periskop-backend/alpha-api-report.md rename to plugins/periskop-backend/api-report-alpha.md diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index be19fd40c2..ed392e5337 100644 --- a/plugins/periskop-backend/package.json +++ b/plugins/periskop-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop-backend", - "version": "0.2.5", + "version": "0.2.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/periskop/CHANGELOG.md b/plugins/periskop/CHANGELOG.md index 2becc5efa6..7af0c55969 100644 --- a/plugins/periskop/CHANGELOG.md +++ b/plugins/periskop/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-periskop +## 0.1.26-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.1.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.1.26-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.1.24 ### Patch Changes diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index ac5869366c..2e5f75da03 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop", - "version": "0.1.24", + "version": "0.1.26-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md b/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md index 820b8f3401..7a893efe16 100644 --- a/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md +++ b/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-permission-backend-module-allow-all-policy +## 0.1.5-next.2 + +### Patch Changes + +- cc4228e: Switched module ID to use kebab-case. +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + +## 0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/plugin-permission-common@0.7.10 + ## 0.1.4 ### Patch Changes diff --git a/plugins/permission-backend-module-policy-allow-all/package.json b/plugins/permission-backend-module-policy-allow-all/package.json index f1dcc9d328..3d3d5889f2 100644 --- a/plugins/permission-backend-module-policy-allow-all/package.json +++ b/plugins/permission-backend-module-policy-allow-all/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-backend-module-allow-all-policy", "description": "Allow all policy backend module for the permission plugin.", - "version": "0.1.4", + "version": "0.1.5-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-backend-module-policy-allow-all/src/module.ts b/plugins/permission-backend-module-policy-allow-all/src/module.ts index 47ab202a00..f7a38f293c 100644 --- a/plugins/permission-backend-module-policy-allow-all/src/module.ts +++ b/plugins/permission-backend-module-policy-allow-all/src/module.ts @@ -23,8 +23,8 @@ import { AllowAllPermissionPolicy } from './policy'; * @public */ export const permissionModuleAllowAllPolicy = createBackendModule({ - moduleId: 'allowAllPolicy', pluginId: 'permission', + moduleId: 'allow-all-policy', register(reg) { reg.registerInit({ deps: { policy: policyExtensionPoint }, diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index 04ae79d5ff..8ccc1e1b9d 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-permission-backend +## 0.5.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + +## 0.5.31-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + +## 0.5.31-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + ## 0.5.30 ### Patch Changes diff --git a/plugins/permission-backend/alpha-api-report.md b/plugins/permission-backend/api-report-alpha.md similarity index 100% rename from plugins/permission-backend/alpha-api-report.md rename to plugins/permission-backend/api-report-alpha.md diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index 8226b30c4b..2b95f48511 100644 --- a/plugins/permission-backend/package.json +++ b/plugins/permission-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-backend", - "version": "0.5.30", + "version": "0.5.31-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index 934163ee05..734a3ebc2f 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-permission-node +## 0.7.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + +## 0.7.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-permission-common@0.7.10 + +## 0.7.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + ## 0.7.18 ### Patch Changes diff --git a/plugins/permission-node/alpha-api-report.md b/plugins/permission-node/api-report-alpha.md similarity index 100% rename from plugins/permission-node/alpha-api-report.md rename to plugins/permission-node/api-report-alpha.md diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index aca30402e9..5cd6616e18 100644 --- a/plugins/permission-node/package.json +++ b/plugins/permission-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-node", "description": "Common permission and authorization utilities for backend plugins", - "version": "0.7.18", + "version": "0.7.19-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-react/CHANGELOG.md b/plugins/permission-react/CHANGELOG.md index a5e91cc3cf..3fedc6e80a 100644 --- a/plugins/permission-react/CHANGELOG.md +++ b/plugins/permission-react/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-permission-react +## 0.4.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + +## 0.4.18-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.10 + ## 0.4.17 ### Patch Changes diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index d1d2acf809..433ec8bcb4 100644 --- a/plugins/permission-react/package.json +++ b/plugins/permission-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-permission-react", - "version": "0.4.17", + "version": "0.4.18-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist-backend/CHANGELOG.md b/plugins/playlist-backend/CHANGELOG.md index 39d1ccf4d1..a7cde6d097 100644 --- a/plugins/playlist-backend/CHANGELOG.md +++ b/plugins/playlist-backend/CHANGELOG.md @@ -1,5 +1,53 @@ # @backstage/plugin-playlist-backend +## 0.3.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + - @backstage/plugin-playlist-common@0.1.12 + +## 0.3.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + - @backstage/plugin-playlist-common@0.1.12 + +## 0.3.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-playlist-common@0.1.12 + ## 0.3.11 ### Patch Changes diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json index cd51661d76..15943da053 100644 --- a/plugins/playlist-backend/package.json +++ b/plugins/playlist-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist-backend", - "version": "0.3.11", + "version": "0.3.12-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist/CHANGELOG.md b/plugins/playlist/CHANGELOG.md index 4ef8095125..ff6460c029 100644 --- a/plugins/playlist/CHANGELOG.md +++ b/plugins/playlist/CHANGELOG.md @@ -1,5 +1,56 @@ # @backstage/plugin-playlist +## 0.2.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/plugin-playlist-common@0.1.12 + +## 0.2.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-playlist-common@0.1.12 + +## 0.2.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-playlist-common@0.1.12 + ## 0.2.0 ### Minor Changes diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index 1068a1fb49..af7c76c179 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist", - "version": "0.2.0", + "version": "0.2.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist/src/components/CreatePlaylistButton/CreatePlaylistButton.tsx b/plugins/playlist/src/components/CreatePlaylistButton/CreatePlaylistButton.tsx index ac32097680..26c7b3fd45 100644 --- a/plugins/playlist/src/components/CreatePlaylistButton/CreatePlaylistButton.tsx +++ b/plugins/playlist/src/components/CreatePlaylistButton/CreatePlaylistButton.tsx @@ -20,13 +20,12 @@ import { useRouteRef, alertApiRef, } from '@backstage/core-plugin-api'; -import { BackstageTheme } from '@backstage/theme'; import { usePermission } from '@backstage/plugin-permission-react'; import { permissions, PlaylistMetadata, } from '@backstage/plugin-playlist-common'; -import { Button, IconButton, useMediaQuery } from '@material-ui/core'; +import { Button, IconButton, Theme, useMediaQuery } from '@material-ui/core'; import AddCircleOutline from '@material-ui/icons/AddCircleOutline'; import React, { useCallback, useState } from 'react'; import { useNavigate } from 'react-router-dom'; @@ -49,7 +48,7 @@ export const CreatePlaylistButton = () => { const { allowed } = usePermission({ permission: permissions.playlistListCreate, }); - const isXSScreen = useMediaQuery(theme => + const isXSScreen = useMediaQuery(theme => theme.breakpoints.down('xs'), ); diff --git a/plugins/playlist/src/components/PersonalListPicker/PersonalListPicker.tsx b/plugins/playlist/src/components/PersonalListPicker/PersonalListPicker.tsx index a8537cb213..0691d26732 100644 --- a/plugins/playlist/src/components/PersonalListPicker/PersonalListPicker.tsx +++ b/plugins/playlist/src/components/PersonalListPicker/PersonalListPicker.tsx @@ -29,7 +29,6 @@ import { ListItemText, makeStyles, MenuItem, - Theme, Typography, } from '@material-ui/core'; import PlaylistPlayIcon from '@material-ui/icons/PlaylistPlay'; @@ -75,7 +74,7 @@ export class PersonalListFilter implements PlaylistFilter { } } -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ root: { backgroundColor: 'rgba(0, 0, 0, .11)', boxShadow: 'none', diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index 4a2cb29827..eadc30bec7 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-proxy-backend +## 0.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + +## 0.4.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + +## 0.4.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + ## 0.4.5 ### Patch Changes diff --git a/plugins/proxy-backend/alpha-api-report.md b/plugins/proxy-backend/api-report-alpha.md similarity index 100% rename from plugins/proxy-backend/alpha-api-report.md rename to plugins/proxy-backend/api-report-alpha.md diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 55fcc6fd87..8beddba626 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-proxy-backend", "description": "A Backstage backend plugin that helps you set up proxy endpoints in the backend", - "version": "0.4.5", + "version": "0.4.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/puppetdb/CHANGELOG.md b/plugins/puppetdb/CHANGELOG.md index e8cf64f255..01699058c0 100644 --- a/plugins/puppetdb/CHANGELOG.md +++ b/plugins/puppetdb/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-puppetdb +## 0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.1.9 ### Patch Changes diff --git a/plugins/puppetdb/package.json b/plugins/puppetdb/package.json index 0f68073d52..c54a725356 100644 --- a/plugins/puppetdb/package.json +++ b/plugins/puppetdb/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-puppetdb", "description": "Backstage plugin to visualize resource information and Puppet facts from PuppetDB.", - "version": "0.1.9", + "version": "0.1.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsLogsTable.tsx b/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsLogsTable.tsx index f512fcd935..d12b432314 100644 --- a/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsLogsTable.tsx +++ b/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsLogsTable.tsx @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import Typography from '@material-ui/core/Typography'; import React from 'react'; import { puppetDbApiRef, PuppetDbReportLog } from '../../api'; @@ -24,13 +25,12 @@ import { import useAsync from 'react-use/lib/useAsync'; import { useApi } from '@backstage/core-plugin-api'; import { makeStyles } from '@material-ui/core/styles'; -import { BackstageTheme } from '@backstage/theme'; type ReportLogsTableProps = { hash: string; }; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ empty: { padding: theme.spacing(2), display: 'flex', diff --git a/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsPage.tsx b/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsPage.tsx index db6536fce4..c7da8df36b 100644 --- a/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsPage.tsx +++ b/plugins/puppetdb/src/components/ReportDetailsPage/ReportDetailsPage.tsx @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { Link as RouterLink, useParams } from 'react-router-dom'; import { Breadcrumbs, Link } from '@backstage/core-components'; import { makeStyles } from '@material-ui/core/styles'; @@ -27,11 +28,10 @@ import { Typography, Tabs, } from '@material-ui/core'; -import { BackstageTheme } from '@backstage/theme'; import { ReportDetailsEventsTable } from './ReportDetailsEventsTable'; import { ReportDetailsLogsTable } from './ReportDetailsLogsTable'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ cards: { marginTop: theme.spacing(2), }, diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md index 388e936d45..7df536e3d4 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-rollbar-backend +## 0.1.53-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/config@1.1.1 + +## 0.1.53-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + +## 0.1.53-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/config@1.1.1 + ## 0.1.52 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index b3f7272bbe..8823d15ff4 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar-backend", "description": "A Backstage backend plugin that integrates towards Rollbar", - "version": "0.1.52", + "version": "0.1.53-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index d1bffcd547..084f3c1a14 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-rollbar +## 0.4.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.4.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.4.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.4.26 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 571ce6daa1..7c8dd8b9b9 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar", "description": "A Backstage plugin that integrates towards Rollbar", - "version": "0.4.26", + "version": "0.4.28-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md index 21114b347f..2beac8fccb 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-scaffolder-backend-module-confluence-to-markdown +## 0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + +## 0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + +## 0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.2.8 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json index 0a347ff7f7..48c3fb5aaf 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/package.json +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown", "description": "The confluence-to-markdown module for @backstage/plugin-scaffolder-backend", - "version": "0.2.8", + "version": "0.2.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md index eadc11d7f8..937c6068fe 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.2.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + +## 0.2.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + +## 0.2.32-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.2.31 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 1742905379..9d99e2ca68 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-cookiecutter", "description": "A module for the scaffolder backend that lets you template projects using cookiecutter", - "version": "0.2.31", + "version": "0.2.32-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md index 54ab2d2a28..b113d4abda 100644 --- a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-scaffolder-backend-module-gitlab +## 0.2.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + +## 0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + +## 0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.2.10 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index 4f4dfc8d3e..bdb55606f1 100644 --- a/plugins/scaffolder-backend-module-gitlab/package.json +++ b/plugins/scaffolder-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gitlab", - "version": "0.2.10", + "version": "0.2.11-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-rails/CHANGELOG.md b/plugins/scaffolder-backend-module-rails/CHANGELOG.md index a8413c589b..5df1fe2eef 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.4.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + +## 0.4.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + +## 0.4.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.4.24 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index dbab5789a3..4a175cffc6 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend-module-rails", "description": "A module for the scaffolder backend that lets you template projects using Rails", - "version": "0.4.24", + "version": "0.4.25-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md index 110a049c09..47e602cb31 100644 --- a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-scaffolder-backend-module-sentry +## 0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + +## 0.1.16-next.1 + +### Patch Changes + +- 7f8a801e6d: Added examples for `sentry:project:create` scaffolder action and unit tests. +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + +## 0.1.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.1.15 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-sentry/package.json b/plugins/scaffolder-backend-module-sentry/package.json index 627c577533..46dc0c3bba 100644 --- a/plugins/scaffolder-backend-module-sentry/package.json +++ b/plugins/scaffolder-backend-module-sentry/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-sentry", - "version": "0.1.15", + "version": "0.1.16-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,10 +30,14 @@ "dependencies": { "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", - "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/plugin-scaffolder-node": "workspace:^", + "yaml": "^2.3.3" }, "devDependencies": { - "@backstage/cli": "workspace:^" + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "@backstage/types": "workspace:^", + "msw": "^2.0.0" }, "files": [ "dist" diff --git a/plugins/scaffolder-backend-module-sentry/src/actions/createProject.examples.ts b/plugins/scaffolder-backend-module-sentry/src/actions/createProject.examples.ts new file mode 100644 index 0000000000..9d4551c1b5 --- /dev/null +++ b/plugins/scaffolder-backend-module-sentry/src/actions/createProject.examples.ts @@ -0,0 +1,53 @@ +/* + * 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 { TemplateExample } from '@backstage/plugin-scaffolder-node'; +import yaml from 'yaml'; + +export const examples: TemplateExample[] = [ + { + description: 'Creates a Sentry project with the specified parameters.', + example: yaml.stringify({ + steps: [ + { + id: 'create-sentry-project', + action: 'sentry:project:create', + name: 'Create a Sentry project with provided project slug.', + input: { + organizationSlug: 'my-org', + teamSlug: 'team-a', + name: 'Scaffolded project A', + slug: 'scaff-proj-a', + authToken: + 'a14711beb516e1e910d2ede554dc1bf725654ef3c75e5a9106de9aec13d5df96', + }, + }, + { + id: 'create-sentry-project', + action: 'sentry:project:create', + name: 'Create a Sentry project without providing a project slug.', + input: { + organizationSlug: 'my-org', + teamSlug: 'team-b', + name: 'Scaffolded project B', + authToken: + 'b15711beb516e1e910d2ede554dc1bf725654ef3c75e5a9106de9aec13d4gf93', + }, + }, + ], + }), + }, +]; diff --git a/plugins/scaffolder-backend-module-sentry/src/actions/createProject.test.ts b/plugins/scaffolder-backend-module-sentry/src/actions/createProject.test.ts new file mode 100644 index 0000000000..972b0f1e8e --- /dev/null +++ b/plugins/scaffolder-backend-module-sentry/src/actions/createProject.test.ts @@ -0,0 +1,217 @@ +/* + * 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 { setupRequestMockHandlers } from '@backstage/backend-test-utils'; +import { ConfigReader } from '@backstage/config'; +import { InputError } from '@backstage/errors'; +import { ActionContext } from '@backstage/plugin-scaffolder-node'; +import { JsonObject } from '@backstage/types'; +import { randomBytes } from 'crypto'; +import { setupServer } from 'msw/node'; +import { HttpResponse, http } from 'msw'; +import { createSentryCreateProjectAction } from './createProject'; + +describe('sentry:project:create action', () => { + const worker = setupServer(); + setupRequestMockHandlers(worker); + + const createScaffolderConfig = (configData: JsonObject = {}) => ({ + config: new ConfigReader({ + scaffolder: { + ...configData, + }, + }), + }); + + const getActionContext = (): ActionContext<{ + organizationSlug: string; + teamSlug: string; + name: string; + slug?: string; + authToken?: string; + }> => ({ + workspacePath: './dev/proj', + createTemporaryDirectory: jest.fn(), + logger: jest.createMockFromModule('winston'), + logStream: jest.createMockFromModule('stream'), + input: { + organizationSlug: 'org', + teamSlug: 'team', + name: 'test project', + authToken: randomBytes(5).toString('hex'), + }, + output: jest.fn(), + }); + + it('should request sentry project create with specified parameters.', async () => { + expect.assertions(3); + + const action = createSentryCreateProjectAction(createScaffolderConfig()); + const actionContext = getActionContext(); + + worker.use( + http.post( + `https://sentry.io/api/0/teams/${actionContext.input.organizationSlug}/${actionContext.input.teamSlug}/projects/`, + async ({ request }) => { + expect(request.headers.get('Authorization')).toBe( + `Bearer ${actionContext.input.authToken}`, + ); + expect(request.headers.get('Content-Type')).toBe(`application/json`); + await expect(request.json()).resolves.toEqual({ + name: actionContext.input.name, + }); + return HttpResponse.json( + { detail: 'project creation mocked result' }, + { status: 201 }, + ); + }, + ), + ); + + await action.handler(actionContext); + }); + + it('should request sentry project create with added optional specified project slug', async () => { + expect.assertions(3); + + const action = createSentryCreateProjectAction(createScaffolderConfig()); + const actionContext = getActionContext(); + actionContext.input = { ...actionContext.input, slug: 'project-slug' }; + + worker.use( + http.post( + `https://sentry.io/api/0/teams/${actionContext.input.organizationSlug}/${actionContext.input.teamSlug}/projects/`, + async ({ request }) => { + expect(request.headers.get('Authorization')).toBe( + `Bearer ${actionContext.input.authToken}`, + ); + expect(request.headers.get('Content-Type')).toBe(`application/json`); + await expect(request.json()).resolves.toEqual({ + name: actionContext.input.name, + slug: actionContext.input.slug, + }); + return HttpResponse.json( + { detail: 'project creation mocked result' }, + { status: 201 }, + ); + }, + ), + ); + + await action.handler(actionContext); + }); + + it('should take Sentry auth token from scaffolder config when input authToken is missing.', async () => { + expect.assertions(3); + + const sentryScaffolderConfigToken = randomBytes(5).toString('hex'); + const action = createSentryCreateProjectAction( + createScaffolderConfig({ + sentry: { + token: sentryScaffolderConfigToken, + }, + }), + ); + const actionContext = getActionContext(); + actionContext.input.authToken = undefined; + + worker.use( + http.post( + `https://sentry.io/api/0/teams/${actionContext.input.organizationSlug}/${actionContext.input.teamSlug}/projects/`, + async ({ request }) => { + expect(request.headers.get('Authorization')).toBe( + `Bearer ${sentryScaffolderConfigToken}`, + ); + expect(request.headers.get('Content-Type')).toBe(`application/json`); + await expect(request.json()).resolves.toEqual({ + name: actionContext.input.name, + }); + return HttpResponse.json( + { detail: 'project creation mocked result' }, + { status: 201 }, + ); + }, + ), + ); + + await action.handler(actionContext); + }); + + it('should throw InputError when auth token is missing from input parameters and scaffolder config.', async () => { + const action = createSentryCreateProjectAction(createScaffolderConfig()); + const actionContext = getActionContext(); + actionContext.input.authToken = undefined; + + worker.use( + http.post( + `https://sentry.io/api/0/teams/${actionContext.input.organizationSlug}/${actionContext.input.teamSlug}/projects/`, + async ({ request }) => { + expect(request.headers.get('Authorization')).toBe( + `Bearer ${actionContext.input.authToken}`, + ); + expect(request.headers.get('Content-Type')).toBe(`application/json`); + await expect(request.json()).resolves.toEqual({ + name: actionContext.input.name, + }); + return HttpResponse.json( + { detail: 'project creation mocked result' }, + { status: 201 }, + ); + }, + ), + ); + + await expect(() => action.handler(actionContext)).rejects.toThrow( + new InputError('No valid sentry token given'), + ); + }); + + it('should throw InputError when sentry API returns unexpected content-type.', async () => { + const action = createSentryCreateProjectAction(createScaffolderConfig()); + const actionContext = getActionContext(); + + worker.use( + http.post( + `https://sentry.io/api/0/teams/${actionContext.input.organizationSlug}/${actionContext.input.teamSlug}/projects/`, + async () => { + return HttpResponse.text('Bad response', { status: 201 }); + }, + ), + ); + + await expect(() => action.handler(actionContext)).rejects.toThrow( + new InputError(`Unexpected Sentry Response Type: Bad response`), + ); + }); + + it('should throw InputError when sentry API returns unexpected status code.', async () => { + const action = createSentryCreateProjectAction(createScaffolderConfig()); + const actionContext = getActionContext(); + + worker.use( + http.post( + `https://sentry.io/api/0/teams/${actionContext.input.organizationSlug}/${actionContext.input.teamSlug}/projects/`, + async () => { + return HttpResponse.json({ detail: 'OUCH' }, { status: 400 }); + }, + ), + ); + + await expect(() => action.handler(actionContext)).rejects.toThrow( + new InputError(`Sentry Response was: OUCH`), + ); + }); +}); diff --git a/plugins/scaffolder-backend-module-sentry/src/actions/createProject.ts b/plugins/scaffolder-backend-module-sentry/src/actions/createProject.ts index 85a74eda07..259b670f9e 100644 --- a/plugins/scaffolder-backend-module-sentry/src/actions/createProject.ts +++ b/plugins/scaffolder-backend-module-sentry/src/actions/createProject.ts @@ -19,7 +19,7 @@ import { InputError } from '@backstage/errors'; import { Config } from '@backstage/config'; /** - * Creates the `sentry:craete-project` Scaffolder action. + * Creates the `sentry:project:create` Scaffolder action. * * @remarks * diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index 7b1d074952..5715fdb6bd 100644 --- a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-scaffolder-backend-module-yeoman +## 0.2.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + +## 0.2.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + +## 0.2.29-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + ## 0.2.28 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index 4d11dcbf0f..b05a00598c 100644 --- a/plugins/scaffolder-backend-module-yeoman/package.json +++ b/plugins/scaffolder-backend-module-yeoman/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-yeoman", - "version": "0.2.28", + "version": "0.2.29-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index 81f677b7cd..34dfbbf546 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,79 @@ # @backstage/plugin-scaffolder-backend +## 1.19.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/plugin-catalog-backend@1.16.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.2 + - @backstage/plugin-scaffolder-common@1.4.3 + - @backstage/plugin-scaffolder-node@0.2.9-next.2 + +## 1.19.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@1.15.1-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-catalog-node@1.5.1-next.1 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-permission-node@0.7.19-next.1 + - @backstage/plugin-scaffolder-common@1.4.3 + - @backstage/plugin-scaffolder-node@0.2.9-next.1 + +## 1.19.2-next.0 + +### Patch Changes + +- aff34fcf23: Fix issue with Circular JSON dependencies in templating +- 48667b4d3a: Fix creating env secret in github:environment:create action +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/plugin-catalog-backend@1.15.1-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.5-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/plugin-permission-node@0.7.19-next.0 + - @backstage/plugin-scaffolder-node@0.2.9-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-scaffolder-common@1.4.3 + ## 1.19.0 ### Minor Changes diff --git a/plugins/scaffolder-backend/alpha-api-report.md b/plugins/scaffolder-backend/api-report-alpha.md similarity index 100% rename from plugins/scaffolder-backend/alpha-api-report.md rename to plugins/scaffolder-backend/api-report-alpha.md diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 2b6685dafd..b8ee699287 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend", "description": "The Backstage backend plugin that helps you create new things", - "version": "1.19.0", + "version": "1.19.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.examples.test.ts index 5e3da2fcec..9d5dbfd35c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.examples.test.ts @@ -25,7 +25,7 @@ import { examples } from './gitHubEnvironment.examples'; const mockOctokit = { rest: { actions: { - getRepoPublicKey: jest.fn(), + getEnvironmentPublicKey: jest.fn(), createEnvironmentVariable: jest.fn(), createOrUpdateEnvironmentSecret: jest.fn(), }, @@ -68,7 +68,7 @@ describe('github:environment:create examples', () => { }; beforeEach(() => { - mockOctokit.rest.actions.getRepoPublicKey.mockResolvedValue({ + mockOctokit.rest.actions.getEnvironmentPublicKey.mockResolvedValue({ data: { key: publicKey, key_id: 'keyid', @@ -109,7 +109,9 @@ describe('github:environment:create examples', () => { expect( mockOctokit.rest.actions.createEnvironmentVariable, ).not.toHaveBeenCalled(); - expect(mockOctokit.rest.actions.getRepoPublicKey).not.toHaveBeenCalled(); + expect( + mockOctokit.rest.actions.getEnvironmentPublicKey, + ).not.toHaveBeenCalled(); expect( mockOctokit.rest.actions.createOrUpdateEnvironmentSecret, ).not.toHaveBeenCalled(); @@ -141,7 +143,9 @@ describe('github:environment:create examples', () => { expect( mockOctokit.rest.actions.createEnvironmentVariable, ).not.toHaveBeenCalled(); - expect(mockOctokit.rest.actions.getRepoPublicKey).not.toHaveBeenCalled(); + expect( + mockOctokit.rest.actions.getEnvironmentPublicKey, + ).not.toHaveBeenCalled(); expect( mockOctokit.rest.actions.createOrUpdateEnvironmentSecret, ).not.toHaveBeenCalled(); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.test.ts index d158bc122e..8ec3d84e36 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.test.ts @@ -24,7 +24,7 @@ import { ScmIntegrations } from '@backstage/integration'; const mockOctokit = { rest: { actions: { - getRepoPublicKey: jest.fn(), + getEnvironmentPublicKey: jest.fn(), createEnvironmentVariable: jest.fn(), createOrUpdateEnvironmentSecret: jest.fn(), }, @@ -71,7 +71,7 @@ describe('github:environment:create', () => { }; beforeEach(() => { - mockOctokit.rest.actions.getRepoPublicKey.mockResolvedValue({ + mockOctokit.rest.actions.getEnvironmentPublicKey.mockResolvedValue({ data: { key: publicKey, key_id: 'keyid', diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.ts index 874798e4df..16859d9a26 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubEnvironment.ts @@ -167,10 +167,11 @@ export function createGithubEnvironmentAction(options: { } if (secrets) { - const publicKeyResponse = await client.rest.actions.getRepoPublicKey({ - owner: owner, - repo: repo, - }); + const publicKeyResponse = + await client.rest.actions.getEnvironmentPublicKey({ + repository_id: repository.data.id, + environment_name: name, + }); await Sodium.ready; const binaryKey = Sodium.from_base64( diff --git a/plugins/scaffolder-common/alpha-api-report.md b/plugins/scaffolder-common/api-report-alpha.md similarity index 100% rename from plugins/scaffolder-common/alpha-api-report.md rename to plugins/scaffolder-common/api-report-alpha.md diff --git a/plugins/scaffolder-node/CHANGELOG.md b/plugins/scaffolder-node/CHANGELOG.md index 323c8fb2a6..058c4b0d39 100644 --- a/plugins/scaffolder-node/CHANGELOG.md +++ b/plugins/scaffolder-node/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-scaffolder-node +## 0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.3 + +## 0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.3 + +## 0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.3 + ## 0.2.8 ### Patch Changes diff --git a/plugins/scaffolder-node/alpha-api-report.md b/plugins/scaffolder-node/api-report-alpha.md similarity index 100% rename from plugins/scaffolder-node/alpha-api-report.md rename to plugins/scaffolder-node/api-report-alpha.md diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index 84a8b4d480..5e939c2ec1 100644 --- a/plugins/scaffolder-node/package.json +++ b/plugins/scaffolder-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-node", "description": "The plugin-scaffolder-node module for @backstage/plugin-scaffolder-backend", - "version": "0.2.8", + "version": "0.2.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-react/CHANGELOG.md b/plugins/scaffolder-react/CHANGELOG.md index 748ba1a7bc..fed5167e92 100644 --- a/plugins/scaffolder-react/CHANGELOG.md +++ b/plugins/scaffolder-react/CHANGELOG.md @@ -1,5 +1,71 @@ # @backstage/plugin-scaffolder-react +## 1.6.2-next.2 + +### Patch Changes + +- 5bb5240: Fixed issue for showing undefined for hidden form items +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-scaffolder-common@1.4.3 + +## 1.6.2-next.1 + +### Patch Changes + +- fa66d1b5b3: Fixed bug in `ReviewState` where `enum` value was displayed in step review instead of the corresponding label when using `enumNames` +- 2aee53bbeb: Add horizontal slider if stepper overflows +- 2b725913c1: Updated dependency `@rjsf/utils` to `5.14.3`. + Updated dependency `@rjsf/core` to `5.14.3`. + Updated dependency `@rjsf/material-ui` to `5.14.3`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.3`. +- a518c5a25b: Updated dependency `@react-hookz/web` to `^23.0.0`. +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-scaffolder-common@1.4.3 + +## 1.6.2-next.0 + +### Patch Changes + +- e516bf4da8: Step titles in the Stepper are now clickable and redirect the user to the corresponding step, as an alternative to using the back buttons. +- aaa6fb3bc9: Minor updates for TypeScript 5.2.2+ compatibility +- 6cd12f277b: Updated dependency `@rjsf/utils` to `5.14.1`. + Updated dependency `@rjsf/core` to `5.14.1`. + Updated dependency `@rjsf/material-ui` to `5.14.1`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.1`. +- 63c494ef22: Updated dependency `@rjsf/utils` to `5.14.2`. + Updated dependency `@rjsf/core` to `5.14.2`. + Updated dependency `@rjsf/material-ui` to `5.14.2`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.2`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.7 + - @backstage/plugin-scaffolder-common@1.4.3 + ## 1.6.0 ### Minor Changes diff --git a/plugins/scaffolder-react/alpha-api-report.md b/plugins/scaffolder-react/api-report-alpha.md similarity index 100% rename from plugins/scaffolder-react/alpha-api-report.md rename to plugins/scaffolder-react/api-report-alpha.md diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index d8dcc6d39b..98af15fb3d 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-react", "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder", - "version": "1.6.0", + "version": "1.6.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -59,11 +59,11 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", - "@react-hookz/web": "^20.0.0", - "@rjsf/core": "5.13.6", - "@rjsf/material-ui": "5.13.6", - "@rjsf/utils": "5.13.6", - "@rjsf/validator-ajv8": "5.13.6", + "@react-hookz/web": "^23.0.0", + "@rjsf/core": "5.14.3", + "@rjsf/material-ui": "5.14.3", + "@rjsf/utils": "5.14.3", + "@rjsf/validator-ajv8": "5.14.3", "@types/json-schema": "^7.0.9", "@types/react": "^16.13.1 || ^17.0.0", "classnames": "^2.2.6", diff --git a/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.test.tsx b/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.test.tsx index 0f56a32d1d..e9277b2230 100644 --- a/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.test.tsx +++ b/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.test.tsx @@ -94,10 +94,10 @@ describe('ReviewState', () => { }, ]; - const { queryByRole } = render( + const { queryByRole, getAllByRole } = render( , ); - + expect(getAllByRole('row').length).toEqual(1); expect(queryByRole('row', { name: 'Name ******' })).not.toBeInTheDocument(); }); @@ -136,4 +136,70 @@ describe('ReviewState', () => { expect(getByRole('row', { name: 'Name lols' })).toBeInTheDocument(); }); + + it('should display enum label from enumNames', async () => { + const formState = { + name: 'type2', + }; + + const schemas: ParsedTemplateSchema[] = [ + { + mergedSchema: { + type: 'object', + properties: { + name: { + type: 'string', + default: 'type1', + enum: ['type1', 'type2', 'type3'], + enumNames: ['Label-type1', 'Label-type2', 'Label-type3'], + }, + }, + }, + schema: {}, + title: 'test', + uiSchema: {}, + description: 'asd', + }, + ]; + + const { queryByRole } = render( + , + ); + + expect( + queryByRole('row', { name: 'Name Label-type2' }), + ).toBeInTheDocument(); + }); + + it('should display enum value if no corresponding enumNames', async () => { + const formState = { + name: 'type4', + }; + + const schemas: ParsedTemplateSchema[] = [ + { + mergedSchema: { + type: 'object', + properties: { + name: { + type: 'string', + default: 'type1', + enum: ['type1', 'type2', 'type3', 'type4'], + enumNames: ['Label-type1', 'Label-type2', 'Label-type3'], + }, + }, + }, + schema: {}, + title: 'test', + uiSchema: {}, + description: 'asd', + }, + ]; + + const { queryByRole } = render( + , + ); + + expect(queryByRole('row', { name: 'Name type4' })).toBeInTheDocument(); + }); }); diff --git a/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx b/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx index 52ad80c4c2..b601f77bf6 100644 --- a/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx +++ b/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx @@ -34,33 +34,44 @@ export type ReviewStateProps = { */ export const ReviewState = (props: ReviewStateProps) => { const reviewData = Object.fromEntries( - Object.entries(props.formState).map(([key, value]) => { - for (const step of props.schemas) { - const parsedSchema = new JSONSchema(step.mergedSchema); - const definitionInSchema = parsedSchema.getSchema( - `#/${key}`, - props.formState, - ); - if (definitionInSchema) { - const backstageReviewOptions = - definitionInSchema['ui:backstage']?.review; + Object.entries(props.formState) + .map(([key, value]) => { + for (const step of props.schemas) { + const parsedSchema = new JSONSchema(step.mergedSchema); + const definitionInSchema = parsedSchema.getSchema( + `#/${key}`, + props.formState, + ); + if (definitionInSchema) { + const backstageReviewOptions = + definitionInSchema['ui:backstage']?.review; - if (backstageReviewOptions) { - if (backstageReviewOptions.mask) { - return [key, backstageReviewOptions.mask]; + if (backstageReviewOptions) { + if (backstageReviewOptions.mask) { + return [key, backstageReviewOptions.mask]; + } + if (backstageReviewOptions.show === false) { + return []; + } } - if (backstageReviewOptions.show === false) { - return []; - } - } - if (definitionInSchema['ui:widget'] === 'password') { - return [key, '******']; + if (definitionInSchema['ui:widget'] === 'password') { + return [key, '******']; + } + + if (definitionInSchema.enum && definitionInSchema.enumNames) { + return [ + key, + definitionInSchema.enumNames[ + definitionInSchema.enum.indexOf(value) + ] || value, + ]; + } } } - } - return [key, value]; - }), + return [key, value]; + }) + .filter(prop => prop.length > 0), ); return ; }; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx index 34243e232d..2bb66fd782 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx @@ -112,6 +112,54 @@ describe('Stepper', () => { ); }); + it('should remember the state of the form when cycling through the pages by directly clicking on the step labels', async () => { + const manifest: TemplateParameterSchema = { + steps: [ + { + title: 'Step 1', + schema: { + properties: { + name: { + type: 'string', + }, + }, + }, + }, + { + title: 'Step 2', + schema: { + properties: { + description: { + type: 'string', + }, + }, + }, + }, + ], + title: 'React JSON Schema Form Test', + }; + + const { getByRole, getByLabelText } = await renderInTestApp( + , + ); + + await fireEvent.change(getByRole('textbox', { name: 'name' }), { + target: { value: 'im a test value' }, + }); + + await act(async () => { + await fireEvent.click(getByRole('button', { name: 'Next' })); + }); + + await act(async () => { + await fireEvent.click(getByLabelText('Step 1')); + }); + + expect(getByRole('textbox', { name: 'name' })).toHaveValue( + 'im a test value', + ); + }); + it('should merge nested formData correctly in multiple steps', async () => { const Repo = ({ onChange, diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index 9a333944b9..a0b06c0e69 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -190,12 +190,28 @@ export const Stepper = (stepperProps: StepperProps) => { return ( <> {isValidating && } - - {steps.map((step, index) => ( - - {step.title} - - ))} + + {steps.map((step, index) => { + const isAllowedLabelClick = activeStep > index; + return ( + + { + if (isAllowedLabelClick) setActiveStep(index); + }} + > + {step.title} + + + ); + })} Review diff --git a/plugins/scaffolder-react/src/next/components/TaskSteps/TaskSteps.tsx b/plugins/scaffolder-react/src/next/components/TaskSteps/TaskSteps.tsx index 96f0d9d865..d74d298778 100644 --- a/plugins/scaffolder-react/src/next/components/TaskSteps/TaskSteps.tsx +++ b/plugins/scaffolder-react/src/next/components/TaskSteps/TaskSteps.tsx @@ -58,6 +58,7 @@ export const TaskSteps = (props: TaskStepsProps) => { activeStep={props.activeStep} alternativeLabel variant="elevation" + style={{ overflowX: 'auto' }} > {props.steps.map(step => { const isCompleted = step.status === 'completed'; diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/CardHeader.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/CardHeader.tsx index 608af1a0bf..1180c8f106 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCard/CardHeader.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/CardHeader.tsx @@ -15,14 +15,13 @@ */ import React from 'react'; -import { makeStyles, useTheme } from '@material-ui/core'; +import { Theme, makeStyles, useTheme } from '@material-ui/core'; import { ItemCardHeader } from '@backstage/core-components'; -import { BackstageTheme } from '@backstage/theme'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { FavoriteEntity } from '@backstage/plugin-catalog-react'; const useStyles = makeStyles< - BackstageTheme, + Theme, { cardFontColor: string; cardBackgroundImage: string; @@ -55,7 +54,7 @@ export const CardHeader = (props: CardHeaderProps) => { spec: { type }, }, } = props; - const { getPageTheme } = useTheme(); + const { getPageTheme } = useTheme(); const themeForType = getPageTheme({ themeId: type }); const styles = useStyles({ diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/CardLink.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/CardLink.tsx index 9bdb3cf7fb..839d6c7ac1 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCard/CardLink.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/CardLink.tsx @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { IconComponent } from '@backstage/core-plugin-api'; -import { BackstageTheme } from '@backstage/theme'; import { Link } from '@backstage/core-components'; import { makeStyles } from '@material-ui/core'; import React from 'react'; @@ -25,7 +25,7 @@ interface CardLinkProps { url: string; } -const useStyles = makeStyles(() => ({ +const useStyles = makeStyles(() => ({ linkText: { display: 'inline-flex', alignItems: 'center', diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx index 82dc46266d..7850137945 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { RELATION_OWNED_BY } from '@backstage/catalog-model'; import { MarkdownContent, UserIcon } from '@backstage/core-components'; import { IconComponent, useApp } from '@backstage/core-plugin-api'; @@ -21,7 +22,6 @@ import { getEntityRelations, } from '@backstage/plugin-catalog-react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; -import { BackstageTheme } from '@backstage/theme'; import { Box, Card, @@ -32,13 +32,14 @@ import { Button, Grid, makeStyles, + Theme, } from '@material-ui/core'; import LanguageIcon from '@material-ui/icons/Language'; import React from 'react'; import { CardHeader } from './CardHeader'; import { CardLink } from './CardLink'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ box: { overflow: 'hidden', textOverflow: 'ellipsis', diff --git a/plugins/scaffolder-react/src/next/components/TemplateCategoryPicker/TemplateCategoryPicker.tsx b/plugins/scaffolder-react/src/next/components/TemplateCategoryPicker/TemplateCategoryPicker.tsx index b850c3bcfe..eba6aebf93 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCategoryPicker/TemplateCategoryPicker.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCategoryPicker/TemplateCategoryPicker.tsx @@ -65,7 +65,7 @@ export const TemplateCategoryPicker = () => { > Categories - multiple id="categories-picker" options={availableTypes} diff --git a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx index c02f3c2757..c6030930c5 100644 --- a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx +++ b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import React, { useEffect } from 'react'; import { Content, @@ -22,16 +23,14 @@ import { } from '@backstage/core-components'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { makeStyles } from '@material-ui/core'; -import { BackstageTheme } from '@backstage/theme'; import { errorApiRef, useApi } from '@backstage/core-plugin-api'; import { useTemplateParameterSchema } from '../../hooks/useTemplateParameterSchema'; import { Stepper, type StepperProps } from '../Stepper/Stepper'; import { SecretsContextProvider } from '../../../secrets/SecretsContext'; - import { useFilteredSchemaProperties } from '../../hooks/useFilteredSchemaProperties'; import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; -const useStyles = makeStyles(() => ({ +const useStyles = makeStyles({ markdown: { /** to make the styles for React Markdown not leak into the description */ '& :first-child': { @@ -41,7 +40,7 @@ const useStyles = makeStyles(() => ({ marginBottom: 0, }, }, -})); +}); /** * @alpha diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index c106b85991..60352ac39e 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,85 @@ # @backstage/plugin-scaffolder +## 1.16.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/plugin-scaffolder-react@1.6.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/plugin-scaffolder-common@1.4.3 + +## 1.16.2-next.1 + +### Patch Changes + +- 2b725913c1: Updated dependency `@rjsf/utils` to `5.14.3`. + Updated dependency `@rjsf/core` to `5.14.3`. + Updated dependency `@rjsf/material-ui` to `5.14.3`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.3`. +- a518c5a25b: Updated dependency `@react-hookz/web` to `^23.0.0`. +- b5fa6918dc: Fixing `headerOptions` not being passed through the `TemplatePage` component +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/plugin-scaffolder-react@1.6.2-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-permission-react@0.4.18-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-scaffolder-common@1.4.3 + +## 1.16.2-next.0 + +### Patch Changes + +- 6806d10be3: Added `headerOptions` to `TemplateListPage` to optionally override default values. + Changed `themeId` of TemplateListPage from `website` to `home`. +- aaa6fb3bc9: Minor updates for TypeScript 5.2.2+ compatibility +- 6cd12f277b: Updated dependency `@rjsf/utils` to `5.14.1`. + Updated dependency `@rjsf/core` to `5.14.1`. + Updated dependency `@rjsf/material-ui` to `5.14.1`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.1`. +- 63c494ef22: Updated dependency `@rjsf/utils` to `5.14.2`. + Updated dependency `@rjsf/core` to `5.14.2`. + Updated dependency `@rjsf/material-ui` to `5.14.2`. + Updated dependency `@rjsf/validator-ajv8` to `5.14.2`. +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-scaffolder-react@1.6.2-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/plugin-permission-react@0.4.18-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-scaffolder-common@1.4.3 + ## 1.16.0 ### Minor Changes diff --git a/plugins/scaffolder/alpha-api-report.md b/plugins/scaffolder/api-report-alpha.md similarity index 92% rename from plugins/scaffolder/alpha-api-report.md rename to plugins/scaffolder/api-report-alpha.md index 55d14bff75..6a1e0648a4 100644 --- a/plugins/scaffolder/alpha-api-report.md +++ b/plugins/scaffolder/api-report-alpha.md @@ -70,6 +70,11 @@ export type TemplateListPageProps = { actions?: boolean; tasks?: boolean; }; + headerOptions?: { + pageTitleOverride?: string; + title?: string; + subtitle?: string; + }; }; // @alpha (undocumented) @@ -80,6 +85,11 @@ export type TemplateWizardPageProps = { }; layouts?: LayoutOptions[]; formProps?: FormProps_3; + headerOptions?: { + pageTitleOverride?: string; + title?: string; + subtitle?: string; + }; }; // (No @packageDocumentation comment for this package) diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index bb7e199ae0..63be480b89 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder", "description": "The Backstage plugin that helps you create new things", - "version": "1.16.0", + "version": "1.16.2-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -67,11 +67,11 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", - "@react-hookz/web": "^20.0.0", - "@rjsf/core": "5.13.6", - "@rjsf/material-ui": "5.13.6", - "@rjsf/utils": "5.13.6", - "@rjsf/validator-ajv8": "5.13.6", + "@react-hookz/web": "^23.0.0", + "@rjsf/core": "5.14.3", + "@rjsf/material-ui": "5.14.3", + "@rjsf/utils": "5.14.3", + "@rjsf/validator-ajv8": "5.14.3", "@types/react": "^16.13.1 || ^17.0.0", "@uiw/react-codemirror": "^4.9.3", "classnames": "^2.2.6", diff --git a/plugins/scaffolder/src/components/ListTasksPage/OwnerListPicker.tsx b/plugins/scaffolder/src/components/ListTasksPage/OwnerListPicker.tsx index 86384275a7..fdb13b68a0 100644 --- a/plugins/scaffolder/src/components/ListTasksPage/OwnerListPicker.tsx +++ b/plugins/scaffolder/src/components/ListTasksPage/OwnerListPicker.tsx @@ -21,7 +21,6 @@ import { ListItemText, makeStyles, MenuItem, - Theme, Typography, } from '@material-ui/core'; import SettingsIcon from '@material-ui/icons/Settings'; @@ -29,7 +28,7 @@ import React, { Fragment } from 'react'; import AllIcon from '@material-ui/icons/FontDownload'; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ root: { backgroundColor: 'rgba(0, 0, 0, .11)', diff --git a/plugins/scaffolder/src/components/OngoingTask/ContextMenu.tsx b/plugins/scaffolder/src/components/OngoingTask/ContextMenu.tsx index 166c26e854..1612b943c2 100644 --- a/plugins/scaffolder/src/components/OngoingTask/ContextMenu.tsx +++ b/plugins/scaffolder/src/components/OngoingTask/ContextMenu.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; + import { IconButton, ListItemIcon, @@ -22,6 +22,7 @@ import { MenuItem, MenuList, Popover, + Theme, useTheme, } from '@material-ui/core'; import { useAsync } from '@react-hookz/web'; @@ -44,7 +45,7 @@ type ContextMenuProps = { taskId?: string; }; -const useStyles = makeStyles(() => ({ +const useStyles = makeStyles(() => ({ button: { color: ({ fontColor }) => fontColor, }, @@ -60,7 +61,7 @@ export const ContextMenu = (props: ContextMenuProps) => { onToggleButtonBar, taskId, } = props; - const { getPageTheme } = useTheme(); + const { getPageTheme } = useTheme(); const pageTheme = getPageTheme({ themeId: 'website' }); const classes = useStyles({ fontColor: pageTheme.fontColor }); const scaffolderApi = useApi(scaffolderApiRef); diff --git a/plugins/scaffolder/src/components/Router/Router.tsx b/plugins/scaffolder/src/components/Router/Router.tsx index dede51d676..c3d971bd11 100644 --- a/plugins/scaffolder/src/components/Router/Router.tsx +++ b/plugins/scaffolder/src/components/Router/Router.tsx @@ -133,6 +133,7 @@ export const Router = (props: PropsWithChildren) => { contextMenu={props.contextMenu} groups={props.groups} templateFilter={props.templateFilter} + headerOptions={props.headerOptions} /> } /> @@ -141,6 +142,7 @@ export const Router = (props: PropsWithChildren) => { element={ { > Categories - id="categories-picker" multiple options={availableTypes} diff --git a/plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPageContextMenu.tsx b/plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPageContextMenu.tsx index 5558b314da..f6151c227b 100644 --- a/plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPageContextMenu.tsx +++ b/plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPageContextMenu.tsx @@ -15,7 +15,6 @@ */ import { useRouteRef } from '@backstage/core-plugin-api'; -import { BackstageTheme } from '@backstage/theme'; import IconButton from '@material-ui/core/IconButton'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; @@ -35,7 +34,7 @@ import { scaffolderListTaskRouteRef, } from '../../routes'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ button: { color: theme.page.fontColor, }, diff --git a/plugins/scaffolder/src/legacy/TemplateCard/TemplateCard.tsx b/plugins/scaffolder/src/legacy/TemplateCard/TemplateCard.tsx index b4e68318d0..80f719bd36 100644 --- a/plugins/scaffolder/src/legacy/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder/src/legacy/TemplateCard/TemplateCard.tsx @@ -45,7 +45,6 @@ import { getEntitySourceLocation, } from '@backstage/plugin-catalog-react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; -import { BackstageTheme } from '@backstage/theme'; import { Box, Card, @@ -55,6 +54,7 @@ import { Chip, IconButton, makeStyles, + Theme, Tooltip, Typography, useTheme, @@ -65,7 +65,7 @@ import React from 'react'; import { selectedTemplateRouteRef, viewTechDocRouteRef } from '../../routes'; const useStyles = makeStyles< - BackstageTheme, + Theme, { fontColor: string; backgroundImage: string } >(theme => ({ cardHeader: { @@ -179,7 +179,7 @@ const DeprecationWarning = () => { export const TemplateCard = ({ template, deprecated }: TemplateCardProps) => { const app = useApp(); - const backstageTheme = useTheme(); + const backstageTheme = useTheme(); const templateRoute = useRouteRef(selectedTemplateRouteRef); const templateProps = getTemplateCardProps(template); const ownedByRelations = getEntityRelations( diff --git a/plugins/scaffolder/src/next/TemplateListPage/RegisterExistingButton.tsx b/plugins/scaffolder/src/next/TemplateListPage/RegisterExistingButton.tsx index 069a2cc6c5..eab7ce4485 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/RegisterExistingButton.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/RegisterExistingButton.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; import Button from '@material-ui/core/Button'; import IconButton from '@material-ui/core/IconButton'; import useMediaQuery from '@material-ui/core/useMediaQuery'; @@ -23,6 +22,7 @@ import { Link as RouterLink, LinkProps } from 'react-router-dom'; import AddCircleOutline from '@material-ui/icons/AddCircleOutline'; import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha'; import { usePermission } from '@backstage/plugin-permission-react'; +import { Theme } from '@material-ui/core'; /** * Properties for {@link RegisterExistingButton} @@ -42,7 +42,7 @@ export const RegisterExistingButton = (props: RegisterExistingButtonProps) => { const { allowed } = usePermission({ permission: catalogEntityCreatePermission, }); - const isXSScreen = useMediaQuery(theme => + const isXSScreen = useMediaQuery(theme => theme.breakpoints.down('xs'), ); diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx index 44390bc03c..b1508e43fc 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx @@ -67,6 +67,11 @@ export type TemplateListPageProps = { actions?: boolean; tasks?: boolean; }; + headerOptions?: { + pageTitleOverride?: string; + title?: string; + subtitle?: string; + }; }; const defaultGroup: TemplateGroupFilter = { @@ -93,6 +98,7 @@ export const TemplateListPage = (props: TemplateListPageProps) => { TemplateCardComponent, groups: givenGroups = [], templateFilter, + headerOptions, } = props; const navigate = useNavigate(); const editorLink = useRouteRef(editRouteRef); @@ -151,11 +157,12 @@ export const TemplateListPage = (props: TemplateListPageProps) => { return ( - +
diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index 3b14f2c07f..611330e76b 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -50,6 +50,11 @@ export type TemplateWizardPageProps = { }; layouts?: LayoutOptions[]; formProps?: FormProps; + headerOptions?: { + pageTitleOverride?: string; + title?: string; + subtitle?: string; + }; }; export const TemplateWizardPage = (props: TemplateWizardPageProps) => { @@ -87,6 +92,7 @@ export const TemplateWizardPage = (props: TemplateWizardPageProps) => { pageTitleOverride="Create a new component" title="Create a new component" subtitle="Create new software components using standard templates in your organization" + {...props.headerOptions} /> import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; -import { Extension } from '@backstage/frontend-plugin-api'; +import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { ListItemProps } from '@material-ui/core'; import { PortableSchema } from '@backstage/frontend-plugin-api'; import { SearchDocument } from '@backstage/plugin-search-common'; @@ -23,7 +23,9 @@ export function createSearchResultListItemExtension< TConfig extends { noTrack?: boolean; }, ->(options: SearchResultItemExtensionOptions): Extension; +>( + options: SearchResultItemExtensionOptions, +): ExtensionDefinition; // @alpha (undocumented) export type SearchResultItemExtensionComponent = < @@ -47,7 +49,8 @@ export type SearchResultItemExtensionOptions< noTrack?: boolean; }, > = { - id: string; + namespace?: string; + name?: string; attachTo?: { id: string; input: string; diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index bef3865069..fb34895fb1 100644 --- a/plugins/search-react/package.json +++ b/plugins/search-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-react", - "version": "1.7.2", + "version": "1.7.4-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -69,6 +69,7 @@ "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", "@backstage/frontend-app-api": "workspace:^", + "@backstage/frontend-test-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", diff --git a/plugins/search-react/src/alpha.test.tsx b/plugins/search-react/src/alpha.test.tsx index 5222e4dad5..3b05c61eb2 100644 --- a/plugins/search-react/src/alpha.test.tsx +++ b/plugins/search-react/src/alpha.test.tsx @@ -14,41 +14,28 @@ * limitations under the License. */ -import React from 'react'; - -import { render, screen } from '@testing-library/react'; - import { createExtensionInput, createPageExtension, - createPlugin, createSchemaFromZod, } from '@backstage/frontend-plugin-api'; +import { createExtensionTester } from '@backstage/frontend-test-utils'; import { SearchResult } from '@backstage/plugin-search-common'; -import { createApp } from '@backstage/frontend-app-api'; -import { MockConfigApi } from '@backstage/test-utils'; - +import { screen } from '@testing-library/react'; +import React from 'react'; import { BaseSearchResultListItemProps, createSearchResultListItemExtension, searchResultItemExtensionData as searchResultListItemExtensionData, } from './alpha'; -// TODO: Remove this mock when we have a permanent solution for nav items extensions -// The `GraphiQLIcon` used in "packages/frontend-app-api/src/extensions/CoreNav.tsx" file -// is throwing a "ReferenceError: ref is not defined" error during test -jest.mock('@backstage/plugin-graphiql', () => ({ - ...jest.requireActual('@backstage/plugin-graphiql'), - GraphiQLIcon: () => null, -})); - describe('createSearchResultListItemExtension', () => { it('Should use the correct result component', async () => { - type TechDocsSearchReasulListItemProps = BaseSearchResultListItemProps<{ + type TechDocsSearchResultListItemProps = BaseSearchResultListItemProps<{ lineClamp: number; }>; const TechDocsSearchResultItemComponent = ( - props: TechDocsSearchReasulListItemProps, + props: TechDocsSearchResultListItemProps, ) => (
TechDocs - Rank: {props.rank} - Line clamp: {props.lineClamp} @@ -57,13 +44,14 @@ describe('createSearchResultListItemExtension', () => { const TechDocsSearchResultItemExtension = createSearchResultListItemExtension({ - id: 'techdocs', - attachTo: { id: 'plugin.search.page', input: 'items' }, + namespace: 'techdocs', configSchema: createSchemaFromZod(z => - z.object({ - noTrack: z.boolean().default(true), - lineClamp: z.number().default(5), - }), + z + .object({ + noTrack: z.boolean().default(true), + lineClamp: z.number().default(5), + }) + .default({}), ), predicate: result => result.type === 'techdocs', component: @@ -78,14 +66,13 @@ describe('createSearchResultListItemExtension', () => { const ExploreSearchResultItemExtension = createSearchResultListItemExtension({ - id: 'explore', - attachTo: { id: 'plugin.search.page', input: 'items' }, + namespace: 'explore', predicate: result => result.type === 'explore', component: async () => ExploreSearchResultItemComponent, }); const SearchPageExtension = createPageExtension({ - id: 'plugin.search.page', + namespace: 'search', defaultPath: '/', inputs: { items: createExtensionInput({ @@ -128,10 +115,10 @@ describe('createSearchResultListItemExtension', () => { ); const getResultItemComponent = (result: SearchResult) => { - const value = inputs.items.find(({ item }) => - item?.predicate?.(result), + const value = inputs.items.find(item => + item?.output.item.predicate?.(result), ); - return value?.item.component ?? DefaultResultItem; + return value?.output.item.component ?? DefaultResultItem; }; const Component = () => { @@ -158,34 +145,15 @@ describe('createSearchResultListItemExtension', () => { }, }); - const SearchPlugin = createPlugin({ - id: 'search.plugin', - extensions: [ - SearchPageExtension, - ExploreSearchResultItemExtension, - TechDocsSearchResultItemExtension, - ], - }); - - const app = createApp({ - features: [SearchPlugin], - configLoader: async () => - new MockConfigApi({ - app: { - extensions: [ - { - 'plugin.search.result.item.techdocs': { - config: { - lineClamp: 3, - }, - }, - }, - ], - }, - }), - }); - - render(app.createRoot()); + createExtensionTester(SearchPageExtension) + .add(TechDocsSearchResultItemExtension, { + // TODO(Rugvip): We need to make the config input type available for use here + config: { + lineClamp: 3, + } as any, + }) + .add(ExploreSearchResultItemExtension) + .render(); expect(await screen.findByText(/Search Page/)).toBeInTheDocument(); diff --git a/plugins/search-react/src/alpha.tsx b/plugins/search-react/src/alpha.tsx index 80e464fe4e..c733e2ee9f 100644 --- a/plugins/search-react/src/alpha.tsx +++ b/plugins/search-react/src/alpha.tsx @@ -58,9 +58,13 @@ export type SearchResultItemExtensionOptions< TConfig extends { noTrack?: boolean }, > = { /** - * The extension id. + * The extension namespace. */ - id: string; + namespace?: string; + /** + * The extension name. + */ + name?: string; /** * The extension attachment point (e.g., search modal or page). */ @@ -86,8 +90,6 @@ export type SearchResultItemExtensionOptions< export function createSearchResultListItemExtension< TConfig extends { noTrack?: boolean }, >(options: SearchResultItemExtensionOptions) { - const id = `plugin.search.result.item.${options.id}`; - const configSchema = 'configSchema' in options ? options.configSchema @@ -98,16 +100,18 @@ export function createSearchResultListItemExtension< ) as PortableSchema); return createExtension({ - id, + kind: 'search-result-list-item', + namespace: options.namespace, + name: options.name, attachTo: options.attachTo ?? { - id: 'plugin.search.page', + id: 'page:search', input: 'items', }, configSchema, output: { item: searchResultItemExtensionData, }, - factory({ config, source }) { + factory({ config, node }) { const ExtensionComponent = lazy(() => options .component({ config }) @@ -118,7 +122,7 @@ export function createSearchResultListItemExtension< item: { predicate: options.predicate, component: props => ( - + ; +export const SearchApi: ExtensionDefinition<{}>; // @alpha (undocumented) -export const SearchNavItem: Extension<{ +export const SearchNavItem: ExtensionDefinition<{ title: string; }>; // @alpha (undocumented) -export const SearchPage: Extension<{ +export const SearchPage: ExtensionDefinition<{ path: string; noTrack: boolean; }>; diff --git a/plugins/search/package.json b/plugins/search/package.json index a856804a08..33c78cfbc1 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search", "description": "The Backstage plugin that provides your backstage app with search", - "version": "1.4.2", + "version": "1.4.4-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index ef11828c71..7899fb2ae1 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -67,7 +67,10 @@ import { rootRouteRef } from './plugin'; import { SearchClient } from './apis'; import { SearchType } from './components/SearchType'; import { UrlUpdater } from './components/SearchPage/SearchPage'; -import { convertLegacyRouteRef } from '@backstage/core-compat-api'; +import { + compatWrapper, + convertLegacyRouteRef, +} from '@backstage/core-compat-api'; /** @alpha */ export const SearchApi = createApiExtension({ @@ -98,7 +101,6 @@ const useSearchPageStyles = makeStyles((theme: Theme) => ({ /** @alpha */ export const SearchPage = createPageExtension({ - id: 'plugin.search.page', routeRef: convertLegacyRouteRef(rootRouteRef), configSchema: createSchemaFromZod(z => z.object({ @@ -113,8 +115,10 @@ export const SearchPage = createPageExtension({ }, loader: async ({ config, inputs }) => { const getResultItemComponent = (result: SearchResult) => { - const value = inputs.items.find(({ item }) => item?.predicate?.(result)); - return value?.item.component ?? DefaultResultListItem; + const value = inputs.items.find(item => + item?.output.item.predicate?.(result), + ); + return value?.output.item.component ?? DefaultResultListItem; }; const Component = () => { @@ -224,18 +228,17 @@ export const SearchPage = createPageExtension({ ); }; - return ( + return compatWrapper( - + , ); }, }); /** @alpha */ export const SearchNavItem = createNavItemExtension({ - id: 'plugin.search.nav.index', routeRef: convertLegacyRouteRef(rootRouteRef), title: 'Search', icon: SearchIcon, diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index 0c57922efc..f6c69ebbc5 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-sentry +## 0.5.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.5.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.5.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.5.11 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index f423cdcb42..efd86f5d41 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sentry", "description": "A Backstage plugin that integrates towards Sentry", - "version": "0.5.11", + "version": "0.5.13-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sentry/src/components/ErrorCell/ErrorCell.tsx b/plugins/sentry/src/components/ErrorCell/ErrorCell.tsx index 14e0213bfa..2a0e0fbb69 100644 --- a/plugins/sentry/src/components/ErrorCell/ErrorCell.tsx +++ b/plugins/sentry/src/components/ErrorCell/ErrorCell.tsx @@ -18,13 +18,13 @@ import React from 'react'; import { SentryIssue } from '../../api'; import { Typography } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; -import { BackstageTheme } from '@backstage/theme'; import { Link } from '@backstage/core-components'; function stripText(text: string, maxLength: number) { return text.length > maxLength ? `${text.slice(0, maxLength)}...` : text; } -const useStyles = makeStyles(theme => ({ + +const useStyles = makeStyles(theme => ({ root: { minWidth: 260, position: 'relative', diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index 6521481a82..3edd1b203c 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-shortcuts +## 0.3.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/types@1.1.1 + +## 0.3.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + +## 0.3.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + ## 0.3.16 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index ebcfff07b1..7988358d72 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-shortcuts", "description": "A Backstage plugin that provides a shortcuts feature to the sidebar", - "version": "0.3.16", + "version": "0.3.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube-backend/CHANGELOG.md b/plugins/sonarqube-backend/CHANGELOG.md index 0248e8a5c0..ede6beed67 100644 --- a/plugins/sonarqube-backend/CHANGELOG.md +++ b/plugins/sonarqube-backend/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-sonarqube-backend +## 0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## 0.2.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + +## 0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.2.9 ### Patch Changes diff --git a/plugins/sonarqube-backend/package.json b/plugins/sonarqube-backend/package.json index b1f5ff09dc..7ce9402edb 100644 --- a/plugins/sonarqube-backend/package.json +++ b/plugins/sonarqube-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-backend", - "version": "0.2.9", + "version": "0.2.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube-react/CHANGELOG.md b/plugins/sonarqube-react/CHANGELOG.md index 08a6d8cb8b..ff15e247ae 100644 --- a/plugins/sonarqube-react/CHANGELOG.md +++ b/plugins/sonarqube-react/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-sonarqube-react +## 0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/catalog-model@1.4.3 + +## 0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.1.10 ### Patch Changes diff --git a/plugins/sonarqube-react/alpha-api-report.md b/plugins/sonarqube-react/alpha-api-report.md deleted file mode 100644 index 4fad469d12..0000000000 --- a/plugins/sonarqube-react/alpha-api-report.md +++ /dev/null @@ -1,65 +0,0 @@ -## API Report File for "@backstage/plugin-sonarqube-react" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { ApiRef } from '@backstage/core-plugin-api'; -import { Entity } from '@backstage/catalog-model'; - -// @public (undocumented) -export interface FindingSummary { - // (undocumented) - getComponentMeasuresUrl: SonarUrlProcessorFunc; - // (undocumented) - getIssuesUrl: SonarUrlProcessorFunc; - // (undocumented) - getSecurityHotspotsUrl: () => string; - // (undocumented) - lastAnalysis: string; - // (undocumented) - metrics: Metrics; - // (undocumented) - projectUrl: string; -} - -// @public (undocumented) -export type MetricKey = - | 'alert_status' - | 'bugs' - | 'reliability_rating' - | 'vulnerabilities' - | 'security_rating' - | 'code_smells' - | 'sqale_rating' - | 'security_hotspots_reviewed' - | 'security_review_rating' - | 'coverage' - | 'duplicated_lines_density'; - -// @public -export type Metrics = { - [key in MetricKey]: string | undefined; -}; - -// @public (undocumented) -export type SonarQubeApi = { - getFindingSummary(options: { - componentKey?: string; - projectInstance?: string; - }): Promise; -}; - -// @public (undocumented) -export const sonarQubeApiRef: ApiRef; - -// @public (undocumented) -export type SonarUrlProcessorFunc = (identifier: string) => string; - -// @public -export const useProjectInfo: (entity: Entity) => { - projectInstance: string | undefined; - projectKey: string | undefined; -}; - -// (No @packageDocumentation comment for this package) -``` diff --git a/plugins/sonarqube-react/package.json b/plugins/sonarqube-react/package.json index 5da357b655..c5c90158a1 100644 --- a/plugins/sonarqube-react/package.json +++ b/plugins/sonarqube-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-sonarqube-react", - "version": "0.1.10", + "version": "0.1.11-next.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index c91fc757ff..71fa53dae9 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-sonarqube +## 0.7.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-sonarqube-react@0.1.11-next.1 + +## 0.7.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-sonarqube-react@0.1.11-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.7.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-sonarqube-react@0.1.11-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.7.8 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 7d27fdfe83..bd94e1c56d 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.7.8", + "version": "0.7.10-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index fcf30d5d34..6aa345e184 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-splunk-on-call +## 0.4.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.4.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.5.0-next.0 + +## 0.4.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + ## 0.4.15 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index f4c8eb18c7..e481bd469f 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-splunk-on-call", "description": "A Backstage plugin that integrates towards Splunk On-Call", - "version": "0.4.15", + "version": "0.4.17-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow-backend/CHANGELOG.md b/plugins/stack-overflow-backend/CHANGELOG.md index 40dddfb5a2..1308080a6d 100644 --- a/plugins/stack-overflow-backend/CHANGELOG.md +++ b/plugins/stack-overflow-backend/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-stack-overflow-backend +## 0.2.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-search-backend-module-stack-overflow-collator@0.1.1-next.2 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.8 + +## 0.2.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/plugin-search-backend-module-stack-overflow-collator@0.1.1-next.1 + - @backstage/plugin-search-common@1.2.8 + +## 0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-search-backend-module-stack-overflow-collator@0.1.1-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.8 + ## 0.2.11 ### Patch Changes diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index 07cdecc6b7..bbbf1b6a79 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-stack-overflow-backend", "description": "Deprecated, consider using @backstage/plugin-search-backend-module-stack-overflow-collator instead", - "version": "0.2.11", + "version": "0.2.12-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow/CHANGELOG.md b/plugins/stack-overflow/CHANGELOG.md index 18cd1632df..d8d172d0ff 100644 --- a/plugins/stack-overflow/CHANGELOG.md +++ b/plugins/stack-overflow/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-stack-overflow +## 0.1.23-next.2 + +### Patch Changes + +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-home-react@0.1.6-next.2 + - @backstage/plugin-search-common@1.2.8 + +## 0.1.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/plugin-home-react@0.1.6-next.1 + - @backstage/config@1.1.1 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-search-common@1.2.8 + +## 0.1.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/plugin-home-react@0.1.6-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.8 + ## 0.1.22 ### Patch Changes diff --git a/plugins/stack-overflow/alpha-api-report.md b/plugins/stack-overflow/api-report-alpha.md similarity index 100% rename from plugins/stack-overflow/alpha-api-report.md rename to plugins/stack-overflow/api-report-alpha.md diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index b32ff45338..8a3501a422 100644 --- a/plugins/stack-overflow/package.json +++ b/plugins/stack-overflow/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow", - "version": "0.1.22", + "version": "0.1.23-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/stack-overflow/src/alpha.tsx b/plugins/stack-overflow/src/alpha.tsx index 3708271ef1..f34c91f78b 100644 --- a/plugins/stack-overflow/src/alpha.tsx +++ b/plugins/stack-overflow/src/alpha.tsx @@ -33,7 +33,6 @@ const StackOverflowApi = createApiExtension({ /** @alpha */ const StackOverflowSearchResultListItem = createSearchResultListItemExtension({ - id: 'stack-overflow', predicate: result => result.type === 'stack-overflow', component: () => import('./search/StackOverflowSearchResultListItem').then( diff --git a/plugins/stackstorm/CHANGELOG.md b/plugins/stackstorm/CHANGELOG.md index ea46e02af5..8d10d814a8 100644 --- a/plugins/stackstorm/CHANGELOG.md +++ b/plugins/stackstorm/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-stackstorm +## 0.1.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.1.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/errors@1.2.3 + ## 0.1.8 ### Patch Changes diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json index 030ff0dd17..95e5606edb 100644 --- a/plugins/stackstorm/package.json +++ b/plugins/stackstorm/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-stackstorm", "description": "A Backstage plugin that integrates towards StackStorm", - "version": "0.1.8", + "version": "0.1.9-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md index fa3c0ea158..b4b09d1d7b 100644 --- a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md +++ b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-tech-insights-backend-module-jsonfc +## 0.1.40-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-tech-insights-common@0.2.12 + - @backstage/plugin-tech-insights-node@0.4.14-next.2 + +## 0.1.40-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-tech-insights-common@0.2.12 + - @backstage/plugin-tech-insights-node@0.4.14-next.1 + +## 0.1.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-tech-insights-node@0.4.14-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.1.39 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index 03b425e326..f78f4f7530 100644 --- a/plugins/tech-insights-backend-module-jsonfc/package.json +++ b/plugins/tech-insights-backend-module-jsonfc/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-backend-module-jsonfc", - "version": "0.1.39", + "version": "0.1.40-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-backend/CHANGELOG.md b/plugins/tech-insights-backend/CHANGELOG.md index a16c22a455..d8d3c0f933 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,50 @@ # @backstage/plugin-tech-insights-backend +## 0.5.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + - @backstage/plugin-tech-insights-node@0.4.14-next.2 + +## 0.5.22-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + - @backstage/plugin-tech-insights-node@0.4.14-next.1 + +## 0.5.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/plugin-tech-insights-node@0.4.14-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.5.21 ### Patch Changes diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index c7872c36a0..6e446635cb 100644 --- a/plugins/tech-insights-backend/package.json +++ b/plugins/tech-insights-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-backend", - "version": "0.5.21", + "version": "0.5.22-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-node/CHANGELOG.md b/plugins/tech-insights-node/CHANGELOG.md index 62171b8a37..36199d726a 100644 --- a/plugins/tech-insights-node/CHANGELOG.md +++ b/plugins/tech-insights-node/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-tech-insights-node +## 0.4.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## 0.4.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## 0.4.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.4.13 ### Patch Changes diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index fc1c3d7491..c6e6cf2286 100644 --- a/plugins/tech-insights-node/package.json +++ b/plugins/tech-insights-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights-node", - "version": "0.4.13", + "version": "0.4.14-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights/CHANGELOG.md b/plugins/tech-insights/CHANGELOG.md index 44b6f4bf0a..6c18551001 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/plugin-tech-insights +## 0.3.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## 0.3.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## 0.3.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.3.18 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index 54b6a44612..23445109b0 100644 --- a/plugins/tech-insights/package.json +++ b/plugins/tech-insights/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-tech-insights", - "version": "0.3.18", + "version": "0.3.20-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index 583e51de7d..38e4e5a025 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-tech-radar +## 0.6.11-next.3 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + +## 0.6.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/theme@0.5.0-next.0 + +## 0.6.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + +## 0.6.11-next.0 + +### Patch Changes + +- 03d0b6dcdc: The `convertLegacyRouteRef` utility used by the alpha exports is now imported from `@backstage/core-compat-api`. +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + ## 0.6.10 ### Patch Changes diff --git a/plugins/tech-radar/alpha-api-report.md b/plugins/tech-radar/api-report-alpha.md similarity index 75% rename from plugins/tech-radar/alpha-api-report.md rename to plugins/tech-radar/api-report-alpha.md index da8f12cf0e..bcc9142223 100644 --- a/plugins/tech-radar/alpha-api-report.md +++ b/plugins/tech-radar/api-report-alpha.md @@ -4,7 +4,7 @@ ```ts import { BackstagePlugin } from '@backstage/frontend-plugin-api'; -import { Extension } from '@backstage/frontend-plugin-api'; +import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) @@ -17,7 +17,10 @@ const _default: BackstagePlugin< export default _default; // @alpha (undocumented) -export const TechRadarPage: Extension<{ +export const sampleTechRadarApi: ExtensionDefinition<{}>; + +// @alpha (undocumented) +export const TechRadarPage: ExtensionDefinition<{ height: number; width: number; title: string; diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index a7d8a41e8e..3718e2960a 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-tech-radar", "description": "A Backstage plugin that lets you display a Tech Radar for your organization", - "version": "0.6.10", + "version": "0.6.11-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -68,6 +68,7 @@ "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", + "@backstage/frontend-test-utils": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", diff --git a/plugins/tech-radar/src/alpha.test.tsx b/plugins/tech-radar/src/alpha.test.tsx new file mode 100644 index 0000000000..37d39c412b --- /dev/null +++ b/plugins/tech-radar/src/alpha.test.tsx @@ -0,0 +1,34 @@ +/* + * 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. + */ + +import { createExtensionTester } from '@backstage/frontend-test-utils'; +import { screen } from '@testing-library/react'; +import { TechRadarPage, sampleTechRadarApi } from './alpha'; + +describe('TechRadarPage', () => { + beforeAll(() => { + Object.defineProperty(window.SVGElement.prototype, 'getBBox', { + value: () => ({ width: 100, height: 100 }), + configurable: true, + }); + }); + + it('renders without exploding', async () => { + createExtensionTester(TechRadarPage).add(sampleTechRadarApi).render(); + + await expect(screen.findByText('Tech Radar')).resolves.toBeInTheDocument(); + }); +}); diff --git a/plugins/tech-radar/src/alpha.tsx b/plugins/tech-radar/src/alpha.tsx index f9a34e2158..dfed6d3af0 100644 --- a/plugins/tech-radar/src/alpha.tsx +++ b/plugins/tech-radar/src/alpha.tsx @@ -24,12 +24,14 @@ import { import React from 'react'; import { techRadarApiRef } from './api'; import { SampleTechRadarApi } from './sample'; -import { convertLegacyRouteRef } from '@backstage/core-compat-api'; +import { + compatWrapper, + convertLegacyRouteRef, +} from '@backstage/core-compat-api'; import { rootRouteRef } from './plugin'; /** @alpha */ export const TechRadarPage = createPageExtension({ - id: 'plugin.techradar.page', defaultPath: '/tech-radar', routeRef: convertLegacyRouteRef(rootRouteRef), configSchema: createSchemaFromZod(z => @@ -45,14 +47,14 @@ export const TechRadarPage = createPageExtension({ }), ), loader: ({ config }) => - import('./components').then(m => ), + import('./components').then(m => + compatWrapper(), + ), }); -const sampleTechRadarApi = createApiExtension({ - api: techRadarApiRef, - factory() { - return createApiFactory(techRadarApiRef, new SampleTechRadarApi()); - }, +/** @alpha */ +export const sampleTechRadarApi = createApiExtension({ + factory: createApiFactory(techRadarApiRef, new SampleTechRadarApi()), }); /** @alpha */ diff --git a/plugins/tech-radar/src/components/RadarBubble/RadarBubble.tsx b/plugins/tech-radar/src/components/RadarBubble/RadarBubble.tsx index c114744a40..a904b981ca 100644 --- a/plugins/tech-radar/src/components/RadarBubble/RadarBubble.tsx +++ b/plugins/tech-radar/src/components/RadarBubble/RadarBubble.tsx @@ -15,7 +15,7 @@ */ import React, { useRef, useLayoutEffect } from 'react'; -import { makeStyles, Theme } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core'; export type Props = { visible: boolean; @@ -24,7 +24,7 @@ export type Props = { y: number; }; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ bubble: { pointerEvents: 'none', userSelect: 'none', diff --git a/plugins/tech-radar/src/components/RadarEntry/RadarEntry.tsx b/plugins/tech-radar/src/components/RadarEntry/RadarEntry.tsx index b7f5ea5962..996b8d1040 100644 --- a/plugins/tech-radar/src/components/RadarEntry/RadarEntry.tsx +++ b/plugins/tech-radar/src/components/RadarEntry/RadarEntry.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { makeStyles, Theme } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core'; import { WithLink } from '../../utils/components'; import { RadarDescription } from '../RadarDescription'; import type { EntrySnapshot } from '../../utils/types'; @@ -37,7 +37,7 @@ export type Props = { onClick?: (event: React.MouseEvent) => void; }; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ text: { pointerEvents: 'none', userSelect: 'none', diff --git a/plugins/tech-radar/src/components/RadarGrid/RadarGrid.tsx b/plugins/tech-radar/src/components/RadarGrid/RadarGrid.tsx index 8f796620e0..8f4f8acc78 100644 --- a/plugins/tech-radar/src/components/RadarGrid/RadarGrid.tsx +++ b/plugins/tech-radar/src/components/RadarGrid/RadarGrid.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { makeStyles, Theme } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core'; import type { Ring } from '../../utils/types'; export type Props = { @@ -23,7 +23,7 @@ export type Props = { rings: Ring[]; }; -const useStyles = makeStyles( +const useStyles = makeStyles( theme => ({ ring: { fill: 'none', diff --git a/plugins/tech-radar/src/components/RadarLegend/RadarLegend.tsx b/plugins/tech-radar/src/components/RadarLegend/RadarLegend.tsx index d74cde1d40..0a7a69b73c 100644 --- a/plugins/tech-radar/src/components/RadarLegend/RadarLegend.tsx +++ b/plugins/tech-radar/src/components/RadarLegend/RadarLegend.tsx @@ -13,13 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { makeStyles, Theme } from '@material-ui/core'; + +import { makeStyles } from '@material-ui/core'; import React from 'react'; import { RadarLegendQuadrant } from './RadarLegendQuadrant'; import { RadarLegendProps } from './types'; import { setupSegments } from './utils'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ quadrant: { height: '100%', width: '100%', diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index 7ac18d121a..8a435e5813 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,65 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.25-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-techdocs@1.9.2-next.3 + - @backstage/plugin-catalog@1.16.0-next.3 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/test-utils@1.4.6-next.2 + - @backstage/plugin-techdocs-react@1.1.14-next.2 + +## 1.0.25-next.2 + +### Patch Changes + +- 5d796829bb: Remove unnecessary catalog dependency +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-catalog@1.16.0-next.2 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/test-utils@1.4.6-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/plugin-techdocs@1.9.2-next.2 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-techdocs-react@1.1.14-next.1 + - @backstage/theme@0.5.0-next.0 + +## 1.0.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.16.0-next.1 + - @backstage/plugin-techdocs@1.9.2-next.1 + +## 1.0.25-next.0 + +### Patch Changes + +- 3f354e68f4: Move `@testing-library/react` to be a `peerDependency` +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-catalog@1.16.0-next.0 + - @backstage/plugin-techdocs@1.9.2-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/test-utils@1.4.6-next.0 + - @backstage/plugin-techdocs-react@1.1.14-next.0 + ## 1.0.23 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index a85e803ae5..24dcdf042f 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-addons-test-utils", - "version": "1.0.23", + "version": "1.0.25-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,6 +38,7 @@ "@backstage/core-plugin-api": "workspace:^", "@backstage/integration-react": "workspace:^", "@backstage/plugin-catalog": "workspace:^", + "@backstage/plugin-catalog-react": "workspace:^", "@backstage/plugin-search-react": "workspace:^", "@backstage/plugin-techdocs": "workspace:^", "@backstage/plugin-techdocs-react": "workspace:^", @@ -46,12 +47,12 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", - "@testing-library/react": "^14.0.0", "@types/react": "^16.13.1 || ^17.0.0", "react-use": "^17.2.4", "testing-library__dom": "^7.29.4-beta.1" }, "peerDependencies": { + "@testing-library/react": "^12.1.3 || ^13.0.0 || ^14.0.0", "react": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" diff --git a/plugins/techdocs-addons-test-utils/src/test-utils.tsx b/plugins/techdocs-addons-test-utils/src/test-utils.tsx index 865e8c0d3b..518e469e1e 100644 --- a/plugins/techdocs-addons-test-utils/src/test-utils.tsx +++ b/plugins/techdocs-addons-test-utils/src/test-utils.tsx @@ -34,7 +34,7 @@ import { techdocsStorageApiRef, } from '@backstage/plugin-techdocs-react'; import { TechDocsReaderPage, techdocsPlugin } from '@backstage/plugin-techdocs'; -import { catalogPlugin } from '@backstage/plugin-catalog'; +import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { searchApiRef } from '@backstage/plugin-search-react'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; @@ -259,7 +259,7 @@ export class TechDocsAddonTester { mountedRoutes: { '/docs': techdocsPlugin.routes.root, '/docs/:namespace/:kind/:name/*': techdocsPlugin.routes.docRoot, - '/catalog/:namespace/:kind/:name': catalogPlugin.routes.catalogEntity, + '/catalog/:namespace/:kind/:name': entityRouteRef, }, }); } diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 871dd55b8b..d923e0a0e6 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,59 @@ # @backstage/plugin-techdocs-backend +## 1.9.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-common@1.2.8 + - @backstage/plugin-techdocs-node@1.11.0-next.2 + +## 1.9.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/plugin-techdocs-node@1.11.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.1 + - @backstage/plugin-search-common@1.2.8 + +## 1.9.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-techdocs-node@1.11.0-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.12-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-common@1.0.18 + - @backstage/plugin-permission-common@0.7.10 + - @backstage/plugin-search-common@1.2.8 + ## 1.9.0 ### Minor Changes diff --git a/plugins/techdocs-backend/alpha-api-report.md b/plugins/techdocs-backend/api-report-alpha.md similarity index 100% rename from plugins/techdocs-backend/alpha-api-report.md rename to plugins/techdocs-backend/api-report-alpha.md diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 31221c856f..80bf7c1bdc 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-backend", "description": "The Backstage backend plugin that renders technical documentation for your components", - "version": "1.9.0", + "version": "1.9.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index 62c50dc90d..852008a4d1 100644 --- a/plugins/techdocs-module-addons-contrib/CHANGELOG.md +++ b/plugins/techdocs-module-addons-contrib/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-techdocs-module-addons-contrib +## 1.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-techdocs-react@1.1.14-next.2 + +## 1.1.3-next.1 + +### Patch Changes + +- a518c5a25b: Updated dependency `@react-hookz/web` to `^23.0.0`. +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-techdocs-react@1.1.14-next.1 + - @backstage/theme@0.5.0-next.0 + +## 1.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/plugin-techdocs-react@1.1.14-next.0 + ## 1.1.2 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index d3fa7000e6..2899e1f1ae 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-module-addons-contrib", "description": "Plugin module for contributed TechDocs Addons", - "version": "1.1.2", + "version": "1.1.3-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -43,7 +43,7 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", - "@react-hookz/web": "^20.0.0", + "@react-hookz/web": "^23.0.0", "git-url-parse": "^13.0.0", "photoswipe": "^5.3.7", "react-use": "^17.2.4" diff --git a/plugins/techdocs-node/CHANGELOG.md b/plugins/techdocs-node/CHANGELOG.md index 10a9538e63..5cd95049c6 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,54 @@ # @backstage/plugin-techdocs-node +## 1.11.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-aws-node@0.1.8 + - @backstage/plugin-search-common@1.2.8 + +## 1.11.0-next.1 + +### Patch Changes + +- 99fb54183b: Updated dependency `@azure/identity` to `^4.0.0`. +- 2666675457: Updated dependency `@google-cloud/storage` to `^7.0.0`. +- 4f773c15f6: Bumped the default TechDocs docker image version to the latest which was released several month ago +- Updated dependencies + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/plugin-search-common@1.2.8 + +## 1.11.0-next.0 + +### Minor Changes + +- d15d483a49: Add command `--runAsDefaultUser` for `@techdocs/cli generate` to bypass running the docker builds as host user for macOS and Linux. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration-aws-node@0.1.8 + - @backstage/plugin-search-common@1.2.8 + ## 1.10.0 ### Minor Changes diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index c267574642..5203d30faa 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -62,6 +62,7 @@ export type GeneratorRunOptions = { siteOptions?: { name?: string; }; + runAsDefaultUser?: boolean; }; // @public @@ -263,7 +264,7 @@ export class TechdocsGenerator implements GeneratorBase { config: Config; scmIntegrations: ScmIntegrationRegistry; }); - static readonly defaultDockerImage = 'spotify/techdocs:v1.2.1'; + static readonly defaultDockerImage = 'spotify/techdocs:v1.2.3'; static fromConfig( config: Config, options: GeneratorOptions, diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index 0fc5512e1b..31b5f01132 100644 --- a/plugins/techdocs-node/package.json +++ b/plugins/techdocs-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-node", "description": "Common node.js functionalities for TechDocs, to be shared between techdocs-backend plugin and techdocs-cli", - "version": "1.10.0", + "version": "1.11.0-next.2", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -43,7 +43,7 @@ "@aws-sdk/credential-providers": "^3.350.0", "@aws-sdk/lib-storage": "^3.350.0", "@aws-sdk/types": "^3.347.0", - "@azure/identity": "^3.2.1", + "@azure/identity": "^4.0.0", "@azure/storage-blob": "^12.5.0", "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", @@ -53,7 +53,7 @@ "@backstage/integration": "workspace:^", "@backstage/integration-aws-node": "workspace:^", "@backstage/plugin-search-common": "workspace:^", - "@google-cloud/storage": "^6.0.0", + "@google-cloud/storage": "^7.0.0", "@smithy/node-http-handler": "^2.1.7", "@trendyol-js/openstack-swift-sdk": "^0.0.6", "@types/express": "^4.17.6", diff --git a/plugins/techdocs-node/src/stages/generate/techdocs.ts b/plugins/techdocs-node/src/stages/generate/techdocs.ts index b1baf214b3..c5130a3f8f 100644 --- a/plugins/techdocs-node/src/stages/generate/techdocs.ts +++ b/plugins/techdocs-node/src/stages/generate/techdocs.ts @@ -53,7 +53,7 @@ export class TechdocsGenerator implements GeneratorBase { * The default docker image (and version) used to generate content. Public * and static so that techdocs-node consumers can use the same version. */ - public static readonly defaultDockerImage = 'spotify/techdocs:v1.2.1'; + public static readonly defaultDockerImage = 'spotify/techdocs:v1.2.3'; private readonly logger: Logger; private readonly containerRunner?: ContainerRunner; private readonly options: GeneratorConfig; @@ -97,6 +97,7 @@ export class TechdocsGenerator implements GeneratorBase { logger: childLogger, logStream, siteOptions, + runAsDefaultUser, } = options; // Do some updates to mkdocs.yml before generating docs e.g. adding repo_url @@ -171,6 +172,7 @@ export class TechdocsGenerator implements GeneratorBase { // write to, otherwise they will just fail trying to write to / envVars: { HOME: '/tmp' }, pullImage: this.options.pullImage, + defaultUser: runAsDefaultUser, }); childLogger.info( `Successfully generated docs from ${inputDir} into ${outputDir} using techdocs-container`, diff --git a/plugins/techdocs-node/src/stages/generate/types.ts b/plugins/techdocs-node/src/stages/generate/types.ts index eca1057914..149c3c2195 100644 --- a/plugins/techdocs-node/src/stages/generate/types.ts +++ b/plugins/techdocs-node/src/stages/generate/types.ts @@ -64,6 +64,7 @@ export type GeneratorRunOptions = { logger: Logger; logStream?: Writable; siteOptions?: { name?: string }; + runAsDefaultUser?: boolean; }; /** diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index 21cdbed9d1..cd1a166852 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-techdocs-react +## 1.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/version-bridge@1.0.7 + +## 1.1.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/version-bridge@1.0.7 + +## 1.1.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/version-bridge@1.0.7 + ## 1.1.13 ### Patch Changes diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 6fba453755..796dcf6ddc 100644 --- a/plugins/techdocs-react/package.json +++ b/plugins/techdocs-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-react", "description": "Shared frontend utilities for TechDocs and Addons", - "version": "1.1.13", + "version": "1.1.14-next.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 0a9e2c9a73..1a96cdb437 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,75 @@ # @backstage/plugin-techdocs +## 1.9.2-next.3 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/plugin-search-react@1.7.4-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-search-common@1.2.8 + - @backstage/plugin-techdocs-react@1.1.14-next.2 + +## 1.9.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/plugin-search-react@1.7.4-next.1 + - @backstage/integration@1.8.0-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/integration-react@1.1.22-next.1 + - @backstage/plugin-techdocs-react@1.1.14-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/plugin-search-common@1.2.8 + +## 1.9.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + +## 1.9.2-next.0 + +### Patch Changes + +- 03d0b6dcdc: The `convertLegacyRouteRef` utility used by the alpha exports is now imported from `@backstage/core-compat-api`. +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/plugin-search-react@1.7.4-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/integration-react@1.1.22-next.0 + - @backstage/plugin-techdocs-react@1.1.14-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-common@1.2.8 + ## 1.9.0 ### Minor Changes diff --git a/plugins/techdocs/alpha-api-report.md b/plugins/techdocs/api-report-alpha.md similarity index 83% rename from plugins/techdocs/alpha-api-report.md rename to plugins/techdocs/api-report-alpha.md index 2b63d6e691..afc3202a43 100644 --- a/plugins/techdocs/alpha-api-report.md +++ b/plugins/techdocs/api-report-alpha.md @@ -4,7 +4,7 @@ ```ts import { BackstagePlugin } from '@backstage/frontend-plugin-api'; -import { Extension } from '@backstage/frontend-plugin-api'; +import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) @@ -23,7 +23,7 @@ const _default: BackstagePlugin< export default _default; // @alpha (undocumented) -export const TechDocsSearchResultListItemExtension: Extension<{ +export const TechDocsSearchResultListItemExtension: ExtensionDefinition<{ lineClamp: number; noTrack: boolean; asListItem: boolean; diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 19f3883565..877b9b1f20 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs", "description": "The Backstage plugin that renders technical documentation for your components", - "version": "1.9.0", + "version": "1.9.2-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs/src/alpha.tsx b/plugins/techdocs/src/alpha.tsx index 533b4cb524..26891b23f0 100644 --- a/plugins/techdocs/src/alpha.tsx +++ b/plugins/techdocs/src/alpha.tsx @@ -31,7 +31,10 @@ import { fetchApiRef, identityApiRef, } from '@backstage/core-plugin-api'; -import { convertLegacyRouteRef } from '@backstage/core-compat-api'; +import { + compatWrapper, + convertLegacyRouteRef, +} from '@backstage/core-compat-api'; import { techdocsApiRef, techdocsStorageApiRef, @@ -46,53 +49,45 @@ import { createEntityContentExtension } from '@backstage/plugin-catalog-react/al /** @alpha */ const techDocsStorage = createApiExtension({ - api: techdocsStorageApiRef, - - factory() { - return createApiFactory({ - api: techdocsStorageApiRef, - deps: { - configApi: configApiRef, - discoveryApi: discoveryApiRef, - identityApi: identityApiRef, - fetchApi: fetchApiRef, - }, - factory: ({ configApi, discoveryApi, identityApi, fetchApi }) => - new TechDocsStorageClient({ - configApi, - discoveryApi, - identityApi, - fetchApi, - }), - }); - }, + factory: createApiFactory({ + api: techdocsStorageApiRef, + deps: { + configApi: configApiRef, + discoveryApi: discoveryApiRef, + identityApi: identityApiRef, + fetchApi: fetchApiRef, + }, + factory: ({ configApi, discoveryApi, identityApi, fetchApi }) => + new TechDocsStorageClient({ + configApi, + discoveryApi, + identityApi, + fetchApi, + }), + }), }); /** @alpha */ const techDocsClient = createApiExtension({ - api: techdocsApiRef, - factory() { - return createApiFactory({ - api: techdocsApiRef, - deps: { - configApi: configApiRef, - discoveryApi: discoveryApiRef, - fetchApi: fetchApiRef, - }, - factory: ({ configApi, discoveryApi, fetchApi }) => - new TechDocsClient({ - configApi, - discoveryApi, - fetchApi, - }), - }); - }, + factory: createApiFactory({ + api: techdocsApiRef, + deps: { + configApi: configApiRef, + discoveryApi: discoveryApiRef, + fetchApi: fetchApiRef, + }, + factory: ({ configApi, discoveryApi, fetchApi }) => + new TechDocsClient({ + configApi, + discoveryApi, + fetchApi, + }), + }), }); /** @alpha */ export const TechDocsSearchResultListItemExtension = createSearchResultListItemExtension({ - id: 'techdocs', configSchema: createSchemaFromZod(z => z.object({ // TODO: Define how the icon can be configurable @@ -108,7 +103,8 @@ export const TechDocsSearchResultListItemExtension = const { TechDocsSearchResultListItem } = await import( './search/components/TechDocsSearchResultListItem' ); - return props => ; + return props => + compatWrapper(); }, }); @@ -118,13 +114,12 @@ export const TechDocsSearchResultListItemExtension = * @alpha */ const TechDocsIndexPage = createPageExtension({ - id: 'plugin.techdocs.indexPage', defaultPath: '/docs', routeRef: convertLegacyRouteRef(rootRouteRef), loader: () => - import('./home/components/TechDocsIndexPage').then(m => ( - - )), + import('./home/components/TechDocsIndexPage').then(m => + compatWrapper(), + ), }); /** @@ -133,13 +128,13 @@ const TechDocsIndexPage = createPageExtension({ * @alpha */ const TechDocsReaderPage = createPageExtension({ - id: 'plugin.techdocs.readerPage', + name: 'reader', defaultPath: '/docs/:namespace/:kind/:name', routeRef: convertLegacyRouteRef(rootDocsRouteRef), loader: () => - import('./reader/components/TechDocsReaderPage').then(m => ( - - )), + import('./reader/components/TechDocsReaderPage').then(m => + compatWrapper(), + ), }); /** @@ -148,15 +143,14 @@ const TechDocsReaderPage = createPageExtension({ * @alpha */ const TechDocsEntityContent = createEntityContentExtension({ - id: 'techdocs', defaultPath: 'docs', defaultTitle: 'TechDocs', - loader: () => import('./Router').then(m => ), + loader: () => + import('./Router').then(m => compatWrapper()), }); /** @alpha */ const TechDocsNavItem = createNavItemExtension({ - id: 'plugin.techdocs.nav.index', icon: LibraryBooks, title: 'Docs', routeRef: convertLegacyRouteRef(rootRouteRef), diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx index 29e6945fa7..3d12718986 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/dom.tsx @@ -18,7 +18,6 @@ import { useCallback, useEffect, useState } from 'react'; import { useTheme, useMediaQuery } from '@material-ui/core'; -import { BackstageTheme } from '@backstage/theme'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { useAnalytics, useApi } from '@backstage/core-plugin-api'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; @@ -58,7 +57,7 @@ export const useTechDocsReaderDom = ( entityRef: CompoundEntityRef, ): Element | null => { const navigate = useNavigateUrl(); - const theme = useTheme(); + const theme = useTheme(); const isMobileMedia = useMediaQuery(MOBILE_MEDIA_QUERY); const sanitizerTransformer = useSanitizerTransformer(); const stylesTransformer = useStylesTransformer(); diff --git a/plugins/techdocs/src/reader/transformers/styles/rules/types.ts b/plugins/techdocs/src/reader/transformers/styles/rules/types.ts index 6419ef8e39..defdc4ad90 100644 --- a/plugins/techdocs/src/reader/transformers/styles/rules/types.ts +++ b/plugins/techdocs/src/reader/transformers/styles/rules/types.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { BackstageTheme } from '@backstage/theme'; +import { Theme } from '@material-ui/core'; /** * A Backstage sidebar object that contains properties such as its pin state. @@ -31,7 +31,7 @@ export type RuleOptions = { /** * A Backstage theme object that contains the application's design tokens. */ - theme: BackstageTheme; + theme: Theme; /** * A Backstage sidebar, see {@link BackstageSidebar} for more details. */ diff --git a/plugins/techdocs/src/reader/transformers/styles/transformer.ts b/plugins/techdocs/src/reader/transformers/styles/transformer.ts index 04a6d476af..dee77fb1ed 100644 --- a/plugins/techdocs/src/reader/transformers/styles/transformer.ts +++ b/plugins/techdocs/src/reader/transformers/styles/transformer.ts @@ -15,12 +15,8 @@ */ import { useCallback, useMemo } from 'react'; - import { useTheme } from '@material-ui/core'; - import { useSidebarPinState } from '@backstage/core-components'; -import { BackstageTheme } from '@backstage/theme'; - import { Transformer } from '../transformer'; import { rules } from './rules'; @@ -35,7 +31,7 @@ const useSidebar = () => useSidebarPinState(); */ const useRuleStyles = () => { const sidebar = useSidebar(); - const theme = useTheme(); + const theme = useTheme(); return useMemo(() => { const options = { theme, sidebar }; diff --git a/plugins/todo-backend/CHANGELOG.md b/plugins/todo-backend/CHANGELOG.md index 8e9b55ea8c..7ec5dfae85 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,50 @@ # @backstage/plugin-todo-backend +## 0.3.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.6.0-next.2 + - @backstage/backend-common@0.20.0-next.2 + - @backstage/catalog-client@1.5.0-next.1 + - @backstage/backend-openapi-utils@0.1.1-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/integration@1.8.0-next.1 + +## 0.3.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.5.0-next.0 + - @backstage/integration@1.8.0-next.1 + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-openapi-utils@0.1.1-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-catalog-node@1.5.1-next.1 + +## 0.3.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-openapi-utils@0.1.1-next.0 + - @backstage/integration@1.8.0-next.0 + - @backstage/plugin-catalog-node@1.5.1-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-client@1.4.6 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + ## 0.3.5 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index 3f50f67aa1..bc69fbb57e 100644 --- a/plugins/todo-backend/package.json +++ b/plugins/todo-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo-backend", "description": "A Backstage backend plugin that lets you browse TODO comments in your source code", - "version": "0.3.5", + "version": "0.3.6-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index dbe0bdc57b..2c19eb2e3e 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-todo +## 0.2.32-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.2.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.2.32-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.2.30 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index d8b36a8290..12deedde5b 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo", "description": "A Backstage plugin that lets you browse TODO comments in your source code", - "version": "0.2.30", + "version": "0.2.32-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/user-settings-backend/CHANGELOG.md b/plugins/user-settings-backend/CHANGELOG.md index 4650867420..3794e7e9fd 100644 --- a/plugins/user-settings-backend/CHANGELOG.md +++ b/plugins/user-settings-backend/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-user-settings-backend +## 0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/plugin-auth-node@0.4.2-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## 0.2.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-node@0.4.2-next.1 + +## 0.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/plugin-auth-node@0.4.2-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.2.6 ### Patch Changes diff --git a/plugins/user-settings-backend/alpha-api-report.md b/plugins/user-settings-backend/api-report-alpha.md similarity index 100% rename from plugins/user-settings-backend/alpha-api-report.md rename to plugins/user-settings-backend/api-report-alpha.md diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index 051c118a5e..c683f0ff2e 100644 --- a/plugins/user-settings-backend/package.json +++ b/plugins/user-settings-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings-backend", "description": "The Backstage backend plugin to manage user settings", - "version": "0.2.6", + "version": "0.2.7-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index ac60e8e4e4..899cf92da7 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,62 @@ # @backstage/plugin-user-settings +## 0.7.14-next.3 + +### Patch Changes + +- a1227cc: Wrap `/alpha` export extension elements in backwards compatibility wrapper. +- 8f5d6c1: Updates to the `/alpha` exports to match the extension input wrapping change. +- 36c94b8: Refactor of the alpha exports due to API change in how extension IDs are constructed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.2 + - @backstage/theme@0.5.0-next.1 + - @backstage/core-compat-api@0.1.0-next.2 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## 0.7.14-next.2 + +### Patch Changes + +- fb8f3bdbc2: Updated alpha translation message keys to use nested format and camel case. +- Updated dependencies + - @backstage/frontend-plugin-api@0.4.0-next.1 + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/core-app-api@1.11.2-next.1 + - @backstage/core-compat-api@0.0.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + - @backstage/types@1.1.1 + +## 0.7.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.0.1-next.0 + +## 0.7.14-next.0 + +### Patch Changes + +- 03d0b6dcdc: The `convertLegacyRouteRef` utility used by the alpha exports is now imported from `@backstage/core-compat-api`. +- Updated dependencies + - @backstage/core-compat-api@0.0.2-next.0 + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/frontend-plugin-api@0.3.1-next.0 + - @backstage/core-app-api@1.11.2-next.0 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + ## 0.7.12 ### Patch Changes diff --git a/plugins/user-settings/alpha-api-report.md b/plugins/user-settings/api-report-alpha.md similarity index 54% rename from plugins/user-settings/alpha-api-report.md rename to plugins/user-settings/api-report-alpha.md index f375eadbee..adb609a2cb 100644 --- a/plugins/user-settings/alpha-api-report.md +++ b/plugins/user-settings/api-report-alpha.md @@ -20,16 +20,16 @@ export default _default; export const userSettingsTranslationRef: TranslationRef< 'user-settings', { - readonly language: 'Language'; - readonly change_the_language: 'Change the language'; - readonly theme: 'Theme'; - readonly theme_light: 'Light'; - readonly theme_dark: 'Dark'; - readonly theme_auto: 'Auto'; - readonly change_the_theme_mode: 'Change the theme mode'; - readonly select_theme: 'Select {{theme}}'; - readonly select_theme_auto: 'Select Auto Theme'; - readonly select_lng: 'Select language {{language}}'; + readonly 'languageToggle.select': 'Select language {{language}}'; + readonly 'languageToggle.title': 'Language'; + readonly 'languageToggle.description': 'Change the language'; + readonly 'themeToggle.select': 'Select theme {{theme}}'; + readonly 'themeToggle.title': 'Theme'; + readonly 'themeToggle.description': 'Change the theme mode'; + readonly 'themeToggle.names.auto': 'Auto'; + readonly 'themeToggle.names.dark': 'Dark'; + readonly 'themeToggle.names.light': 'Light'; + readonly 'themeToggle.selectAuto': 'Select Auto Theme'; } >; diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 4edb08dc4a..ba26c62098 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings", "description": "A Backstage plugin that provides a settings page", - "version": "0.7.12", + "version": "0.7.14-next.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/user-settings/src/alpha.tsx b/plugins/user-settings/src/alpha.tsx index 419ee2808d..9ee2e4a7c5 100644 --- a/plugins/user-settings/src/alpha.tsx +++ b/plugins/user-settings/src/alpha.tsx @@ -19,7 +19,10 @@ import { createPageExtension, createPlugin, } from '@backstage/frontend-plugin-api'; -import { convertLegacyRouteRef } from '@backstage/core-compat-api'; +import { + convertLegacyRouteRef, + compatWrapper, +} from '@backstage/core-compat-api'; import { settingsRouteRef } from './plugin'; import React from 'react'; @@ -27,7 +30,6 @@ import React from 'react'; export * from './translation'; const UserSettingsPage = createPageExtension({ - id: 'plugin.user-settings.page', defaultPath: '/settings', routeRef: convertLegacyRouteRef(settingsRouteRef), inputs: { @@ -39,9 +41,13 @@ const UserSettingsPage = createPageExtension({ ), }, loader: ({ inputs }) => - import('./components/SettingsPage').then(m => ( - - )), + import('./components/SettingsPage').then(m => + compatWrapper( + , + ), + ), }); /** diff --git a/plugins/user-settings/src/components/AuthProviders/ProviderSettingsAvatar.tsx b/plugins/user-settings/src/components/AuthProviders/ProviderSettingsAvatar.tsx index e92b0efe15..07e9b4aa55 100644 --- a/plugins/user-settings/src/components/AuthProviders/ProviderSettingsAvatar.tsx +++ b/plugins/user-settings/src/components/AuthProviders/ProviderSettingsAvatar.tsx @@ -15,11 +15,10 @@ */ import React from 'react'; -import { BackstageTheme } from '@backstage/theme'; -import { makeStyles, Avatar } from '@material-ui/core'; +import { makeStyles, Avatar, Theme } from '@material-ui/core'; import { sidebarConfig } from '@backstage/core-components'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ avatar: { width: ({ size }) => size, height: ({ size }) => size, diff --git a/plugins/user-settings/src/components/General/UserSettingsLanguageToggle.tsx b/plugins/user-settings/src/components/General/UserSettingsLanguageToggle.tsx index 56756b2248..67519d24ae 100644 --- a/plugins/user-settings/src/components/General/UserSettingsLanguageToggle.tsx +++ b/plugins/user-settings/src/components/General/UserSettingsLanguageToggle.tsx @@ -118,8 +118,8 @@ export const UserSettingsLanguageToggle = () => { > { return ( <>{language} diff --git a/plugins/user-settings/src/components/General/UserSettingsSignInAvatar.tsx b/plugins/user-settings/src/components/General/UserSettingsSignInAvatar.tsx index af1d2969e6..85c616ec72 100644 --- a/plugins/user-settings/src/components/General/UserSettingsSignInAvatar.tsx +++ b/plugins/user-settings/src/components/General/UserSettingsSignInAvatar.tsx @@ -15,12 +15,11 @@ */ import React from 'react'; -import { BackstageTheme } from '@backstage/theme'; -import { makeStyles, Avatar } from '@material-ui/core'; +import { makeStyles, Avatar, Theme } from '@material-ui/core'; import { useUserProfile } from '../useUserProfileInfo'; import { sidebarConfig } from '@backstage/core-components'; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ avatar: { width: ({ size }) => size, height: ({ size }) => size, diff --git a/plugins/user-settings/src/components/General/UserSettingsThemeToggle.tsx b/plugins/user-settings/src/components/General/UserSettingsThemeToggle.tsx index ca57de3a78..37d91ecae0 100644 --- a/plugins/user-settings/src/components/General/UserSettingsThemeToggle.tsx +++ b/plugins/user-settings/src/components/General/UserSettingsThemeToggle.tsx @@ -130,8 +130,8 @@ export const UserSettingsThemeToggle = () => { > { const themeTitle = theme.title || (themeId === 'light' || themeId === 'dark' - ? t(`theme_${themeId}`) + ? t(`themeToggle.names.${themeId}`) : themeId); return ( <> @@ -165,9 +165,9 @@ export const UserSettingsThemeToggle = () => { ); })} - + - {t('theme_auto')}  + {t('themeToggle.names.auto')}  diff --git a/plugins/user-settings/src/translation.ts b/plugins/user-settings/src/translation.ts index 42fd8311e2..411ca1af51 100644 --- a/plugins/user-settings/src/translation.ts +++ b/plugins/user-settings/src/translation.ts @@ -20,15 +20,21 @@ import { createTranslationRef } from '@backstage/core-plugin-api/alpha'; export const userSettingsTranslationRef = createTranslationRef({ id: 'user-settings', messages: { - language: 'Language', - change_the_language: 'Change the language', - theme: 'Theme', - theme_light: 'Light', - theme_dark: 'Dark', - theme_auto: 'Auto', - change_the_theme_mode: 'Change the theme mode', - select_theme: 'Select {{theme}}', - select_theme_auto: 'Select Auto Theme', - select_lng: 'Select language {{language}}', + languageToggle: { + title: 'Language', + description: 'Change the language', + select: 'Select language {{language}}', + }, + themeToggle: { + title: 'Theme', + description: 'Change the theme mode', + select: 'Select theme {{theme}}', + selectAuto: 'Select Auto Theme', + names: { + light: 'Light', + dark: 'Dark', + auto: 'Auto', + }, + }, }, }); diff --git a/plugins/vault-backend/CHANGELOG.md b/plugins/vault-backend/CHANGELOG.md index e124a89344..3eddc7b59a 100644 --- a/plugins/vault-backend/CHANGELOG.md +++ b/plugins/vault-backend/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-vault-backend +## 0.4.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.2 + - @backstage/backend-plugin-api@0.6.8-next.2 + - @backstage/backend-tasks@0.5.13-next.2 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-vault-node@0.1.1-next.2 + +## 0.4.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.1 + - @backstage/backend-plugin-api@0.6.8-next.1 + - @backstage/backend-tasks@0.5.13-next.1 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-vault-node@0.1.1-next.1 + +## 0.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.20.0-next.0 + - @backstage/backend-tasks@0.5.13-next.0 + - @backstage/backend-plugin-api@0.6.8-next.0 + - @backstage/config@1.1.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-vault-node@0.1.1-next.0 + ## 0.4.0 ### Minor Changes diff --git a/plugins/vault-backend/package.json b/plugins/vault-backend/package.json index a5fdf10a72..1cf88d376d 100644 --- a/plugins/vault-backend/package.json +++ b/plugins/vault-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault-backend", "description": "A Backstage backend plugin that integrates towards Vault", - "version": "0.4.0", + "version": "0.4.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/vault-node/CHANGELOG.md b/plugins/vault-node/CHANGELOG.md index bea999183c..a611bd6a83 100644 --- a/plugins/vault-node/CHANGELOG.md +++ b/plugins/vault-node/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-vault-node +## 0.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.2 + +## 0.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.1 + +## 0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.8-next.0 + ## 0.1.0 ### Minor Changes diff --git a/plugins/vault-node/package.json b/plugins/vault-node/package.json index ecf96529a6..da57ba0345 100644 --- a/plugins/vault-node/package.json +++ b/plugins/vault-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault-node", "description": "Node.js library for the vault plugin", - "version": "0.1.0", + "version": "0.1.1-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/vault/CHANGELOG.md b/plugins/vault/CHANGELOG.md index e4292aa633..8200b7cf47 100644 --- a/plugins/vault/CHANGELOG.md +++ b/plugins/vault/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-vault +## 0.1.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.2 + - @backstage/catalog-model@1.4.3 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.1.23-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/plugin-catalog-react@1.9.2-next.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.1.23-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/plugin-catalog-react@1.9.2-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + ## 0.1.21 ### Patch Changes diff --git a/plugins/vault/package.json b/plugins/vault/package.json index b36ad6d3fc..9bf7f2ed4a 100644 --- a/plugins/vault/package.json +++ b/plugins/vault/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-vault", "description": "A Backstage plugin that integrates towards Vault", - "version": "0.1.21", + "version": "0.1.23-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index c2a0dda6c2..67c05b52af 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-xcmetrics +## 0.2.46-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.5.0-next.1 + - @backstage/core-components@0.13.9-next.2 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + +## 0.2.46-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.9-next.1 + - @backstage/core-plugin-api@1.8.1-next.1 + - @backstage/errors@1.2.3 + - @backstage/theme@0.5.0-next.0 + +## 0.2.46-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.8.1-next.0 + - @backstage/core-components@0.13.9-next.0 + - @backstage/theme@0.5.0-next.0 + - @backstage/errors@1.2.3 + ## 0.2.45 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index 89667f0e31..9a17200571 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-xcmetrics", "description": "A Backstage plugin that shows XCode build metrics for your components", - "version": "0.2.45", + "version": "0.2.46-next.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/xcmetrics/src/components/BuildListFilter/BuildListFilter.tsx b/plugins/xcmetrics/src/components/BuildListFilter/BuildListFilter.tsx index 9a2b759235..ce2a2f4c05 100644 --- a/plugins/xcmetrics/src/components/BuildListFilter/BuildListFilter.tsx +++ b/plugins/xcmetrics/src/components/BuildListFilter/BuildListFilter.tsx @@ -18,7 +18,6 @@ import React, { useEffect, useState } from 'react'; import { makeStyles, IconButton, Grid, Button } from '@material-ui/core'; import FilterList from '@material-ui/icons/FilterList'; import { InfoCard, Select } from '@backstage/core-components'; -import { BackstageTheme } from '@backstage/theme'; import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; import { BuildFilters, BuildStatus, xcmetricsApiRef } from '../../api'; @@ -28,7 +27,7 @@ const toSelectItems = (strings: string[]) => { return strings.map(str => ({ label: str, value: str })); }; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ filtersContent: { padding: theme.spacing(2, 2, 2, 2.5), }, diff --git a/plugins/xcmetrics/src/components/OverviewTrends/OverviewTrends.tsx b/plugins/xcmetrics/src/components/OverviewTrends/OverviewTrends.tsx index 4c791688be..e6a1601e37 100644 --- a/plugins/xcmetrics/src/components/OverviewTrends/OverviewTrends.tsx +++ b/plugins/xcmetrics/src/components/OverviewTrends/OverviewTrends.tsx @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { Grid, makeStyles, useTheme } from '@material-ui/core'; import React, { useState } from 'react'; import { Progress, Select } from '@backstage/core-components'; @@ -30,7 +31,6 @@ import { getValues, sumField, } from '../../utils'; -import { BackstageTheme } from '@backstage/theme'; const useStyles = makeStyles({ spacingTop: { @@ -51,7 +51,7 @@ const DAYS_SELECT_ITEMS = [ export const OverviewTrends = () => { const [days, setDays] = useState(14); - const theme = useTheme(); + const theme = useTheme(); const classes = useStyles(); const client = useApi(xcmetricsApiRef); const buildCountsResult = useAsync( diff --git a/plugins/xcmetrics/src/components/StatusCell/StatusCell.tsx b/plugins/xcmetrics/src/components/StatusCell/StatusCell.tsx index 387879b3a0..98ddadc1ff 100644 --- a/plugins/xcmetrics/src/components/StatusCell/StatusCell.tsx +++ b/plugins/xcmetrics/src/components/StatusCell/StatusCell.tsx @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { makeStyles, Tooltip } from '@material-ui/core'; + +import { makeStyles, Theme, Tooltip } from '@material-ui/core'; import React from 'react'; -import { BackstageTheme } from '@backstage/theme'; import { BuildStatus, BuildStatusResult, xcmetricsApiRef } from '../../api'; import { cn, formatDuration, formatStatus } from '../../utils'; import useAsync from 'react-use/lib/useAsync'; @@ -71,7 +71,7 @@ type StatusStyle = { [key in BuildStatus]: any; }; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ root: { width: ({ size }) => size, height: ({ size }) => size, diff --git a/plugins/xcmetrics/src/components/StatusMatrix/StatusMatrix.tsx b/plugins/xcmetrics/src/components/StatusMatrix/StatusMatrix.tsx index 6e78c822ad..4c5af54017 100644 --- a/plugins/xcmetrics/src/components/StatusMatrix/StatusMatrix.tsx +++ b/plugins/xcmetrics/src/components/StatusMatrix/StatusMatrix.tsx @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import React from 'react'; import { makeStyles } from '@material-ui/core'; -import { BackstageTheme } from '@backstage/theme'; import { xcmetricsApiRef } from '../../api'; import useAsync from 'react-use/lib/useAsync'; import useMeasure from 'react-use/lib/useMeasure'; @@ -28,7 +28,7 @@ const CELL_SIZE = 12; const CELL_MARGIN = 4; const MAX_ROWS = 4; -const useStyles = makeStyles(theme => ({ +const useStyles = makeStyles(theme => ({ root: { marginTop: 8, display: 'flex', diff --git a/scripts/verify-local-dependencies.js b/scripts/verify-local-dependencies.js index b44e0836f4..5d75348681 100755 --- a/scripts/verify-local-dependencies.js +++ b/scripts/verify-local-dependencies.js @@ -33,18 +33,84 @@ const depTypes = [ 'optionalDependencies', ]; +const roleRules = [ + { + sourceRole: ['frontend-plugin', 'web-library'], + targetRole: ['backend-plugin', 'node-library'], + message: `Package SOURCE_NAME with frontend role SOURCE_ROLE has a dependency on package TARGET_NAME with backend role TARGET_ROLE, which is not permitted`, + }, + { + sourceRole: ['backend-plugin', 'node-library'], + targetRole: ['frontend-plugin', 'web-library'], + message: `Package SOURCE_NAME with backend role SOURCE_ROLE has a dependency on package TARGET_NAME with frontend role TARGET_ROLE, which is not permitted`, + }, + { + sourceRole: ['common-library'], + targetRole: [ + 'frontend-plugin', + 'web-library', + 'backend-plugin', + 'node-library', + ], + message: `Polymorphic package SOURCE_NAME has a dependency on package TARGET_NAME with role TARGET_ROLE, which is not permitted since it's not also polymorphic`, + }, + { + sourceRole: ['frontend-plugin', 'web-library'], + targetRole: 'frontend-plugin', + except: [ + // TODO(freben): Address these + '@backstage/plugin-api-docs', + '@backstage/plugin-techdocs-addons-test-utils', + ], + message: `Package SOURCE_NAME with role SOURCE_ROLE has a dependency on another plugin package TARGET_NAME, which is not permitted`, + }, + { + sourceRole: ['frontend-plugin', 'web-library'], + targetName: ['@backstage/core-app-api', '@backstage/frontend-app-api'], + except: [ + // These are legitimate + '@backstage/app-defaults', + '@backstage/core-compat-api', + '@backstage/dev-utils', + '@backstage/frontend-app-api', + '@backstage/frontend-test-utils', + '@backstage/test-utils', + // TODO(freben): Address these + '@backstage/plugin-home', + '@backstage/plugin-techdocs-addons-test-utils', + '@backstage/plugin-user-settings', + ], + message: `Plugin package SOURCE_NAME with role SOURCE_ROLE has a runtime dependency on package TARGET_NAME, which is not permitted. If you are using this dependency for dev server purposes, you can move it to devDependencies instead.`, + }, + { + sourceRole: ['backend-plugin', 'node-library'], + targetName: ['@backstage/backend-app-api'], + except: [ + // These are legitimate + '@backstage/backend-common', + '@backstage/backend-defaults', + '@backstage/backend-test-utils', + ], + message: `Plugin package SOURCE_NAME with role SOURCE_ROLE has a runtime dependency on package TARGET_NAME, which is not permitted. If you are using this dependency for dev server purposes, you can move it to devDependencies instead.`, + }, +]; + async function main(args) { const shouldFix = args.includes('--fix'); const rootPath = resolvePath(__dirname, '..'); const { packages } = await getPackages(rootPath); - let hadErrors = false; + let hadVersionRangeErrors = false; + let hadRoleErrors = false; const pkgMap = new Map(packages.map(pkg => [pkg.packageJson.name, pkg])); for (const pkg of packages) { - let fixed = false; + let versionRangeErrorsFixed = false; + /* + * Ensure that all internal deps have "workspace:^" version ranges + */ for (const depType of depTypes) { const deps = pkg.packageJson[depType]; @@ -54,33 +120,94 @@ async function main(args) { } const localPackage = pkgMap.get(dep); if (localPackage && range !== 'workspace:^') { - hadErrors = true; + hadVersionRangeErrors = true; console.log( `Local dependency from ${pkg.packageJson.name} to ${dep} should have a workspace range`, ); - fixed = true; + versionRangeErrorsFixed = true; pkg.packageJson[depType][dep] = 'workspace:^'; } } } - if (shouldFix && fixed) { + /* + * Ensure that there are no forbidden runtime dependency role combinations + */ + const sourceRole = pkg.packageJson.backstage?.role; + if (typeof sourceRole === 'string') { + for (const [targetName] of Object.entries( + pkg.packageJson.dependencies ?? {}, + )) { + let targetPackageJson; + try { + const packageJsonPath = require.resolve( + `${targetName}/package.json`, + { + paths: [pkg.dir], + }, + ); + targetPackageJson = JSON.parse(await fs.readFile(packageJsonPath)); + } catch { + // ignore + continue; + } + + const sourceName = pkg.packageJson.name; + const targetRole = targetPackageJson.backstage?.role; + if (typeof targetRole === 'string') { + for (const rule of roleRules) { + const matchesSourceRole = [rule.sourceRole ?? []] + .flat() + .includes(sourceRole); + const matchesTargetRole = [rule.targetRole ?? []] + .flat() + .includes(targetRole); + const matchesTargetName = [rule.targetName ?? []] + .flat() + .includes(targetName); + const isExempt = [rule.except ?? []].flat().includes(sourceName); + if ( + matchesSourceRole && + (matchesTargetName || matchesTargetRole) && + !isExempt + ) { + hadRoleErrors = true; + console.error( + rule.message + .replace('SOURCE_NAME', `'${sourceName}'`) + .replace('SOURCE_ROLE', `'${sourceRole}'`) + .replace('TARGET_NAME', `'${targetName}'`) + .replace('TARGET_ROLE', `'${targetRole}'`), + ); + } + } + } + } + } + + /* + * Fixup + */ + if (shouldFix && versionRangeErrorsFixed) { await fs.writeJson(joinPath(pkg.dir, 'package.json'), pkg.packageJson, { spaces: 2, }); } } - if (!shouldFix && hadErrors) { + if (!shouldFix && hadVersionRangeErrors) { console.error(); console.error('At least one package has an invalid local dependency'); console.error( 'Run `node scripts/verify-local-dependencies.js --fix` to fix', ); - process.exit(2); } + + if (hadRoleErrors) { + process.exit(3); + } } main(process.argv.slice(2)).catch(error => { diff --git a/storybook/yarn.lock b/storybook/yarn.lock index e16eb422f2..30139baa13 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -2842,90 +2842,82 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-darwin-arm64@npm:1.3.96" +"@swc/core-darwin-arm64@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-darwin-arm64@npm:1.3.100" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-darwin-x64@npm:1.3.96" +"@swc/core-darwin-x64@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-darwin-x64@npm:1.3.100" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.96" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@swc/core-linux-arm64-gnu@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.96" +"@swc/core-linux-arm64-gnu@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.100" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.96" +"@swc/core-linux-arm64-musl@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.100" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.96" +"@swc/core-linux-x64-gnu@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.100" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-x64-musl@npm:1.3.96" +"@swc/core-linux-x64-musl@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-linux-x64-musl@npm:1.3.100" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.96" +"@swc/core-win32-arm64-msvc@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.100" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.96" +"@swc/core-win32-ia32-msvc@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.100" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.96" +"@swc/core-win32-x64-msvc@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.100" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.46": - version: 1.3.96 - resolution: "@swc/core@npm:1.3.96" + version: 1.3.100 + resolution: "@swc/core@npm:1.3.100" dependencies: - "@swc/core-darwin-arm64": 1.3.96 - "@swc/core-darwin-x64": 1.3.96 - "@swc/core-linux-arm-gnueabihf": 1.3.96 - "@swc/core-linux-arm64-gnu": 1.3.96 - "@swc/core-linux-arm64-musl": 1.3.96 - "@swc/core-linux-x64-gnu": 1.3.96 - "@swc/core-linux-x64-musl": 1.3.96 - "@swc/core-win32-arm64-msvc": 1.3.96 - "@swc/core-win32-ia32-msvc": 1.3.96 - "@swc/core-win32-x64-msvc": 1.3.96 + "@swc/core-darwin-arm64": 1.3.100 + "@swc/core-darwin-x64": 1.3.100 + "@swc/core-linux-arm64-gnu": 1.3.100 + "@swc/core-linux-arm64-musl": 1.3.100 + "@swc/core-linux-x64-gnu": 1.3.100 + "@swc/core-linux-x64-musl": 1.3.100 + "@swc/core-win32-arm64-msvc": 1.3.100 + "@swc/core-win32-ia32-msvc": 1.3.100 + "@swc/core-win32-x64-msvc": 1.3.100 "@swc/counter": ^0.1.1 "@swc/types": ^0.1.5 peerDependencies: @@ -2935,8 +2927,6 @@ __metadata: optional: true "@swc/core-darwin-x64": optional: true - "@swc/core-linux-arm-gnueabihf": - optional: true "@swc/core-linux-arm64-gnu": optional: true "@swc/core-linux-arm64-musl": @@ -2954,7 +2944,7 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 41d4a4461b2952aaf8d3be945d373d0f3bd126115ee1aad0f76f2690e2b5635b6ec5bb54a7638deb9afedb1ad6f7d8453468a704e54e5fbb8234dd4a43b80205 + checksum: b68553db388c36b1859f0e8b5231a608277e17ae7fd7a928ea8b448432532176914f84675426d40aa9710617b2e7fb626aaa8358b6b2506b3c43f82db725c41e languageName: node linkType: hard diff --git a/yarn.lock b/yarn.lock index b69ee3fe5c..790655e858 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13,9 +13,9 @@ __metadata: linkType: hard "@adobe/css-tools@npm:^4.3.1": - version: 4.3.1 - resolution: "@adobe/css-tools@npm:4.3.1" - checksum: ad43456379ff391132aff687ece190cb23ea69395e23c9b96690eeabe2468da89a4aaf266e4f8b6eaab53db3d1064107ce0f63c3a974e864f4a04affc768da3f + version: 4.3.2 + resolution: "@adobe/css-tools@npm:4.3.2" + checksum: 9667d61d55dc3b0a315c530ae84e016ce5267c4dd8ac00abb40108dc98e07b98e3090ce8b87acd51a41a68d9e84dcccb08cdf21c902572a9cf9dcaf830da4ae3 languageName: node linkType: hard @@ -105,54 +105,9 @@ __metadata: languageName: node linkType: hard -"@apollo/cache-control-types@npm:^1.0.3": - version: 1.0.3 - resolution: "@apollo/cache-control-types@npm:1.0.3" - peerDependencies: - graphql: 14.x || 15.x || 16.x - checksum: 1c2791f3c7fa0fc609bd42cebcb6a0d1ccfcee9b22e54c4aa5af918944ae9dbdd45d7b84670afc6de34444e9226e9e82523bc3969805b506b86fd28dc9abc9fa - languageName: node - linkType: hard - -"@apollo/client@npm:^3.0.0": - version: 3.8.7 - resolution: "@apollo/client@npm:3.8.7" - dependencies: - "@graphql-typed-document-node/core": ^3.1.1 - "@wry/context": ^0.7.3 - "@wry/equality": ^0.5.6 - "@wry/trie": ^0.4.3 - graphql-tag: ^2.12.6 - hoist-non-react-statics: ^3.3.2 - optimism: ^0.17.5 - prop-types: ^15.7.2 - response-iterator: ^0.2.6 - symbol-observable: ^4.0.0 - ts-invariant: ^0.10.3 - tslib: ^2.3.0 - zen-observable-ts: ^1.2.5 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 - graphql-ws: ^5.5.5 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - subscriptions-transport-ws: ^0.9.0 || ^0.11.0 - peerDependenciesMeta: - graphql-ws: - optional: true - react: - optional: true - react-dom: - optional: true - subscriptions-transport-ws: - optional: true - checksum: b4343d7f64481d6e4ee9f3ff461cfdab669728104b7540a4fff885232335fed55920e76de823ee4f2fa711aa72afbbf1cfe29601eacabb3577dc1f3ee82046d4 - languageName: node - linkType: hard - -"@apollo/explorer@npm:^2.0.0": - version: 2.0.2 - resolution: "@apollo/explorer@npm:2.0.2" +"@apollo/explorer@npm:^3.0.0": + version: 3.6.0 + resolution: "@apollo/explorer@npm:3.6.0" dependencies: "@types/whatwg-mimetype": ^3.0.0 graphql-ws: ^5.9.0 @@ -170,233 +125,11 @@ __metadata: optional: true use-deep-compare-effect: optional: true - checksum: 02ba8732b25ea568905f7c68bd68ae5f9f988743348e93b7ecba4a6882fc5cba3f4f1a426368d96b8aa795c5c9f32fab0fd2be35e4ad01d1cfefa495a22eb92b + checksum: 0617cd1995cb8a63e25ee93204e09f6210a9031ca7942a7c74b9ac74677072fd6242d1479110d9a756c013589626706766380788e9b07dc63a18b494f581406c languageName: node linkType: hard -"@apollo/protobufjs@npm:1.2.7": - version: 1.2.7 - resolution: "@apollo/protobufjs@npm:1.2.7" - dependencies: - "@protobufjs/aspromise": ^1.1.2 - "@protobufjs/base64": ^1.1.2 - "@protobufjs/codegen": ^2.0.4 - "@protobufjs/eventemitter": ^1.1.0 - "@protobufjs/fetch": ^1.1.0 - "@protobufjs/float": ^1.0.2 - "@protobufjs/inquire": ^1.1.0 - "@protobufjs/path": ^1.1.2 - "@protobufjs/pool": ^1.1.0 - "@protobufjs/utf8": ^1.1.0 - "@types/long": ^4.0.0 - long: ^4.0.0 - bin: - apollo-pbjs: bin/pbjs - apollo-pbts: bin/pbts - checksum: e01a33984ae06d6679f6796bb44e55260112ddd090ebc9f87d3f952c45153dd5df5c91ac4bf91ba60fb72ff8c1218059ce4bf8bb2eb08c5049c783de0098eec0 - languageName: node - linkType: hard - -"@apollo/server-gateway-interface@npm:^1.1.1": - version: 1.1.1 - resolution: "@apollo/server-gateway-interface@npm:1.1.1" - dependencies: - "@apollo/usage-reporting-protobuf": ^4.1.1 - "@apollo/utils.fetcher": ^2.0.0 - "@apollo/utils.keyvaluecache": ^2.1.0 - "@apollo/utils.logger": ^2.0.0 - peerDependencies: - graphql: 14.x || 15.x || 16.x - checksum: b85ca1682258f6d022b49acf4b6cb8147a4cc38fcc0e68fa3ca6a00843bee5b84f8317af26cbe3e6a41ede6990eb7eb733c50a123441a1efab56572b7d0fd6dc - languageName: node - linkType: hard - -"@apollo/server@npm:^4.0.0": - version: 4.9.5 - resolution: "@apollo/server@npm:4.9.5" - dependencies: - "@apollo/cache-control-types": ^1.0.3 - "@apollo/server-gateway-interface": ^1.1.1 - "@apollo/usage-reporting-protobuf": ^4.1.1 - "@apollo/utils.createhash": ^2.0.0 - "@apollo/utils.fetcher": ^2.0.0 - "@apollo/utils.isnodelike": ^2.0.0 - "@apollo/utils.keyvaluecache": ^2.1.0 - "@apollo/utils.logger": ^2.0.0 - "@apollo/utils.usagereporting": ^2.1.0 - "@apollo/utils.withrequired": ^2.0.0 - "@graphql-tools/schema": ^9.0.0 - "@josephg/resolvable": ^1.0.0 - "@types/express": ^4.17.13 - "@types/express-serve-static-core": ^4.17.30 - "@types/node-fetch": ^2.6.1 - async-retry: ^1.2.1 - body-parser: ^1.20.0 - cors: ^2.8.5 - express: ^4.17.1 - loglevel: ^1.6.8 - lru-cache: ^7.10.1 - negotiator: ^0.6.3 - node-abort-controller: ^3.1.1 - node-fetch: ^2.6.7 - uuid: ^9.0.0 - whatwg-mimetype: ^3.0.0 - peerDependencies: - graphql: ^16.6.0 - checksum: 52aac2ef0665a776b2da8930b2a6e31b652a9a3c5b2e48e56d323e40b618acae091c69dc04ebed5355a36e22b793ceb31baa04afe516205c67c2db87c0fb01a0 - languageName: node - linkType: hard - -"@apollo/usage-reporting-protobuf@npm:^4.1.0, @apollo/usage-reporting-protobuf@npm:^4.1.1": - version: 4.1.1 - resolution: "@apollo/usage-reporting-protobuf@npm:4.1.1" - dependencies: - "@apollo/protobufjs": 1.2.7 - checksum: 899f13cfb57cfe4320e50fff84254604c25538620aa5a56bad06fb4fc929a8842237b376a5ab6d82800d9aceacc8e79ccae01a1c11e85456d4a9ed50a6fe40ee - languageName: node - linkType: hard - -"@apollo/utils.createhash@npm:^2.0.0": - version: 2.0.0 - resolution: "@apollo/utils.createhash@npm:2.0.0" - dependencies: - "@apollo/utils.isnodelike": ^2.0.0 - sha.js: ^2.4.11 - checksum: 467558891f22b05293ca2d9c04fb4815d8b13e9e03cac6f6f5eb752d06f00eb46a3f237c93250d83d53753326c289899b177f3147cd368079b7e74098392b1b7 - languageName: node - linkType: hard - -"@apollo/utils.dropunuseddefinitions@npm:^2.0.1": - version: 2.0.1 - resolution: "@apollo/utils.dropunuseddefinitions@npm:2.0.1" - peerDependencies: - graphql: 14.x || 15.x || 16.x - checksum: c12166f2551fb44045a8210317b7776abc263136bd07bfe3c6eecdb050468590fc73e524efc437cad21cc4cfcd1efc3e110285025150c2073a4b303934898ac1 - languageName: node - linkType: hard - -"@apollo/utils.fetcher@npm:^2.0.0": - version: 2.0.0 - resolution: "@apollo/utils.fetcher@npm:2.0.0" - checksum: e9f4b696f496751d1b781836f394608115ae1fab673cb30ede223748d04eb983384b5c9e01f8350bb0530d841fd0ccb41be3a3a4bcae0a141b2478862add29cc - languageName: node - linkType: hard - -"@apollo/utils.isnodelike@npm:^2.0.0": - version: 2.0.0 - resolution: "@apollo/utils.isnodelike@npm:2.0.0" - checksum: 436853000037c955e7112d19b60ca82e6d453e7bc715f3360ab23384fe1153039b06f9329e85e1adb030a1b22f0b9e960b28a5ccd92f7c61a1af57e58401a1aa - languageName: node - linkType: hard - -"@apollo/utils.keyvaluecache@npm:^2.1.0": - version: 2.1.0 - resolution: "@apollo/utils.keyvaluecache@npm:2.1.0" - dependencies: - "@apollo/utils.logger": ^2.0.0 - lru-cache: ^7.14.1 - checksum: 1e1c9cdea98384c01864250bd8e39cffaa822adbd60f9387ecf5c6565f69c2fd23b3ebdc499990b39535d4df0e3991fe73ec2d59a2798631ede04d8834d8c384 - languageName: node - linkType: hard - -"@apollo/utils.logger@npm:^2.0.0": - version: 2.0.0 - resolution: "@apollo/utils.logger@npm:2.0.0" - checksum: bfe87036382adaf1b5f05acc8e926b6316a8b37dc0c0b20ae0c2010b61085d018620203eda9cb6884e650f3d971a4dfdbc30980deedba99d219ba2abd9bd8ffa - languageName: node - linkType: hard - -"@apollo/utils.printwithreducedwhitespace@npm:^2.0.1": - version: 2.0.1 - resolution: "@apollo/utils.printwithreducedwhitespace@npm:2.0.1" - peerDependencies: - graphql: 14.x || 15.x || 16.x - checksum: 16cd191e66f3801b15deb581426cd1f55066bb824c32d63fe9de9c255bea2e2b6ee1ffc88873607830d2df0f3b4d9a14c707b709f205062e21a502f08f40d513 - languageName: node - linkType: hard - -"@apollo/utils.removealiases@npm:2.0.1": - version: 2.0.1 - resolution: "@apollo/utils.removealiases@npm:2.0.1" - peerDependencies: - graphql: 14.x || 15.x || 16.x - checksum: 2f3f925b239bce49fe9d80bb9fbb551992c8d9180af160e780faf1c88971a30ef16b842e82e1f27a0e1f8c649af0a442ef95f6838d4cde6148939ec73d9464f6 - languageName: node - linkType: hard - -"@apollo/utils.sortast@npm:^2.0.1": - version: 2.0.1 - resolution: "@apollo/utils.sortast@npm:2.0.1" - dependencies: - lodash.sortby: ^4.7.0 - peerDependencies: - graphql: 14.x || 15.x || 16.x - checksum: b71245558ebd64bf93b98aec933d4b5f5758e0fecf7915728d94725ed4201fb2515e2af92fe01a595638147e5e0ef50a27ab5323d9b76eeb126769fb1e58f051 - languageName: node - linkType: hard - -"@apollo/utils.stripsensitiveliterals@npm:^2.0.1": - version: 2.0.1 - resolution: "@apollo/utils.stripsensitiveliterals@npm:2.0.1" - peerDependencies: - graphql: 14.x || 15.x || 16.x - checksum: a3f74af0626f89d61f7ed1d25194f6b77006a06653399eecaea0b246cf685a85465091f2dc70280b127871b5c1eda7ded799ce176271c2612946acdc9453d388 - languageName: node - linkType: hard - -"@apollo/utils.usagereporting@npm:^2.1.0": - version: 2.1.0 - resolution: "@apollo/utils.usagereporting@npm:2.1.0" - dependencies: - "@apollo/usage-reporting-protobuf": ^4.1.0 - "@apollo/utils.dropunuseddefinitions": ^2.0.1 - "@apollo/utils.printwithreducedwhitespace": ^2.0.1 - "@apollo/utils.removealiases": 2.0.1 - "@apollo/utils.sortast": ^2.0.1 - "@apollo/utils.stripsensitiveliterals": ^2.0.1 - peerDependencies: - graphql: 14.x || 15.x || 16.x - checksum: 7a676f9b519563955d105264a93668e3897108d937115063c4cd3df310f32be29b8d7bdfe12eeca8d5966558d8c7f07742bcfd9ebb844c48b6ad1acee620183f - languageName: node - linkType: hard - -"@apollo/utils.withrequired@npm:^2.0.0": - version: 2.0.0 - resolution: "@apollo/utils.withrequired@npm:2.0.0" - checksum: 144cef2859318879b3478693eb891c31afa75f30e807bdfbef98ec3aa93c74cb0a3f76d245dbdedd4954f52c1b9ec8bebbccc69eb5d8bb8109c88c4352225e24 - languageName: node - linkType: hard - -"@ardatan/relay-compiler@npm:12.0.0": - version: 12.0.0 - resolution: "@ardatan/relay-compiler@npm:12.0.0" - dependencies: - "@babel/core": ^7.14.0 - "@babel/generator": ^7.14.0 - "@babel/parser": ^7.14.0 - "@babel/runtime": ^7.0.0 - "@babel/traverse": ^7.14.0 - "@babel/types": ^7.0.0 - babel-preset-fbjs: ^3.4.0 - chalk: ^4.0.0 - fb-watchman: ^2.0.0 - fbjs: ^3.0.0 - glob: ^7.1.1 - immutable: ~3.7.6 - invariant: ^2.2.4 - nullthrows: ^1.1.1 - relay-runtime: 12.0.0 - signedsource: ^1.0.0 - yargs: ^15.3.1 - peerDependencies: - graphql: "*" - bin: - relay-compiler: bin/relay-compiler - checksum: f0cec120d02961ee8652e0dde72d9e425bc97cad5d0f767d8764cfd30952294eb2838432f33e4da8bb6999d0c13dcd1df128280666bfea373294d98aa8033ae7 - languageName: node - linkType: hard - -"@ardatan/sync-fetch@npm:0.0.1": +"@ardatan/sync-fetch@npm:^0.0.1": version: 0.0.1 resolution: "@ardatan/sync-fetch@npm:0.0.1" dependencies: @@ -405,59 +138,76 @@ __metadata: languageName: node linkType: hard -"@asyncapi/avro-schema-parser@npm:^1.1.0": - version: 1.1.0 - resolution: "@asyncapi/avro-schema-parser@npm:1.1.0" +"@asyncapi/avro-schema-parser@npm:^3.0.7": + version: 3.0.7 + resolution: "@asyncapi/avro-schema-parser@npm:3.0.7" dependencies: - avsc: ^5.7.3 - checksum: 31bb6285a49f255e809088164ac4638103b2ec3e761c9c85be116af8abd9fe429626ba79ba6b3899d3823a77216741d9d793841e600145f2956328f3ce45a0e0 + "@asyncapi/parser": ^3.0.1 + "@types/json-schema": ^7.0.11 + avsc: ^5.7.6 + checksum: c7755708161f41812ebee90c92fb721176230f0006ddd01683b72c7c1d484a6c5cbe7d7e59c54a5c7221f5f722388642ec26b19a67adc9d30059067cc4276d69 languageName: node linkType: hard -"@asyncapi/openapi-schema-parser@npm:^2.0.1": - version: 2.0.1 - resolution: "@asyncapi/openapi-schema-parser@npm:2.0.1" +"@asyncapi/openapi-schema-parser@npm:^3.0.8": + version: 3.0.8 + resolution: "@asyncapi/openapi-schema-parser@npm:3.0.8" dependencies: - "@openapi-contrib/openapi-schema-to-json-schema": ^3.0.0 - checksum: 703662e20f93baed7bfafa1a8fe909c6d8df6404fbd86cf86276c736bcb5e5a54dd5b8a6d979aa27d9502fad1ea11f0d89c3e6f7ca57b67579efa9f5b8ca1759 + "@asyncapi/parser": ^3.0.1 + "@openapi-contrib/openapi-schema-to-json-schema": ~3.2.0 + ajv: ^8.11.0 + ajv-errors: ^3.0.0 + ajv-formats: ^2.1.1 + checksum: 9c3f49d1a826818b864b2a0b16144d88eb2ecf7ca1d9c1e8554eac30d9875619638924892d093f0270b6b9a04efca1a8918dd5a7eb13fd88c14183d467af5ceb languageName: node linkType: hard -"@asyncapi/parser@npm:^1.18.0": - version: 1.18.0 - resolution: "@asyncapi/parser@npm:1.18.0" +"@asyncapi/parser@npm:^3.0.1": + version: 3.0.1 + resolution: "@asyncapi/parser@npm:3.0.1" dependencies: - "@apidevtools/json-schema-ref-parser": ^9.0.6 - "@asyncapi/specs": ^4.1.0 - "@fmvilas/pseudo-yaml-ast": ^0.3.1 - ajv: ^6.10.1 - js-yaml: ^3.13.1 - json-to-ast: ^2.1.0 - lodash.clonedeep: ^4.5.0 - node-fetch: ^2.6.0 - tiny-merge-patch: ^0.1.2 - checksum: 7e08cae52990ce97299170faf99aaf27a8e2e02e6b03df28518d256f5687f394c26fd0a4aba235514ed4e3c2fd081a79321a489c20987ed22122afdb0b9ea0dd + "@asyncapi/specs": ^6.1.0 + "@openapi-contrib/openapi-schema-to-json-schema": ~3.2.0 + "@stoplight/json": ^3.20.2 + "@stoplight/json-ref-readers": ^1.2.2 + "@stoplight/json-ref-resolver": ^3.1.5 + "@stoplight/spectral-core": ^1.16.1 + "@stoplight/spectral-functions": ^1.7.2 + "@stoplight/spectral-parsers": ^1.0.2 + "@stoplight/spectral-ref-resolver": ^1.0.3 + "@stoplight/types": ^13.12.0 + "@types/json-schema": ^7.0.11 + "@types/urijs": ^1.19.19 + ajv: ^8.11.0 + ajv-errors: ^3.0.0 + ajv-formats: ^2.1.1 + avsc: ^5.7.5 + js-yaml: ^4.1.0 + jsonpath-plus: ^7.2.0 + node-fetch: 2.6.7 + checksum: 6dce457e58dcf9dab8bfb945a7cb9507a2fb686c143d04b77f2f1fe1c1247f9fa76134c872203c3e10398005155f4b9bb4b5e43edfb956c1e9ae4d3d95b6ceb3 languageName: node linkType: hard -"@asyncapi/protobuf-schema-parser@npm:^1.0.0": - version: 1.0.0 - resolution: "@asyncapi/protobuf-schema-parser@npm:1.0.0" +"@asyncapi/protobuf-schema-parser@npm:^3.0.4": + version: 3.0.4 + resolution: "@asyncapi/protobuf-schema-parser@npm:3.0.4" dependencies: - conventional-changelog-conventionalcommits: ^5.0.0 + "@asyncapi/parser": ^3.0.1 + "@types/protocol-buffers-schema": ^3.4.1 protocol-buffers-schema: ^3.6.0 - checksum: 0d7dfdf79bb698618701f2ace8f369d3d3b38d26015b6b4a01cab47f9587f88dd9f5042d6f796fa59044b114d801075d47d7216f28bba3c96823364ab5790b7d + checksum: c176e6d86e53f342ac91067279fb6e1ac3ed9d7f36de197fc723a2ceaf2a2588267c445203d67edcb3cd75308c0c0d6ea401ad69508bfe378c9194420702d3db languageName: node linkType: hard -"@asyncapi/react-component@npm:1.0.0-next.48": - version: 1.0.0-next.48 - resolution: "@asyncapi/react-component@npm:1.0.0-next.48" +"@asyncapi/react-component@npm:1.2.6": + version: 1.2.6 + resolution: "@asyncapi/react-component@npm:1.2.6" dependencies: - "@asyncapi/avro-schema-parser": ^1.1.0 - "@asyncapi/openapi-schema-parser": ^2.0.1 - "@asyncapi/parser": ^1.18.0 - "@asyncapi/protobuf-schema-parser": ^1.0.0 + "@asyncapi/avro-schema-parser": ^3.0.7 + "@asyncapi/openapi-schema-parser": ^3.0.8 + "@asyncapi/parser": ^3.0.1 + "@asyncapi/protobuf-schema-parser": ^3.0.4 highlight.js: ^10.7.2 isomorphic-dompurify: ^0.13.0 marked: ^4.0.14 @@ -466,7 +216,7 @@ __metadata: peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: e01c5ca294d708e6557b3e3ccbc83e46a0cb1ca36cc022aec26ff8c7372756df390993ba21f993cdba3b4a95aea644005d9f3531cd5ce066e4376ebf624b21f2 + checksum: 4afb34562767771048d0848323adea8d498dc555cc529947d4a45f3ec8d7f172bb454814bcf9c4419e105a743736368b56b3ed54d09b60addc06a287ca0e82b9 languageName: node linkType: hard @@ -479,6 +229,15 @@ __metadata: languageName: node linkType: hard +"@asyncapi/specs@npm:^6.1.0": + version: 6.1.0 + resolution: "@asyncapi/specs@npm:6.1.0" + dependencies: + "@types/json-schema": ^7.0.11 + checksum: d4ad199ef58b8ef6be081e2e71fd172fdf6720479f3ae6f9b1e58037f833ca177c8af1dadeab4525c2c07e68ea0a4832e0d3dd67c3b033b988ca2435245f6aa6 + languageName: node + linkType: hard + "@aws-crypto/crc32@npm:3.0.0": version: 3.0.0 resolution: "@aws-crypto/crc32@npm:3.0.0" @@ -552,6 +311,17 @@ __metadata: languageName: node linkType: hard +"@aws-crypto/sha256-js@npm:^5.0.0": + version: 5.2.0 + resolution: "@aws-crypto/sha256-js@npm:5.2.0" + dependencies: + "@aws-crypto/util": ^5.2.0 + "@aws-sdk/types": ^3.222.0 + tslib: ^2.6.2 + checksum: 007fbe0436d714d0d0d282e2b61c90e45adcb9ad75eac9ac7ba03d32b56624afd09b2a9ceb4d659661cf17c51d74d1900ab6b00eacafc002da1101664955ca53 + languageName: node + linkType: hard + "@aws-crypto/supports-web-crypto@npm:^3.0.0": version: 3.0.0 resolution: "@aws-crypto/supports-web-crypto@npm:3.0.0" @@ -572,6 +342,17 @@ __metadata: languageName: node linkType: hard +"@aws-crypto/util@npm:^5.2.0": + version: 5.2.0 + resolution: "@aws-crypto/util@npm:5.2.0" + dependencies: + "@aws-sdk/types": ^3.222.0 + "@smithy/util-utf8": ^2.0.0 + tslib: ^2.6.2 + checksum: f0f81d9d2771c59946cfec48b86cb23d39f78a966c4a1f89d4753abdc3cb38de06f907d1e6450059b121d48ac65d612ab88bdb70014553a077fc3dabddfbf8d6 + languageName: node + linkType: hard + "@aws-sdk/abort-controller@npm:3.370.0, @aws-sdk/abort-controller@npm:^3.347.0": version: 3.370.0 resolution: "@aws-sdk/abort-controller@npm:3.370.0" @@ -582,25 +363,25 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/client-cognito-identity@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/client-cognito-identity@npm:3.451.0" +"@aws-sdk/client-cognito-identity@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/client-cognito-identity@npm:3.465.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.451.0 - "@aws-sdk/core": 3.451.0 - "@aws-sdk/credential-provider-node": 3.451.0 - "@aws-sdk/middleware-host-header": 3.451.0 - "@aws-sdk/middleware-logger": 3.451.0 - "@aws-sdk/middleware-recursion-detection": 3.451.0 - "@aws-sdk/middleware-signing": 3.451.0 - "@aws-sdk/middleware-user-agent": 3.451.0 - "@aws-sdk/region-config-resolver": 3.451.0 - "@aws-sdk/types": 3.451.0 - "@aws-sdk/util-endpoints": 3.451.0 - "@aws-sdk/util-user-agent-browser": 3.451.0 - "@aws-sdk/util-user-agent-node": 3.451.0 + "@aws-sdk/client-sts": 3.465.0 + "@aws-sdk/core": 3.465.0 + "@aws-sdk/credential-provider-node": 3.465.0 + "@aws-sdk/middleware-host-header": 3.465.0 + "@aws-sdk/middleware-logger": 3.465.0 + "@aws-sdk/middleware-recursion-detection": 3.465.0 + "@aws-sdk/middleware-signing": 3.465.0 + "@aws-sdk/middleware-user-agent": 3.465.0 + "@aws-sdk/region-config-resolver": 3.465.0 + "@aws-sdk/types": 3.465.0 + "@aws-sdk/util-endpoints": 3.465.0 + "@aws-sdk/util-user-agent-browser": 3.465.0 + "@aws-sdk/util-user-agent-node": 3.465.0 "@smithy/config-resolver": ^2.0.18 "@smithy/fetch-http-handler": ^2.2.6 "@smithy/hash-node": ^2.0.15 @@ -625,29 +406,29 @@ __metadata: "@smithy/util-retry": ^2.0.6 "@smithy/util-utf8": ^2.0.2 tslib: ^2.5.0 - checksum: 8f0cf73420d4e053076c08cbb9b83bf87a12b06ce7dd4e4d00d848a2e1d32ca2ba47563c30b67bce754130c746ea282b4c64548be4b771baaf718cac19cbaa27 + checksum: e02382ef3138cae6c0b7a23cce4df4105ac440e2644b59a4a151033128a8db7e6bdc4d8eab60e550f7e686bb5900d57c14deee2d889db3962a7bf76f17a2d665 languageName: node linkType: hard "@aws-sdk/client-eks@npm:^3.350.0": - version: 3.451.0 - resolution: "@aws-sdk/client-eks@npm:3.451.0" + version: 3.465.0 + resolution: "@aws-sdk/client-eks@npm:3.465.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.451.0 - "@aws-sdk/core": 3.451.0 - "@aws-sdk/credential-provider-node": 3.451.0 - "@aws-sdk/middleware-host-header": 3.451.0 - "@aws-sdk/middleware-logger": 3.451.0 - "@aws-sdk/middleware-recursion-detection": 3.451.0 - "@aws-sdk/middleware-signing": 3.451.0 - "@aws-sdk/middleware-user-agent": 3.451.0 - "@aws-sdk/region-config-resolver": 3.451.0 - "@aws-sdk/types": 3.451.0 - "@aws-sdk/util-endpoints": 3.451.0 - "@aws-sdk/util-user-agent-browser": 3.451.0 - "@aws-sdk/util-user-agent-node": 3.451.0 + "@aws-sdk/client-sts": 3.465.0 + "@aws-sdk/core": 3.465.0 + "@aws-sdk/credential-provider-node": 3.465.0 + "@aws-sdk/middleware-host-header": 3.465.0 + "@aws-sdk/middleware-logger": 3.465.0 + "@aws-sdk/middleware-recursion-detection": 3.465.0 + "@aws-sdk/middleware-signing": 3.465.0 + "@aws-sdk/middleware-user-agent": 3.465.0 + "@aws-sdk/region-config-resolver": 3.465.0 + "@aws-sdk/types": 3.465.0 + "@aws-sdk/util-endpoints": 3.465.0 + "@aws-sdk/util-user-agent-browser": 3.465.0 + "@aws-sdk/util-user-agent-node": 3.465.0 "@smithy/config-resolver": ^2.0.18 "@smithy/fetch-http-handler": ^2.2.6 "@smithy/hash-node": ^2.0.15 @@ -674,29 +455,29 @@ __metadata: "@smithy/util-waiter": ^2.0.13 tslib: ^2.5.0 uuid: ^8.3.2 - checksum: 836397db1c9b44bcab676a4ef2e219c11771a2d15aaea05e81b9cda6fd07e167e873bd56f23a641b1aeb45acc5c4e3e3f6fa5bb8b704dfa32151814b524ae824 + checksum: 9359da8f2c1e68de36b40ad6767d07442322db9c845f745f14213fa9672661b88aea7a61ab2bfad6f7fee7f3dde1efa0a55fe0b5577e998e2ae5e17495c9c8ff languageName: node linkType: hard "@aws-sdk/client-organizations@npm:^3.350.0": - version: 3.451.0 - resolution: "@aws-sdk/client-organizations@npm:3.451.0" + version: 3.465.0 + resolution: "@aws-sdk/client-organizations@npm:3.465.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.451.0 - "@aws-sdk/core": 3.451.0 - "@aws-sdk/credential-provider-node": 3.451.0 - "@aws-sdk/middleware-host-header": 3.451.0 - "@aws-sdk/middleware-logger": 3.451.0 - "@aws-sdk/middleware-recursion-detection": 3.451.0 - "@aws-sdk/middleware-signing": 3.451.0 - "@aws-sdk/middleware-user-agent": 3.451.0 - "@aws-sdk/region-config-resolver": 3.451.0 - "@aws-sdk/types": 3.451.0 - "@aws-sdk/util-endpoints": 3.451.0 - "@aws-sdk/util-user-agent-browser": 3.451.0 - "@aws-sdk/util-user-agent-node": 3.451.0 + "@aws-sdk/client-sts": 3.465.0 + "@aws-sdk/core": 3.465.0 + "@aws-sdk/credential-provider-node": 3.465.0 + "@aws-sdk/middleware-host-header": 3.465.0 + "@aws-sdk/middleware-logger": 3.465.0 + "@aws-sdk/middleware-recursion-detection": 3.465.0 + "@aws-sdk/middleware-signing": 3.465.0 + "@aws-sdk/middleware-user-agent": 3.465.0 + "@aws-sdk/region-config-resolver": 3.465.0 + "@aws-sdk/types": 3.465.0 + "@aws-sdk/util-endpoints": 3.465.0 + "@aws-sdk/util-user-agent-browser": 3.465.0 + "@aws-sdk/util-user-agent-node": 3.465.0 "@smithy/config-resolver": ^2.0.18 "@smithy/fetch-http-handler": ^2.2.6 "@smithy/hash-node": ^2.0.15 @@ -721,38 +502,38 @@ __metadata: "@smithy/util-retry": ^2.0.6 "@smithy/util-utf8": ^2.0.2 tslib: ^2.5.0 - checksum: 52a328844e08f45e96cfe39caa538477a992a55a90ce2fb67f5f093f7ff0c3a75ed404c10127884694b238bfdaf25f3eabeb7f80257ca01054c926297d102c2b + checksum: 556b8f7233c71a075504be48ec5dcf2597cc95c3247fba0c992de6ba91db994e8560f80d9a05022c3c9f9c4764fed361488c9c3c35dfe1d2c370eee3f5ae93d8 languageName: node linkType: hard "@aws-sdk/client-s3@npm:^3.350.0": - version: 3.451.0 - resolution: "@aws-sdk/client-s3@npm:3.451.0" + version: 3.465.0 + resolution: "@aws-sdk/client-s3@npm:3.465.0" dependencies: "@aws-crypto/sha1-browser": 3.0.0 "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.451.0 - "@aws-sdk/core": 3.451.0 - "@aws-sdk/credential-provider-node": 3.451.0 - "@aws-sdk/middleware-bucket-endpoint": 3.451.0 - "@aws-sdk/middleware-expect-continue": 3.451.0 - "@aws-sdk/middleware-flexible-checksums": 3.451.0 - "@aws-sdk/middleware-host-header": 3.451.0 - "@aws-sdk/middleware-location-constraint": 3.451.0 - "@aws-sdk/middleware-logger": 3.451.0 - "@aws-sdk/middleware-recursion-detection": 3.451.0 - "@aws-sdk/middleware-sdk-s3": 3.451.0 - "@aws-sdk/middleware-signing": 3.451.0 - "@aws-sdk/middleware-ssec": 3.451.0 - "@aws-sdk/middleware-user-agent": 3.451.0 - "@aws-sdk/region-config-resolver": 3.451.0 - "@aws-sdk/signature-v4-multi-region": 3.451.0 - "@aws-sdk/types": 3.451.0 - "@aws-sdk/util-endpoints": 3.451.0 - "@aws-sdk/util-user-agent-browser": 3.451.0 - "@aws-sdk/util-user-agent-node": 3.451.0 - "@aws-sdk/xml-builder": 3.310.0 + "@aws-sdk/client-sts": 3.465.0 + "@aws-sdk/core": 3.465.0 + "@aws-sdk/credential-provider-node": 3.465.0 + "@aws-sdk/middleware-bucket-endpoint": 3.465.0 + "@aws-sdk/middleware-expect-continue": 3.465.0 + "@aws-sdk/middleware-flexible-checksums": 3.465.0 + "@aws-sdk/middleware-host-header": 3.465.0 + "@aws-sdk/middleware-location-constraint": 3.465.0 + "@aws-sdk/middleware-logger": 3.465.0 + "@aws-sdk/middleware-recursion-detection": 3.465.0 + "@aws-sdk/middleware-sdk-s3": 3.465.0 + "@aws-sdk/middleware-signing": 3.465.0 + "@aws-sdk/middleware-ssec": 3.465.0 + "@aws-sdk/middleware-user-agent": 3.465.0 + "@aws-sdk/region-config-resolver": 3.465.0 + "@aws-sdk/signature-v4-multi-region": 3.465.0 + "@aws-sdk/types": 3.465.0 + "@aws-sdk/util-endpoints": 3.465.0 + "@aws-sdk/util-user-agent-browser": 3.465.0 + "@aws-sdk/util-user-agent-node": 3.465.0 + "@aws-sdk/xml-builder": 3.465.0 "@smithy/config-resolver": ^2.0.18 "@smithy/eventstream-serde-browser": ^2.0.13 "@smithy/eventstream-serde-config-resolver": ^2.0.13 @@ -786,30 +567,30 @@ __metadata: "@smithy/util-waiter": ^2.0.13 fast-xml-parser: 4.2.5 tslib: ^2.5.0 - checksum: 0604486c6ebdd2bdcf61c63cd8d24177b4fe6d7468fa18e0c653457353d77ea5cf70ed307275534882b647bdbcb9e907dfcbca81ba3f4b2d55f07faa609fb921 + checksum: 05b80b8f3f9dd56b98fba39f8ec01e4f9db1ffd515594def1cc9e27a10d9f188042b482e92fd1865c1eaa91f633a28cf500ff212fa4a7a2f5c58108e9f3829d5 languageName: node linkType: hard "@aws-sdk/client-sqs@npm:^3.350.0": - version: 3.451.0 - resolution: "@aws-sdk/client-sqs@npm:3.451.0" + version: 3.465.0 + resolution: "@aws-sdk/client-sqs@npm:3.465.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/client-sts": 3.451.0 - "@aws-sdk/core": 3.451.0 - "@aws-sdk/credential-provider-node": 3.451.0 - "@aws-sdk/middleware-host-header": 3.451.0 - "@aws-sdk/middleware-logger": 3.451.0 - "@aws-sdk/middleware-recursion-detection": 3.451.0 - "@aws-sdk/middleware-sdk-sqs": 3.451.0 - "@aws-sdk/middleware-signing": 3.451.0 - "@aws-sdk/middleware-user-agent": 3.451.0 - "@aws-sdk/region-config-resolver": 3.451.0 - "@aws-sdk/types": 3.451.0 - "@aws-sdk/util-endpoints": 3.451.0 - "@aws-sdk/util-user-agent-browser": 3.451.0 - "@aws-sdk/util-user-agent-node": 3.451.0 + "@aws-sdk/client-sts": 3.465.0 + "@aws-sdk/core": 3.465.0 + "@aws-sdk/credential-provider-node": 3.465.0 + "@aws-sdk/middleware-host-header": 3.465.0 + "@aws-sdk/middleware-logger": 3.465.0 + "@aws-sdk/middleware-recursion-detection": 3.465.0 + "@aws-sdk/middleware-sdk-sqs": 3.465.0 + "@aws-sdk/middleware-signing": 3.465.0 + "@aws-sdk/middleware-user-agent": 3.465.0 + "@aws-sdk/region-config-resolver": 3.465.0 + "@aws-sdk/types": 3.465.0 + "@aws-sdk/util-endpoints": 3.465.0 + "@aws-sdk/util-user-agent-browser": 3.465.0 + "@aws-sdk/util-user-agent-node": 3.465.0 "@smithy/config-resolver": ^2.0.18 "@smithy/fetch-http-handler": ^2.2.6 "@smithy/hash-node": ^2.0.15 @@ -835,26 +616,26 @@ __metadata: "@smithy/util-retry": ^2.0.6 "@smithy/util-utf8": ^2.0.2 tslib: ^2.5.0 - checksum: a5344775ab77f098acd00e10e956fb525d30c8d350b5ea60d609f8fc7a81bfd0f545be646a267f36c7d1d08eecd55ce6de46bfa16d45c5cda7d6f0b86ce65570 + checksum: 0137ad4ca2fe482a21955f6085dc76eccc87ec3e3b36b18171aa0726f582b0f2c5041e6fa3f076ce60e266865262d7d52fa921abd1c958af7b3eafa8160d2beb languageName: node linkType: hard -"@aws-sdk/client-sso@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/client-sso@npm:3.451.0" +"@aws-sdk/client-sso@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/client-sso@npm:3.465.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/core": 3.451.0 - "@aws-sdk/middleware-host-header": 3.451.0 - "@aws-sdk/middleware-logger": 3.451.0 - "@aws-sdk/middleware-recursion-detection": 3.451.0 - "@aws-sdk/middleware-user-agent": 3.451.0 - "@aws-sdk/region-config-resolver": 3.451.0 - "@aws-sdk/types": 3.451.0 - "@aws-sdk/util-endpoints": 3.451.0 - "@aws-sdk/util-user-agent-browser": 3.451.0 - "@aws-sdk/util-user-agent-node": 3.451.0 + "@aws-sdk/core": 3.465.0 + "@aws-sdk/middleware-host-header": 3.465.0 + "@aws-sdk/middleware-logger": 3.465.0 + "@aws-sdk/middleware-recursion-detection": 3.465.0 + "@aws-sdk/middleware-user-agent": 3.465.0 + "@aws-sdk/region-config-resolver": 3.465.0 + "@aws-sdk/types": 3.465.0 + "@aws-sdk/util-endpoints": 3.465.0 + "@aws-sdk/util-user-agent-browser": 3.465.0 + "@aws-sdk/util-user-agent-node": 3.465.0 "@smithy/config-resolver": ^2.0.18 "@smithy/fetch-http-handler": ^2.2.6 "@smithy/hash-node": ^2.0.15 @@ -879,29 +660,29 @@ __metadata: "@smithy/util-retry": ^2.0.6 "@smithy/util-utf8": ^2.0.2 tslib: ^2.5.0 - checksum: 5ab78bf7704acad673eb2f97b7c9873e4e045e8476f827fc5f6e6f46ca37674f04efc1e168cdc4b3b0c5be1e6ada8e1a76fb4963a7af48560423a60b855f6005 + checksum: 83c2a1c1883a7900ea0c564e3f13c9d04a6970067e67182123b9be52505abbb1cf30d676312cb73ec637be4aab5094baa95d62e0ac910b0b2304cfe089f4f2df languageName: node linkType: hard -"@aws-sdk/client-sts@npm:3.451.0, @aws-sdk/client-sts@npm:^3.350.0": - version: 3.451.0 - resolution: "@aws-sdk/client-sts@npm:3.451.0" +"@aws-sdk/client-sts@npm:3.465.0, @aws-sdk/client-sts@npm:^3.350.0": + version: 3.465.0 + resolution: "@aws-sdk/client-sts@npm:3.465.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/core": 3.451.0 - "@aws-sdk/credential-provider-node": 3.451.0 - "@aws-sdk/middleware-host-header": 3.451.0 - "@aws-sdk/middleware-logger": 3.451.0 - "@aws-sdk/middleware-recursion-detection": 3.451.0 - "@aws-sdk/middleware-sdk-sts": 3.451.0 - "@aws-sdk/middleware-signing": 3.451.0 - "@aws-sdk/middleware-user-agent": 3.451.0 - "@aws-sdk/region-config-resolver": 3.451.0 - "@aws-sdk/types": 3.451.0 - "@aws-sdk/util-endpoints": 3.451.0 - "@aws-sdk/util-user-agent-browser": 3.451.0 - "@aws-sdk/util-user-agent-node": 3.451.0 + "@aws-sdk/core": 3.465.0 + "@aws-sdk/credential-provider-node": 3.465.0 + "@aws-sdk/middleware-host-header": 3.465.0 + "@aws-sdk/middleware-logger": 3.465.0 + "@aws-sdk/middleware-recursion-detection": 3.465.0 + "@aws-sdk/middleware-sdk-sts": 3.465.0 + "@aws-sdk/middleware-signing": 3.465.0 + "@aws-sdk/middleware-user-agent": 3.465.0 + "@aws-sdk/region-config-resolver": 3.465.0 + "@aws-sdk/types": 3.465.0 + "@aws-sdk/util-endpoints": 3.465.0 + "@aws-sdk/util-user-agent-browser": 3.465.0 + "@aws-sdk/util-user-agent-node": 3.465.0 "@smithy/config-resolver": ^2.0.18 "@smithy/fetch-http-handler": ^2.2.6 "@smithy/hash-node": ^2.0.15 @@ -927,50 +708,50 @@ __metadata: "@smithy/util-utf8": ^2.0.2 fast-xml-parser: 4.2.5 tslib: ^2.5.0 - checksum: d5fc965400ddecfd466c82e88ee2c0d1d59c06980774ce4b0715ae13e8c522f1ad346aa04891b68d755a792477ed483411e3040875f156bdd160ae6fde511f07 + checksum: 79c9fec0b4e682ef0258d5da75c18bbbdf278ebabfc2a2c80e1d5a8e13bb94aebf28a2d6e58940bb1b17ef9a8025a9e0c39ef7f6f52e723893f8fbf5d3fb61f0 languageName: node linkType: hard -"@aws-sdk/core@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/core@npm:3.451.0" +"@aws-sdk/core@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/core@npm:3.465.0" dependencies: "@smithy/smithy-client": ^2.1.15 tslib: ^2.5.0 - checksum: 20e36a0280ba6848222099eb30d3a09683563edf8eca48746529c9c2ae89dd7ab5d6a01ab05cd21b4bdd4f16117d41dc89e07d4d71f0abbcf50dcc5e85ef992d + checksum: 25aed5f8a15830a845a332e952cc55a92a52162af598a9dc2c6c6a92f711a32ab26826cabddedb6e41f597a1cbdcc68b896054a8e1396bacc31e985fe50188d4 languageName: node linkType: hard -"@aws-sdk/credential-provider-cognito-identity@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/credential-provider-cognito-identity@npm:3.451.0" +"@aws-sdk/credential-provider-cognito-identity@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/credential-provider-cognito-identity@npm:3.465.0" dependencies: - "@aws-sdk/client-cognito-identity": 3.451.0 - "@aws-sdk/types": 3.451.0 + "@aws-sdk/client-cognito-identity": 3.465.0 + "@aws-sdk/types": 3.465.0 "@smithy/property-provider": ^2.0.0 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: f12a7d576364d379c813a93b020e97ee7ed606f0d20ca0134527b0b51c0f2389d23ca391d094a0dad142084acfa8a31ca5bab36d22534552cd5231cca8b7609b + checksum: ad8400bdd6e92b7e40f12cd640f16c7289d4e7aee7a30c9389971baba793f10bd6d83cfbc676197fb1515d94d5e2a816aaede84492eb439c9833e5e51b1e475a languageName: node linkType: hard -"@aws-sdk/credential-provider-env@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/credential-provider-env@npm:3.451.0" +"@aws-sdk/credential-provider-env@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/credential-provider-env@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/property-provider": ^2.0.0 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: 20268e3d30317ab92cfce042fbaf751959d8da8e5669b822f8089df26bf5ea4972bab04eb0653fd903a4ab6c41118fae57f589a7e05fd3022e0154cb0cd71ed7 + checksum: 89f5f9b8edd1251f60e1aa32819480cc14e0b77c24249d070b653f21d788885c0fdbc4a69dd1ed9c526b31ee12869eda8979d2431b914af2bf664ef3940e58df languageName: node linkType: hard -"@aws-sdk/credential-provider-http@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/credential-provider-http@npm:3.451.0" +"@aws-sdk/credential-provider-http@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/credential-provider-http@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/fetch-http-handler": ^2.2.6 "@smithy/node-http-handler": ^2.1.9 "@smithy/property-provider": ^2.0.0 @@ -979,108 +760,108 @@ __metadata: "@smithy/types": ^2.5.0 "@smithy/util-stream": ^2.0.20 tslib: ^2.5.0 - checksum: 72d6c1487a24a95e765b665a0d2fb337fc86bb426f1fc999f7a2789a826302a649850791ec428eff13e250b4bf0e33f9d333dc3c34cfb15c83c863c254f601df + checksum: cbad41fb117b73136923d213d90cbe2753f984e96c1f2acc7504c4eb72e8f1e00db945f2f57989eed5e18d03857695ba40f3b71e3678e72ac48630d98fdf207f languageName: node linkType: hard -"@aws-sdk/credential-provider-ini@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/credential-provider-ini@npm:3.451.0" +"@aws-sdk/credential-provider-ini@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/credential-provider-ini@npm:3.465.0" dependencies: - "@aws-sdk/credential-provider-env": 3.451.0 - "@aws-sdk/credential-provider-process": 3.451.0 - "@aws-sdk/credential-provider-sso": 3.451.0 - "@aws-sdk/credential-provider-web-identity": 3.451.0 - "@aws-sdk/types": 3.451.0 + "@aws-sdk/credential-provider-env": 3.465.0 + "@aws-sdk/credential-provider-process": 3.465.0 + "@aws-sdk/credential-provider-sso": 3.465.0 + "@aws-sdk/credential-provider-web-identity": 3.465.0 + "@aws-sdk/types": 3.465.0 "@smithy/credential-provider-imds": ^2.0.0 "@smithy/property-provider": ^2.0.0 "@smithy/shared-ini-file-loader": ^2.0.6 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: 6d549724209f24c2e21fa88f318c7faaa9e2e58c854fcabc257b71cd2e6f849d38eaa932e16b44bf56c420183fd4ae804ac44c7584808af868ae7316fde2c3b1 + checksum: 6640707dd4a86b0e860e77a4560922f8c7689d25892b18246276b65aab3350547bf489a4f41a8377cde408f5d906259adebc3bf7cd77e74cec3d4ce7b3daa78a languageName: node linkType: hard -"@aws-sdk/credential-provider-node@npm:3.451.0, @aws-sdk/credential-provider-node@npm:^3.350.0": - version: 3.451.0 - resolution: "@aws-sdk/credential-provider-node@npm:3.451.0" +"@aws-sdk/credential-provider-node@npm:3.465.0, @aws-sdk/credential-provider-node@npm:^3.350.0": + version: 3.465.0 + resolution: "@aws-sdk/credential-provider-node@npm:3.465.0" dependencies: - "@aws-sdk/credential-provider-env": 3.451.0 - "@aws-sdk/credential-provider-ini": 3.451.0 - "@aws-sdk/credential-provider-process": 3.451.0 - "@aws-sdk/credential-provider-sso": 3.451.0 - "@aws-sdk/credential-provider-web-identity": 3.451.0 - "@aws-sdk/types": 3.451.0 + "@aws-sdk/credential-provider-env": 3.465.0 + "@aws-sdk/credential-provider-ini": 3.465.0 + "@aws-sdk/credential-provider-process": 3.465.0 + "@aws-sdk/credential-provider-sso": 3.465.0 + "@aws-sdk/credential-provider-web-identity": 3.465.0 + "@aws-sdk/types": 3.465.0 "@smithy/credential-provider-imds": ^2.0.0 "@smithy/property-provider": ^2.0.0 "@smithy/shared-ini-file-loader": ^2.0.6 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: 19dd93776250fd4e55a70daaca311f1f0bb27e5b195713e3f9d8e8431411e637c917a46bbd41dcf2044a93e0fdea02ebb238863f8c49684bf3e63aff928b5a6b + checksum: 9c8d444d95f67e64463679f0f6a87d3bb42cdbc4abd44abdb11e8da4c1f7e620a7dba424d26b97cf86965e790fd9933f984df7ad651b10524136511971cd5ab4 languageName: node linkType: hard -"@aws-sdk/credential-provider-process@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/credential-provider-process@npm:3.451.0" +"@aws-sdk/credential-provider-process@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/credential-provider-process@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/property-provider": ^2.0.0 "@smithy/shared-ini-file-loader": ^2.0.6 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: 2c01b893d03f9a001bb970553bad14061e807445ec96002bb85d37445fa28403a5adbfc68036f01fc20d7c5310e88ccbcd96cd54d5ba9326640a18d6c96b93a2 + checksum: e48cb385eccd44ddbf6a32b8fb26113025cd474ee28942953b1777a2d02b4bdc905da5d69aee9cf3712cdb888e652b86a7d9853f14caf7436ce59e6657c02140 languageName: node linkType: hard -"@aws-sdk/credential-provider-sso@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/credential-provider-sso@npm:3.451.0" +"@aws-sdk/credential-provider-sso@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/credential-provider-sso@npm:3.465.0" dependencies: - "@aws-sdk/client-sso": 3.451.0 - "@aws-sdk/token-providers": 3.451.0 - "@aws-sdk/types": 3.451.0 + "@aws-sdk/client-sso": 3.465.0 + "@aws-sdk/token-providers": 3.465.0 + "@aws-sdk/types": 3.465.0 "@smithy/property-provider": ^2.0.0 "@smithy/shared-ini-file-loader": ^2.0.6 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: 34483b4a213cac1f4859978319b38ef7f69a0d090de49a98d987486da2691a4cf5f474601ce338497d030156b1616a455a8d0bb79a4abbdbe8873a91e451ead2 + checksum: 40764632b5b117bd9f8263b6dced2a6231093f4e5e26b6cc6730e16e6c92b478563d78dbc49a5fde80e1d588439c3218c89acf1821030dc8979211e164502892 languageName: node linkType: hard -"@aws-sdk/credential-provider-web-identity@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/credential-provider-web-identity@npm:3.451.0" +"@aws-sdk/credential-provider-web-identity@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/credential-provider-web-identity@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/property-provider": ^2.0.0 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: 2f677b9e4f727b6c24ed64d1ba23f524d8d136394dc62376db7b60acf57938a911d178bcdc33688a0cb17b5f55e2cc4aa455473a4393864568cacd202a50ce44 + checksum: 2bdd92ed25b310d88fbbf42fa26e58070d910dd25bd569b4a3bc7d328f3dff421beb1a775f21c1a1696f439f561ccf7dd595a42829a3b88d432683b3f4a8c58e languageName: node linkType: hard "@aws-sdk/credential-providers@npm:^3.350.0": - version: 3.451.0 - resolution: "@aws-sdk/credential-providers@npm:3.451.0" + version: 3.465.0 + resolution: "@aws-sdk/credential-providers@npm:3.465.0" dependencies: - "@aws-sdk/client-cognito-identity": 3.451.0 - "@aws-sdk/client-sso": 3.451.0 - "@aws-sdk/client-sts": 3.451.0 - "@aws-sdk/credential-provider-cognito-identity": 3.451.0 - "@aws-sdk/credential-provider-env": 3.451.0 - "@aws-sdk/credential-provider-http": 3.451.0 - "@aws-sdk/credential-provider-ini": 3.451.0 - "@aws-sdk/credential-provider-node": 3.451.0 - "@aws-sdk/credential-provider-process": 3.451.0 - "@aws-sdk/credential-provider-sso": 3.451.0 - "@aws-sdk/credential-provider-web-identity": 3.451.0 - "@aws-sdk/types": 3.451.0 + "@aws-sdk/client-cognito-identity": 3.465.0 + "@aws-sdk/client-sso": 3.465.0 + "@aws-sdk/client-sts": 3.465.0 + "@aws-sdk/credential-provider-cognito-identity": 3.465.0 + "@aws-sdk/credential-provider-env": 3.465.0 + "@aws-sdk/credential-provider-http": 3.465.0 + "@aws-sdk/credential-provider-ini": 3.465.0 + "@aws-sdk/credential-provider-node": 3.465.0 + "@aws-sdk/credential-provider-process": 3.465.0 + "@aws-sdk/credential-provider-sso": 3.465.0 + "@aws-sdk/credential-provider-web-identity": 3.465.0 + "@aws-sdk/types": 3.465.0 "@smithy/credential-provider-imds": ^2.0.0 "@smithy/property-provider": ^2.0.0 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: a003392aaf26b285076f833508166c9b761b23493c72d2835c347202f78f6d0dd74ffb5eb028da25e604a69edd7fdd0579de729768a522e09af46f297689e9d3 + checksum: ff594821d82227c2cf9884283f003d72c322f78d0aeace12fb47f5b0fa7fbb3cce7d6b96822df848a89649eeea6bc9dda18de40e5a5399a8c5f6930fe906d3e3 languageName: node linkType: hard @@ -1106,8 +887,8 @@ __metadata: linkType: hard "@aws-sdk/lib-storage@npm:^3.350.0": - version: 3.451.0 - resolution: "@aws-sdk/lib-storage@npm:3.451.0" + version: 3.465.0 + resolution: "@aws-sdk/lib-storage@npm:3.465.0" dependencies: "@smithy/abort-controller": ^2.0.1 "@smithy/middleware-endpoint": ^2.2.0 @@ -1118,22 +899,22 @@ __metadata: tslib: ^2.5.0 peerDependencies: "@aws-sdk/client-s3": ^3.0.0 - checksum: b05ed4cda2655f678f13a1a090b809d32fe4666d650547ef7a66a8f10f26ed0b10865d2b4b6bfa6a2fae285dc2b70c2a773ab01a125e60d038358901ff266c65 + checksum: fe351e545dbc28d20d936ae6e3ea1c5faf672bdc402d3e15a3709fc8175060b8925647b381b0a3ad0eac1d25b73e16c5580ad1e32764a011a1ca77432662f682 languageName: node linkType: hard -"@aws-sdk/middleware-bucket-endpoint@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/middleware-bucket-endpoint@npm:3.451.0" +"@aws-sdk/middleware-bucket-endpoint@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/middleware-bucket-endpoint@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 - "@aws-sdk/util-arn-parser": 3.310.0 + "@aws-sdk/types": 3.465.0 + "@aws-sdk/util-arn-parser": 3.465.0 "@smithy/node-config-provider": ^2.1.5 "@smithy/protocol-http": ^3.0.9 "@smithy/types": ^2.5.0 "@smithy/util-config-provider": ^2.0.0 tslib: ^2.5.0 - checksum: 4fba4c2ca560fe9a482d59a374239b5c6bf63a9f49373b91d9b1ed3aced648f0198b7d3b82c14fa896ec5f465562871bf9c59c29ff2e3f94df88f4641ff2bf78 + checksum: 381375b8eb4e37e14612c7a5c9e027163cd116747a766e2c2fc0cf5a5349f0e3fd5f8b871657c0c38596c8a0c28c1093fcebcbeb99c142d7d17a3f2f88690650 languageName: node linkType: hard @@ -1150,116 +931,119 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/middleware-expect-continue@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/middleware-expect-continue@npm:3.451.0" +"@aws-sdk/middleware-expect-continue@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/middleware-expect-continue@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/protocol-http": ^3.0.9 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: 3bfe5a1fc8f3e8baaec650aa085cb7a1c79d8d5af41bd940c005ba9c3c6d4feca2b65513d3494fe986276f43154e829f95ce1de4d852a741d7900cd95b864c1a + checksum: 88ca4283f94057978dabc463083dafddd2b01d368cc0fb9fb6d15d21dbbf828fd615e6fc649a47bac2919d2e226376d233604f91bf942421452ea34827e0a652 languageName: node linkType: hard -"@aws-sdk/middleware-flexible-checksums@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/middleware-flexible-checksums@npm:3.451.0" +"@aws-sdk/middleware-flexible-checksums@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/middleware-flexible-checksums@npm:3.465.0" dependencies: "@aws-crypto/crc32": 3.0.0 "@aws-crypto/crc32c": 3.0.0 - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/is-array-buffer": ^2.0.0 "@smithy/protocol-http": ^3.0.9 "@smithy/types": ^2.5.0 "@smithy/util-utf8": ^2.0.2 tslib: ^2.5.0 - checksum: 24f69c68437899286c19e68caf417e263529190f4e663c8e886a032090452c9cbaa0d6d25887a65a7234edb9d2657f847b2ff589aec2341852d727a174c94cf2 + checksum: e003b96421e1251eb629231a6afebd99b5795c219562496c4f1d23165233a073fffc754e18819f874a600a518ada4c2647a4c9fbd88b2bf2ce39f68501d04a0f languageName: node linkType: hard -"@aws-sdk/middleware-host-header@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/middleware-host-header@npm:3.451.0" +"@aws-sdk/middleware-host-header@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/middleware-host-header@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/protocol-http": ^3.0.9 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: ba06894d88f5fdd06762de839e7542b1605c73474d7bf93e6b0b74a62e77c5f3f4dd612daaf76e9eff59447c95a73cfa69b29f9856f7282227eea31173db99ca + checksum: fe7fba3fdd12d3d7bee052583a353cd5afb64e652a44c89af0c416d7994110dfcf7e03df3380ce06724305a10774661a72d09369f655f6c4b7d1d9ead28a957a languageName: node linkType: hard -"@aws-sdk/middleware-location-constraint@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/middleware-location-constraint@npm:3.451.0" +"@aws-sdk/middleware-location-constraint@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/middleware-location-constraint@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: d47ea96b28c429196352f2e99cbd5a3ab57726e0be0bfdb2d9ef7acb1e492a4a318f7c40e54bd14ce3b8d3f6f340e1fa89fcd5e3c62cf4e1f8edf08edd78b98b + checksum: 341e9adc1eb255b5033d23b3797e6093ae1955ea2df912f7de69bf35632d8e1197d73166900d16e8224bc7ecdc800ba5649b38fec8e101efbe8ed0d27b344ec6 languageName: node linkType: hard -"@aws-sdk/middleware-logger@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/middleware-logger@npm:3.451.0" +"@aws-sdk/middleware-logger@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/middleware-logger@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: 34342389013ab83407c34eb58a5e162fb7b294050030f494a2b538e85492828a2719642365af1f7e5b89f847888fd936469c4bdb6843b81887edb89896b0a926 + checksum: dd28c204cc9986780f25090ce9d91115b5784cc31c5677018f7f289c90476a631a044702da70c576d3263a5f16f99aa41851fc28948e115eaf64fc0986a18a7f languageName: node linkType: hard -"@aws-sdk/middleware-recursion-detection@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/middleware-recursion-detection@npm:3.451.0" +"@aws-sdk/middleware-recursion-detection@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/middleware-recursion-detection@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/protocol-http": ^3.0.9 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: 70625b5c9e9f61d4c58a05a8aa616ec31c7bb23f45e8187fffe30003861fd3fe0bce96e6b120b4bb3937c0c66e04c96c8e024a4c42dd0524f0a0b6dc73b7e1d5 + checksum: 3b718e0e300fa115198702645d177916d059612c76b17ea81c6d722b3c8312606b50aa765a990711f44c899724bc82c8ebd45a2a5ddaee788cb28ef3449f726b languageName: node linkType: hard -"@aws-sdk/middleware-sdk-s3@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/middleware-sdk-s3@npm:3.451.0" +"@aws-sdk/middleware-sdk-s3@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/middleware-sdk-s3@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 - "@aws-sdk/util-arn-parser": 3.310.0 + "@aws-sdk/types": 3.465.0 + "@aws-sdk/util-arn-parser": 3.465.0 + "@smithy/node-config-provider": ^2.1.5 "@smithy/protocol-http": ^3.0.9 + "@smithy/signature-v4": ^2.0.0 "@smithy/smithy-client": ^2.1.15 "@smithy/types": ^2.5.0 + "@smithy/util-config-provider": ^2.0.0 tslib: ^2.5.0 - checksum: e8ba5b5d5918223b4f76113dcfabf7f342880f0ef5a0ebae861f142f2d74748f1aadd47270d61c591e31ba88c52cfca0cf7ba992384b34271e13ca144edf48a6 + checksum: 61117fa5da796ac89926df1caf3709ad8405810b20b089e7c122f069f3440556923d939da1fd24765cadc8ccde5670d1339dc84ed4e82908c7755ff2d73406cd languageName: node linkType: hard -"@aws-sdk/middleware-sdk-sqs@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/middleware-sdk-sqs@npm:3.451.0" +"@aws-sdk/middleware-sdk-sqs@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/middleware-sdk-sqs@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/types": ^2.5.0 "@smithy/util-hex-encoding": ^2.0.0 "@smithy/util-utf8": ^2.0.2 tslib: ^2.5.0 - checksum: 4ef20e1ebffb3a2fe6ddc77a5ca18203ef405e71f77b3167cbee8241e5ff77be08d3ca43fb25c3582454ddc53d42b44f38c6942c95d706ac4c4f6111d062910a + checksum: b760657584c0362c603f38ea4df4744b42d40734c6433232fe5ec590f501cac7be705da8a2afa6c5cce0e4cb73b8bbffbc7066d7b9d28dd042055f478a8f0490 languageName: node linkType: hard -"@aws-sdk/middleware-sdk-sts@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/middleware-sdk-sts@npm:3.451.0" +"@aws-sdk/middleware-sdk-sts@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/middleware-sdk-sts@npm:3.465.0" dependencies: - "@aws-sdk/middleware-signing": 3.451.0 - "@aws-sdk/types": 3.451.0 + "@aws-sdk/middleware-signing": 3.465.0 + "@aws-sdk/types": 3.465.0 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: 8aef507f62ffc342bbf70f3ecb24e96d286526aa23040a13a1f4761059b1a57f3d2bed9b14caef0bde53dd440584ef9fea6947ff18cfdae7498b028beefa9ec5 + checksum: cddb425eacd40dddf490d2af0f8b9e6032cd0cc7da0138f25876aa3d57ab48148cc105db16f411aaf1857c22c3841e8e904a781c383f3b6f8b541282575ffd48 languageName: node linkType: hard @@ -1273,42 +1057,42 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/middleware-signing@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/middleware-signing@npm:3.451.0" +"@aws-sdk/middleware-signing@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/middleware-signing@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/property-provider": ^2.0.0 "@smithy/protocol-http": ^3.0.9 "@smithy/signature-v4": ^2.0.0 "@smithy/types": ^2.5.0 "@smithy/util-middleware": ^2.0.6 tslib: ^2.5.0 - checksum: 6a2900bdad76733fec5155af97f9f2b3448451bf15357d0dfbc35f646a321120dc6b5d5e3c5690b0bfc5294044c139ce28b3a07c149f33dd9572399f5ae0999d + checksum: de9aa66c61d3f499c4f0cca7bee5359777d8357c3aaccf51a9062eda923b82f2d5b13808462c2a2f9120231e3c1a66ae4e35636f08da8ec3521ace1d970ff67a languageName: node linkType: hard -"@aws-sdk/middleware-ssec@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/middleware-ssec@npm:3.451.0" +"@aws-sdk/middleware-ssec@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/middleware-ssec@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: f9666c4aba9085eb6257e49636e0d4eae61ce9be1411965cb2212a0ce1bf63f89365db5b4710a9154e1001dba8ac0be09a46d6e38c13f6b9dc2b73b8a4efdce4 + checksum: c04dd79af338bbbb6f439e123adc961698a5a71d5ab66deab8ef3fe08dc63c7d24d92646b32cc7c6eb684e101dfb0fd590618124567470b40a389f63fa90f7b3 languageName: node linkType: hard -"@aws-sdk/middleware-user-agent@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/middleware-user-agent@npm:3.451.0" +"@aws-sdk/middleware-user-agent@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/middleware-user-agent@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 - "@aws-sdk/util-endpoints": 3.451.0 + "@aws-sdk/types": 3.465.0 + "@aws-sdk/util-endpoints": 3.465.0 "@smithy/protocol-http": ^3.0.9 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: d547fb999a6f657d8806165102b57a082a4e5464666c928148292e233be38a53209c1b9a39eac7e0c403a77e0336159b9a72e89daad86365306421058b0c4f92 + checksum: e00a86370f0d3e4f63d2ca7153dcbfa12b8d492141434dd5cdfd3ec402bbed4d5c80661d2aec50f251979c6091c15752a16431058a928788f1200757605271bd languageName: node linkType: hard @@ -1356,29 +1140,30 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/region-config-resolver@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/region-config-resolver@npm:3.451.0" +"@aws-sdk/region-config-resolver@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/region-config-resolver@npm:3.465.0" dependencies: "@smithy/node-config-provider": ^2.1.5 "@smithy/types": ^2.5.0 "@smithy/util-config-provider": ^2.0.0 "@smithy/util-middleware": ^2.0.6 tslib: ^2.5.0 - checksum: df1e324d873399ff022b29a0a7d03e840aadbb0a42fad0f7f1a11f041d5f37319ecefc58038d62eff998e627b07752c96ab5879b2a34ebd088e45fc9c7a12303 + checksum: 3af46df3f8a36a7280ff488f03e59c16801287bc56607186e1e7af1818adfb1610524d7873648ac31378277c64b44d549205232e495f544d5ca1ea34dda0f745 languageName: node linkType: hard -"@aws-sdk/signature-v4-multi-region@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/signature-v4-multi-region@npm:3.451.0" +"@aws-sdk/signature-v4-multi-region@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/signature-v4-multi-region@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/middleware-sdk-s3": 3.465.0 + "@aws-sdk/types": 3.465.0 "@smithy/protocol-http": ^3.0.9 "@smithy/signature-v4": ^2.0.0 "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: d0c9e434e28c4c06a78d6d12ebe0067bf4d299b73e106ef336dd730a63941dcdb443147a998603c0f64ec8a1a9f53c0b8ad7f0e67fe36959c154c1dcf664a485 + checksum: d40dbc77b963357afa3536cd461bfb1dd1d7ad734d33185a9d82b6a6104f517ec7283e48a9855ec75d90235fc7fdd06d66992c5a792d9f36e5ac717155069271 languageName: node linkType: hard @@ -1398,21 +1183,21 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/token-providers@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/token-providers@npm:3.451.0" +"@aws-sdk/token-providers@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/token-providers@npm:3.465.0" dependencies: "@aws-crypto/sha256-browser": 3.0.0 "@aws-crypto/sha256-js": 3.0.0 - "@aws-sdk/middleware-host-header": 3.451.0 - "@aws-sdk/middleware-logger": 3.451.0 - "@aws-sdk/middleware-recursion-detection": 3.451.0 - "@aws-sdk/middleware-user-agent": 3.451.0 - "@aws-sdk/region-config-resolver": 3.451.0 - "@aws-sdk/types": 3.451.0 - "@aws-sdk/util-endpoints": 3.451.0 - "@aws-sdk/util-user-agent-browser": 3.451.0 - "@aws-sdk/util-user-agent-node": 3.451.0 + "@aws-sdk/middleware-host-header": 3.465.0 + "@aws-sdk/middleware-logger": 3.465.0 + "@aws-sdk/middleware-recursion-detection": 3.465.0 + "@aws-sdk/middleware-user-agent": 3.465.0 + "@aws-sdk/region-config-resolver": 3.465.0 + "@aws-sdk/types": 3.465.0 + "@aws-sdk/util-endpoints": 3.465.0 + "@aws-sdk/util-user-agent-browser": 3.465.0 + "@aws-sdk/util-user-agent-node": 3.465.0 "@smithy/config-resolver": ^2.0.18 "@smithy/fetch-http-handler": ^2.2.6 "@smithy/hash-node": ^2.0.15 @@ -1439,7 +1224,7 @@ __metadata: "@smithy/util-retry": ^2.0.6 "@smithy/util-utf8": ^2.0.2 tslib: ^2.5.0 - checksum: 1c2d3927e33eedcfc0482744f065c44f632d13fb7a03152dd4d5b04546ab06fed6373f2e8432caf332c0ab93ac9a64bf88cc5071702f6f1adacc8aed53ed3e3b + checksum: ebfeb68e09294775b345f4fbd76be546283a5a10cb388fdf25c38d0f229c29616dbe0c708d0fcf196a74a52e3df0a55e77cada158cbcb6ace44a86f9606ce1eb languageName: node linkType: hard @@ -1453,13 +1238,13 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/types@npm:3.451.0, @aws-sdk/types@npm:^3.222.0, @aws-sdk/types@npm:^3.347.0": - version: 3.451.0 - resolution: "@aws-sdk/types@npm:3.451.0" +"@aws-sdk/types@npm:3.465.0, @aws-sdk/types@npm:^3.222.0, @aws-sdk/types@npm:^3.347.0": + version: 3.465.0 + resolution: "@aws-sdk/types@npm:3.465.0" dependencies: "@smithy/types": ^2.5.0 tslib: ^2.5.0 - checksum: 0f66eccf707ece1f21af6c8099a6b13191a119f48dacebd8794d74263628b95dcf0bfa479493ec1774c902fe7bb8867cfcbd1cf7d908653fe0e0759168970d19 + checksum: 73f05accd990f70a0eb58c5c568ed091a097caab808415efb420deee0873e912469fe2e0a68e1d0087cd376237cc4a7e3182a475670cd295676735d90f132ca6 languageName: node linkType: hard @@ -1474,12 +1259,12 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-arn-parser@npm:3.310.0, @aws-sdk/util-arn-parser@npm:^3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/util-arn-parser@npm:3.310.0" +"@aws-sdk/util-arn-parser@npm:3.465.0, @aws-sdk/util-arn-parser@npm:^3.310.0": + version: 3.465.0 + resolution: "@aws-sdk/util-arn-parser@npm:3.465.0" dependencies: tslib: ^2.5.0 - checksum: faac1e10f8bb6c2fe5fee82bcb7ce56c2b37ae9ffdb2b78b0746a7a06005eaa5ea747a0a10eaf490c1c4907ecc327e1c94a600e26a069e023e54b8d63c031e96 + checksum: ce2dd638e9b8ef3260ce1c1ae299a4e44cbaa28a07cda9f1033b763cea8b1d901b7a963338e8a172af17074d06811f09605f3f903318c4bd2bbf102e92d02546 languageName: node linkType: hard @@ -1493,14 +1278,14 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-endpoints@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/util-endpoints@npm:3.451.0" +"@aws-sdk/util-endpoints@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/util-endpoints@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/util-endpoints": ^1.0.4 tslib: ^2.5.0 - checksum: ebb558cadb896754f2f0078b31720441bf8d8f4735372950a00c677b2db1a9076a3aefa3c14148e39708b593f148a12930e1b29ecce6e4ed653ea10ab26f3c80 + checksum: 38b0a5335f67c63dcc3562b1b34161249ff5638da4ebdc295f561d64448d84215fb4b46825ee6ebcfa7010449e1725c3705230529a74510e40f2a0e37881a0f1 languageName: node linkType: hard @@ -1552,23 +1337,23 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/util-user-agent-browser@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/util-user-agent-browser@npm:3.451.0" +"@aws-sdk/util-user-agent-browser@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/util-user-agent-browser@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/types": ^2.5.0 bowser: ^2.11.0 tslib: ^2.5.0 - checksum: 83e6a74aca3575b385db09787021bbd40589afdff0fcad1d4ea33c7a4711f3147d61fa6465a629838d8d093609d43097bedb4bfc6e12e3695179f4c244b691e3 + checksum: 46c280a8284ddc34096eff401a9372f0fc84c1805c8dc1489ad4e6a44b4fac0b5c58bc200a00c873ce5928bf2bbc11fe4ab465b8cb606ddf64ca2cb76be205c4 languageName: node linkType: hard -"@aws-sdk/util-user-agent-node@npm:3.451.0": - version: 3.451.0 - resolution: "@aws-sdk/util-user-agent-node@npm:3.451.0" +"@aws-sdk/util-user-agent-node@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/util-user-agent-node@npm:3.465.0" dependencies: - "@aws-sdk/types": 3.451.0 + "@aws-sdk/types": 3.465.0 "@smithy/node-config-provider": ^2.1.5 "@smithy/types": ^2.5.0 tslib: ^2.5.0 @@ -1577,7 +1362,7 @@ __metadata: peerDependenciesMeta: aws-crt: optional: true - checksum: 94ccacf05776b558f965d8081602435565be59a62e0ec61946a49c2519f742ae2552df407b9ba9b37d8cbac1ef8ea5538bb72c96bc1e1c55ab9ecb6be187fe67 + checksum: 197203f9345aefedda3109bc523c218382de2138f9fd2ef284ddc8f6d73819a5688503706098fb86562d3efd8dde3dc769f9fd59feba284fa890b3152111a1de languageName: node linkType: hard @@ -1600,12 +1385,12 @@ __metadata: languageName: node linkType: hard -"@aws-sdk/xml-builder@npm:3.310.0": - version: 3.310.0 - resolution: "@aws-sdk/xml-builder@npm:3.310.0" +"@aws-sdk/xml-builder@npm:3.465.0": + version: 3.465.0 + resolution: "@aws-sdk/xml-builder@npm:3.465.0" dependencies: tslib: ^2.5.0 - checksum: fc17fd8f68470702d947948ada46097bdddecafdc68fa57bf584320e92748e8ef0372a51999d3ab7902ba4f62c2dbfbdec2dba1180fca19bb5127bad1ef0e48b + checksum: 33c370b216aece520352bc36dc147649bee0bca7139a5d5c6e49e99756e9ca369c73bacc55dff5920f6003d06a29a1375920e18b9776c264de925c5a9cfc3deb languageName: node linkType: hard @@ -1618,18 +1403,18 @@ __metadata: languageName: node linkType: hard -"@azure/arm-appservice@npm:^13.0.1": - version: 13.0.3 - resolution: "@azure/arm-appservice@npm:13.0.3" +"@azure/arm-appservice@npm:^14.0.0": + version: 14.1.0 + resolution: "@azure/arm-appservice@npm:14.1.0" dependencies: "@azure/abort-controller": ^1.0.0 "@azure/core-auth": ^1.3.0 - "@azure/core-client": ^1.6.1 - "@azure/core-lro": ^2.2.0 + "@azure/core-client": ^1.7.0 + "@azure/core-lro": ^2.5.4 "@azure/core-paging": ^1.2.0 - "@azure/core-rest-pipeline": ^1.8.0 + "@azure/core-rest-pipeline": ^1.12.0 tslib: ^2.2.0 - checksum: 9cd73985a31744fd7da56654c1de2d1396e93fa0cc3527b7c2843e56913e2b0abd81d996a319447f2f289421c45ede6a87f820ed0f4414e7cd2afeb383ee8a0a + checksum: b989bc26d94056e0f02d2ede9981ebbf90ebefdc8b35c8f66531d3220c4ce52484d49c0a15b7056b79898a76533b0de0edf141b7736aadfabf2c33305804b884 languageName: node linkType: hard @@ -1656,9 +1441,9 @@ __metadata: languageName: node linkType: hard -"@azure/core-client@npm:^1.4.0, @azure/core-client@npm:^1.6.1": - version: 1.6.1 - resolution: "@azure/core-client@npm:1.6.1" +"@azure/core-client@npm:^1.4.0, @azure/core-client@npm:^1.7.0": + version: 1.7.3 + resolution: "@azure/core-client@npm:1.7.3" dependencies: "@azure/abort-controller": ^1.0.0 "@azure/core-auth": ^1.4.0 @@ -1667,7 +1452,7 @@ __metadata: "@azure/core-util": ^1.0.0 "@azure/logger": ^1.0.0 tslib: ^2.2.0 - checksum: 400890a9b5f0c8801ff92005c3cba7bb5124634e321735406731bef33688a79f23d28b49fccdfab90814dade41a13f3d3cb99f80151a2bff17628416e811afb6 + checksum: 155a188b75b2d5ea783d5fde50479337c41796736f0fced1576466c8251e429195c229f2aff0bf897761f15c19d8fd0deea9a54aab514bd3584e37140e3f0cdc languageName: node linkType: hard @@ -1693,15 +1478,15 @@ __metadata: languageName: node linkType: hard -"@azure/core-lro@npm:^2.2.0": - version: 2.2.4 - resolution: "@azure/core-lro@npm:2.2.4" +"@azure/core-lro@npm:^2.2.0, @azure/core-lro@npm:^2.5.4": + version: 2.5.4 + resolution: "@azure/core-lro@npm:2.5.4" dependencies: "@azure/abort-controller": ^1.0.0 - "@azure/core-tracing": 1.0.0-preview.13 + "@azure/core-util": ^1.2.0 "@azure/logger": ^1.0.0 tslib: ^2.2.0 - checksum: f3db331409f95fc71206acd9f64efbbdf43a83d86c2012bdd19e577a603225b3a7e74e827e5c6aad1cf18024bdd8110c4cf341f7386fc83c5cb86ab72f5ad9ca + checksum: f048b99850e8497b557cf661c2f8a384ea1227de6ea0c0e1436653851c3932e28a05056a380f7c20ebc51e4c6d7bd15d7dfabc6ecca80eddb9dc3e3339df9519 languageName: node linkType: hard @@ -1714,21 +1499,20 @@ __metadata: languageName: node linkType: hard -"@azure/core-rest-pipeline@npm:^1.1.0, @azure/core-rest-pipeline@npm:^1.8.0, @azure/core-rest-pipeline@npm:^1.9.1": - version: 1.9.2 - resolution: "@azure/core-rest-pipeline@npm:1.9.2" +"@azure/core-rest-pipeline@npm:^1.1.0, @azure/core-rest-pipeline@npm:^1.12.0, @azure/core-rest-pipeline@npm:^1.9.1": + version: 1.12.2 + resolution: "@azure/core-rest-pipeline@npm:1.12.2" dependencies: "@azure/abort-controller": ^1.0.0 "@azure/core-auth": ^1.4.0 "@azure/core-tracing": ^1.0.1 - "@azure/core-util": ^1.0.0 + "@azure/core-util": ^1.3.0 "@azure/logger": ^1.0.0 form-data: ^4.0.0 http-proxy-agent: ^5.0.0 https-proxy-agent: ^5.0.0 tslib: ^2.2.0 - uuid: ^8.3.0 - checksum: cdfdaf8bdb0778f40ecfeb8b5da0b4f8643d641b75bb5869485afd38f7c3127ab088ac2fe2980df03d28fb6715928e04560343ee6416246aebe75443c4dd2906 + checksum: a774ab2e87ff56d7f3ef1844a814bbd76264ea1c33534081d38ce6df1098d803d0b13b15912f9053d0695ca2669b0dd104c8feec8dbf24df80a3608ea784fc9e languageName: node linkType: hard @@ -1751,7 +1535,7 @@ __metadata: languageName: node linkType: hard -"@azure/core-util@npm:^1.0.0, @azure/core-util@npm:^1.1.0, @azure/core-util@npm:^1.1.1, @azure/core-util@npm:^1.6.1": +"@azure/core-util@npm:^1.0.0, @azure/core-util@npm:^1.1.0, @azure/core-util@npm:^1.1.1, @azure/core-util@npm:^1.2.0, @azure/core-util@npm:^1.3.0, @azure/core-util@npm:^1.6.1": version: 1.6.1 resolution: "@azure/core-util@npm:1.6.1" dependencies: @@ -1783,6 +1567,28 @@ __metadata: languageName: node linkType: hard +"@azure/identity@npm:^4.0.0": + version: 4.0.0 + resolution: "@azure/identity@npm:4.0.0" + dependencies: + "@azure/abort-controller": ^1.0.0 + "@azure/core-auth": ^1.5.0 + "@azure/core-client": ^1.4.0 + "@azure/core-rest-pipeline": ^1.1.0 + "@azure/core-tracing": ^1.0.0 + "@azure/core-util": ^1.0.0 + "@azure/logger": ^1.0.0 + "@azure/msal-browser": ^3.5.0 + "@azure/msal-node": ^2.5.1 + events: ^3.0.0 + jws: ^4.0.0 + open: ^8.0.0 + stoppable: ^1.1.0 + tslib: ^2.2.0 + checksum: 534a62afe4715d18e221e021f8088873b1efad34344bd4c6c4685572c89517f15a646e246e9233e8db7942b0a5c73f1961ea63e3baf39c28edde1ba51da4423d + languageName: node + linkType: hard + "@azure/logger@npm:^1.0.0": version: 1.0.1 resolution: "@azure/logger@npm:1.0.1" @@ -1881,14 +1687,14 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.18.8, @babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9": +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9": version: 7.22.9 resolution: "@babel/compat-data@npm:7.22.9" checksum: bed77d9044ce948b4327b30dd0de0779fa9f3a7ed1f2d31638714ed00229fa71fc4d1617ae0eb1fad419338d3658d0e9a5a083297451e09e73e078d0347ff808 languageName: node linkType: hard -"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.14.0, @babel/core@npm:^7.19.6, @babel/core@npm:^7.23.0, @babel/core@npm:^7.23.2": +"@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3, @babel/core@npm:^7.19.6, @babel/core@npm:^7.23.0, @babel/core@npm:^7.23.3": version: 7.23.3 resolution: "@babel/core@npm:7.23.3" dependencies: @@ -1911,7 +1717,7 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.14.0, @babel/generator@npm:^7.18.13, @babel/generator@npm:^7.23.3, @babel/generator@npm:^7.7.2": +"@babel/generator@npm:^7.23.3, @babel/generator@npm:^7.7.2": version: 7.23.3 resolution: "@babel/generator@npm:7.23.3" dependencies: @@ -1941,7 +1747,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.18.9, @babel/helper-compilation-targets@npm:^7.22.10, @babel/helper-compilation-targets@npm:^7.22.15, @babel/helper-compilation-targets@npm:^7.22.5, @babel/helper-compilation-targets@npm:^7.22.6": +"@babel/helper-compilation-targets@npm:^7.22.10, @babel/helper-compilation-targets@npm:^7.22.15, @babel/helper-compilation-targets@npm:^7.22.5, @babel/helper-compilation-targets@npm:^7.22.6": version: 7.22.15 resolution: "@babel/helper-compilation-targets@npm:7.22.15" dependencies: @@ -1954,7 +1760,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.22.11, @babel/helper-create-class-features-plugin@npm:^7.22.15, @babel/helper-create-class-features-plugin@npm:^7.22.5": +"@babel/helper-create-class-features-plugin@npm:^7.22.11, @babel/helper-create-class-features-plugin@npm:^7.22.15, @babel/helper-create-class-features-plugin@npm:^7.22.5": version: 7.22.15 resolution: "@babel/helper-create-class-features-plugin@npm:7.22.15" dependencies: @@ -2069,7 +1875,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.18.9, @babel/helper-plugin-utils@npm:^7.19.0, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": version: 7.22.5 resolution: "@babel/helper-plugin-utils@npm:7.22.5" checksum: c0fc7227076b6041acd2f0e818145d2e8c41968cc52fb5ca70eed48e21b8fe6dd88a0a91cbddf4951e33647336eb5ae184747ca706817ca3bef5e9e905151ff5 @@ -2183,7 +1989,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.20.15, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.3": +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.23.3": version: 7.23.3 resolution: "@babel/parser@npm:7.23.3" bin: @@ -2216,33 +2022,6 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-proposal-class-properties@npm:^7.0.0": - version: 7.18.6 - resolution: "@babel/plugin-proposal-class-properties@npm:7.18.6" - dependencies: - "@babel/helper-create-class-features-plugin": ^7.18.6 - "@babel/helper-plugin-utils": ^7.18.6 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 49a78a2773ec0db56e915d9797e44fd079ab8a9b2e1716e0df07c92532f2c65d76aeda9543883916b8e0ff13606afeffa67c5b93d05b607bc87653ad18a91422 - languageName: node - linkType: hard - -"@babel/plugin-proposal-object-rest-spread@npm:^7.0.0": - version: 7.18.9 - resolution: "@babel/plugin-proposal-object-rest-spread@npm:7.18.9" - dependencies: - "@babel/compat-data": ^7.18.8 - "@babel/helper-compilation-targets": ^7.18.9 - "@babel/helper-plugin-utils": ^7.18.9 - "@babel/plugin-syntax-object-rest-spread": ^7.8.3 - "@babel/plugin-transform-parameters": ^7.18.8 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 66b9bae741d46edf1c96776d26dfe5d335981e57164ec2450583e3d20dfaa08a5137ffebb897e443913207789f9816bfec4ae845f38762c0196a60949eaffdba - languageName: node - linkType: hard - "@babel/plugin-proposal-private-property-in-object@npm:7.21.0-placeholder-for-preset-env.2": version: 7.21.0-placeholder-for-preset-env.2 resolution: "@babel/plugin-proposal-private-property-in-object@npm:7.21.0-placeholder-for-preset-env.2" @@ -2274,7 +2053,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-class-properties@npm:^7.0.0, @babel/plugin-syntax-class-properties@npm:^7.12.13, @babel/plugin-syntax-class-properties@npm:^7.8.3": +"@babel/plugin-syntax-class-properties@npm:^7.12.13, @babel/plugin-syntax-class-properties@npm:^7.8.3": version: 7.12.13 resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" dependencies: @@ -2318,7 +2097,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-flow@npm:^7.0.0, @babel/plugin-syntax-flow@npm:^7.23.3": +"@babel/plugin-syntax-flow@npm:^7.23.3": version: 7.23.3 resolution: "@babel/plugin-syntax-flow@npm:7.23.3" dependencies: @@ -2329,17 +2108,6 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-import-assertions@npm:7.20.0": - version: 7.20.0 - resolution: "@babel/plugin-syntax-import-assertions@npm:7.20.0" - dependencies: - "@babel/helper-plugin-utils": ^7.19.0 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 6a86220e0aae40164cd3ffaf80e7c076a1be02a8f3480455dddbae05fda8140f429290027604df7a11b3f3f124866e8a6d69dbfa1dda61ee7377b920ad144d5b - languageName: node - linkType: hard - "@babel/plugin-syntax-import-assertions@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-syntax-import-assertions@npm:7.22.5" @@ -2384,7 +2152,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:^7.0.0, @babel/plugin-syntax-jsx@npm:^7.22.5, @babel/plugin-syntax-jsx@npm:^7.23.3, @babel/plugin-syntax-jsx@npm:^7.7.2": +"@babel/plugin-syntax-jsx@npm:^7.22.5, @babel/plugin-syntax-jsx@npm:^7.23.3, @babel/plugin-syntax-jsx@npm:^7.7.2": version: 7.23.3 resolution: "@babel/plugin-syntax-jsx@npm:7.23.3" dependencies: @@ -2428,7 +2196,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-object-rest-spread@npm:^7.0.0, @babel/plugin-syntax-object-rest-spread@npm:^7.8.3": +"@babel/plugin-syntax-object-rest-spread@npm:^7.8.3": version: 7.8.3 resolution: "@babel/plugin-syntax-object-rest-spread@npm:7.8.3" dependencies: @@ -2506,7 +2274,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-arrow-functions@npm:^7.0.0, @babel/plugin-transform-arrow-functions@npm:^7.22.5": +"@babel/plugin-transform-arrow-functions@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-arrow-functions@npm:7.22.5" dependencies: @@ -2544,7 +2312,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-block-scoped-functions@npm:^7.0.0, @babel/plugin-transform-block-scoped-functions@npm:^7.22.5": +"@babel/plugin-transform-block-scoped-functions@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.22.5" dependencies: @@ -2555,7 +2323,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.0.0, @babel/plugin-transform-block-scoping@npm:^7.22.10": +"@babel/plugin-transform-block-scoping@npm:^7.22.10": version: 7.22.10 resolution: "@babel/plugin-transform-block-scoping@npm:7.22.10" dependencies: @@ -2591,7 +2359,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.0.0, @babel/plugin-transform-classes@npm:^7.22.6": +"@babel/plugin-transform-classes@npm:^7.22.6": version: 7.22.6 resolution: "@babel/plugin-transform-classes@npm:7.22.6" dependencies: @@ -2610,7 +2378,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-computed-properties@npm:^7.0.0, @babel/plugin-transform-computed-properties@npm:^7.22.5": +"@babel/plugin-transform-computed-properties@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-computed-properties@npm:7.22.5" dependencies: @@ -2622,7 +2390,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-destructuring@npm:^7.0.0, @babel/plugin-transform-destructuring@npm:^7.22.10": +"@babel/plugin-transform-destructuring@npm:^7.22.10": version: 7.22.10 resolution: "@babel/plugin-transform-destructuring@npm:7.22.10" dependencies: @@ -2692,7 +2460,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-flow-strip-types@npm:^7.0.0, @babel/plugin-transform-flow-strip-types@npm:^7.23.3": +"@babel/plugin-transform-flow-strip-types@npm:^7.23.3": version: 7.23.3 resolution: "@babel/plugin-transform-flow-strip-types@npm:7.23.3" dependencies: @@ -2704,7 +2472,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-for-of@npm:^7.0.0, @babel/plugin-transform-for-of@npm:^7.22.5": +"@babel/plugin-transform-for-of@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-for-of@npm:7.22.5" dependencies: @@ -2715,7 +2483,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-function-name@npm:^7.0.0, @babel/plugin-transform-function-name@npm:^7.22.5": +"@babel/plugin-transform-function-name@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-function-name@npm:7.22.5" dependencies: @@ -2740,7 +2508,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-literals@npm:^7.0.0, @babel/plugin-transform-literals@npm:^7.22.5": +"@babel/plugin-transform-literals@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-literals@npm:7.22.5" dependencies: @@ -2763,7 +2531,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-member-expression-literals@npm:^7.0.0, @babel/plugin-transform-member-expression-literals@npm:^7.22.5": +"@babel/plugin-transform-member-expression-literals@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-member-expression-literals@npm:7.22.5" dependencies: @@ -2786,7 +2554,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.0.0, @babel/plugin-transform-modules-commonjs@npm:^7.22.5, @babel/plugin-transform-modules-commonjs@npm:^7.23.0, @babel/plugin-transform-modules-commonjs@npm:^7.23.3": +"@babel/plugin-transform-modules-commonjs@npm:^7.22.5, @babel/plugin-transform-modules-commonjs@npm:^7.23.0, @babel/plugin-transform-modules-commonjs@npm:^7.23.3": version: 7.23.3 resolution: "@babel/plugin-transform-modules-commonjs@npm:7.23.3" dependencies: @@ -2887,7 +2655,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-object-super@npm:^7.0.0, @babel/plugin-transform-object-super@npm:^7.22.5": +"@babel/plugin-transform-object-super@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-object-super@npm:7.22.5" dependencies: @@ -2924,7 +2692,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-parameters@npm:^7.0.0, @babel/plugin-transform-parameters@npm:^7.18.8, @babel/plugin-transform-parameters@npm:^7.22.5": +"@babel/plugin-transform-parameters@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-parameters@npm:7.22.5" dependencies: @@ -2961,7 +2729,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-property-literals@npm:^7.0.0, @babel/plugin-transform-property-literals@npm:^7.22.5": +"@babel/plugin-transform-property-literals@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-property-literals@npm:7.22.5" dependencies: @@ -2983,7 +2751,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-react-display-name@npm:^7.0.0, @babel/plugin-transform-react-display-name@npm:^7.22.5": +"@babel/plugin-transform-react-display-name@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-react-display-name@npm:7.22.5" dependencies: @@ -3005,29 +2773,29 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-self@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-react-jsx-self@npm:7.22.5" +"@babel/plugin-transform-react-jsx-self@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-react-jsx-self@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 671eebfabd14a0c7d6ae805fff7e289dfdb7ba984bb100ea2ef6dad1d6a665ebbb09199ab2e64fca7bc78bd0fdc80ca897b07996cf215fafc32c67bc564309af + checksum: 882bf56bc932d015c2d83214133939ddcf342e5bcafa21f1a93b19f2e052145115e1e0351730897fd66e5f67cad7875b8a8d81ceb12b6e2a886ad0102cb4eb1f languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-source@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-react-jsx-source@npm:7.22.5" +"@babel/plugin-transform-react-jsx-source@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-react-jsx-source@npm:7.23.3" dependencies: "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 4ca2bd62ca14f8bbdcda9139f3f799e1c1c1bae504b67c1ca9bca142c53d81926d1a2b811f66a625f20999b2d352131053d886601f1ba3c1e9378c104d884277 + checksum: 92287fb797e522d99bdc77eaa573ce79ff0ad9f1cf4e7df374645e28e51dce0adad129f6f075430b129b5bac8dad843f65021970e12e992d6d6671f0d65bb1e0 languageName: node linkType: hard -"@babel/plugin-transform-react-jsx@npm:^7.0.0, @babel/plugin-transform-react-jsx@npm:^7.22.5": +"@babel/plugin-transform-react-jsx@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-react-jsx@npm:7.22.5" dependencies: @@ -3077,7 +2845,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-shorthand-properties@npm:^7.0.0, @babel/plugin-transform-shorthand-properties@npm:^7.22.5": +"@babel/plugin-transform-shorthand-properties@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-shorthand-properties@npm:7.22.5" dependencies: @@ -3088,7 +2856,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-spread@npm:^7.0.0, @babel/plugin-transform-spread@npm:^7.22.5": +"@babel/plugin-transform-spread@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-spread@npm:7.22.5" dependencies: @@ -3111,7 +2879,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-template-literals@npm:^7.0.0, @babel/plugin-transform-template-literals@npm:^7.22.5": +"@babel/plugin-transform-template-literals@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-template-literals@npm:7.22.5" dependencies: @@ -3373,16 +3141,16 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.20.6, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.23.2 - resolution: "@babel/runtime@npm:7.23.2" +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.20.6, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.4, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": + version: 7.23.5 + resolution: "@babel/runtime@npm:7.23.5" dependencies: regenerator-runtime: ^0.14.0 - checksum: 6c4df4839ec75ca10175f636d6362f91df8a3137f86b38f6cd3a4c90668a0fe8e9281d320958f4fbd43b394988958585a17c3aab2a4ea6bf7316b22916a371fb + checksum: 164d9802424f06908e62d29b8fd3a87db55accf82f46f964ac481dcead11ff7df8391e3696e5fa91a8ca10ea8845bf650acd730fa88cf13f8026cd8d5eec6936 languageName: node linkType: hard -"@babel/template@npm:^7.18.10, @babel/template@npm:^7.22.15, @babel/template@npm:^7.22.5, @babel/template@npm:^7.3.3": +"@babel/template@npm:^7.22.15, @babel/template@npm:^7.22.5, @babel/template@npm:^7.3.3": version: 7.22.15 resolution: "@babel/template@npm:7.22.15" dependencies: @@ -3393,7 +3161,7 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.3, @babel/traverse@npm:^7.4.5": +"@babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.23.3, @babel/traverse@npm:^7.4.5": version: 7.23.3 resolution: "@babel/traverse@npm:7.23.3" dependencies: @@ -3411,7 +3179,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.16.8, @babel/types@npm:^7.18.13, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.3, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.10, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.3, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": version: 7.23.3 resolution: "@babel/types@npm:7.23.3" dependencies: @@ -3514,13 +3282,13 @@ __metadata: "@backstage/integration": "workspace:^" "@backstage/integration-aws-node": "workspace:^" "@backstage/types": "workspace:^" - "@google-cloud/storage": ^6.0.0 + "@google-cloud/storage": ^7.0.0 "@keyv/memcache": ^1.3.5 "@keyv/redis": ^2.5.3 - "@kubernetes/client-node": 0.19.0 + "@kubernetes/client-node": 0.20.0 "@manypkg/get-packages": ^1.1.3 "@octokit/rest": ^19.0.3 - "@types/archiver": ^5.1.0 + "@types/archiver": ^6.0.0 "@types/base64-stream": ^1.0.2 "@types/compression": ^1.7.0 "@types/concat-stream": ^2.0.0 @@ -3535,7 +3303,7 @@ __metadata: "@types/tar": ^6.1.1 "@types/webpack-env": ^1.15.2 "@types/yauzl": ^2.10.0 - archiver: ^5.0.2 + archiver: ^6.0.0 aws-sdk-client-mock: ^3.0.0 base64-stream: ^1.0.0 better-sqlite3: ^9.0.0 @@ -3722,6 +3490,17 @@ __metadata: languageName: unknown linkType: soft +"@backstage/catalog-client@npm:^1.4.6": + version: 1.4.6 + resolution: "@backstage/catalog-client@npm:1.4.6" + dependencies: + "@backstage/catalog-model": ^1.4.3 + "@backstage/errors": ^1.2.3 + cross-fetch: ^4.0.0 + checksum: c62b479ea8865c23046f742d75db5fb36827627e78cfdff64e713eb72abd11fef071b8150c07e695e5e6d879d257a8a9dc85ec132b7c64229c6a0bd2ef821200 + languageName: node + linkType: hard + "@backstage/catalog-client@workspace:^, @backstage/catalog-client@workspace:packages/catalog-client": version: 0.0.0-use.local resolution: "@backstage/catalog-client@workspace:packages/catalog-client" @@ -3731,6 +3510,7 @@ __metadata: "@backstage/errors": "workspace:^" cross-fetch: ^4.0.0 msw: ^1.0.0 + uri-template: ^2.0.0 languageName: unknown linkType: soft @@ -3804,9 +3584,9 @@ __metadata: "@octokit/oauth-app": ^4.2.0 "@octokit/request": ^6.0.0 "@pmmmwh/react-refresh-webpack-plugin": ^0.5.7 - "@rollup/plugin-commonjs": ^23.0.0 - "@rollup/plugin-json": ^5.0.0 - "@rollup/plugin-node-resolve": ^13.0.6 + "@rollup/plugin-commonjs": ^25.0.0 + "@rollup/plugin-json": ^6.0.0 + "@rollup/plugin-node-resolve": ^15.0.0 "@rollup/plugin-yaml": ^4.0.0 "@spotify/eslint-config-base": ^14.0.0 "@spotify/eslint-config-react": ^14.0.0 @@ -3839,11 +3619,11 @@ __metadata: "@types/terser-webpack-plugin": ^5.0.4 "@types/webpack-env": ^1.15.2 "@types/yarnpkg__lockfile": ^1.1.4 - "@typescript-eslint/eslint-plugin": 6.10.0 + "@typescript-eslint/eslint-plugin": ^6.12.0 "@typescript-eslint/parser": ^6.7.2 "@yarnpkg/lockfile": ^1.1.0 "@yarnpkg/parsers": ^3.0.0-rc.4 - bfj: ^7.0.2 + bfj: ^8.0.0 buffer: ^6.0.3 chalk: ^4.0.0 chokidar: ^3.3.1 @@ -3865,6 +3645,7 @@ __metadata: eslint-plugin-jsx-a11y: ^6.5.1 eslint-plugin-react: ^7.28.0 eslint-plugin-react-hooks: ^4.3.0 + eslint-plugin-unused-imports: ^3.0.0 eslint-webpack-plugin: ^3.1.1 express: ^4.17.1 fork-ts-checker-webpack-plugin: ^7.0.0-alpha.8 @@ -3908,7 +3689,7 @@ __metadata: tar: ^6.1.12 terser-webpack-plugin: ^5.1.3 ts-node: ^10.0.0 - tsx: ^3.14.0 + tsx: ^4.0.0 util: ^0.12.3 webpack: ^5.70.0 webpack-dev-server: ^4.7.3 @@ -3921,7 +3702,7 @@ __metadata: "@vitejs/plugin-react": ^4.0.4 vite: ^4.4.9 vite-plugin-html: ^3.2.0 - vite-plugin-node-polyfills: ^0.16.0 + vite-plugin-node-polyfills: ^0.17.0 peerDependenciesMeta: "@vitejs/plugin-react": optional: true @@ -3983,7 +3764,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/config@^1.0.6, @backstage/config@^1.0.7, @backstage/config@workspace:^, @backstage/config@workspace:packages/config": +"@backstage/config@^1.0.6, @backstage/config@^1.0.7, @backstage/config@^1.1.1, @backstage/config@workspace:^, @backstage/config@workspace:packages/config": version: 0.0.0-use.local resolution: "@backstage/config@workspace:packages/config" dependencies: @@ -4040,85 +3821,17 @@ __metadata: "@backstage/core-app-api": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/frontend-plugin-api": "workspace:^" + "@backstage/frontend-test-utils": "workspace:^" + "@backstage/plugin-catalog": "workspace:^" "@backstage/plugin-puppetdb": "workspace:^" "@backstage/plugin-stackstorm": "workspace:^" + "@backstage/version-bridge": "workspace:^" "@oriflame/backstage-plugin-score-card": ^0.7.0 "@testing-library/jest-dom": ^6.0.0 - peerDependencies: - react: ^16.13.1 || ^17.0.0 || ^18.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - languageName: unknown - linkType: soft - -"@backstage/core-components@^0.13.7, @backstage/core-components@workspace:^, @backstage/core-components@workspace:packages/core-components": - version: 0.0.0-use.local - resolution: "@backstage/core-components@workspace:packages/core-components" - dependencies: - "@backstage/cli": "workspace:^" - "@backstage/config": "workspace:^" - "@backstage/core-app-api": "workspace:^" - "@backstage/core-plugin-api": "workspace:^" - "@backstage/errors": "workspace:^" - "@backstage/test-utils": "workspace:^" - "@backstage/theme": "workspace:^" - "@backstage/version-bridge": "workspace:^" - "@date-io/core": ^1.3.13 - "@material-table/core": ^3.1.0 - "@material-ui/core": ^4.12.2 - "@material-ui/icons": ^4.9.1 - "@material-ui/lab": 4.0.0-alpha.61 - "@react-hookz/web": ^20.0.0 - "@testing-library/dom": ^9.0.0 - "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^14.0.0 - "@testing-library/user-event": ^14.0.0 - "@types/ansi-regex": ^5.0.0 - "@types/classnames": ^2.2.9 - "@types/d3-selection": ^3.0.1 - "@types/d3-shape": ^3.0.1 - "@types/d3-zoom": ^3.0.1 - "@types/dagre": ^0.7.44 - "@types/google-protobuf": ^3.7.2 "@types/react": ^16.13.1 || ^17.0.0 - "@types/react-helmet": ^6.1.0 - "@types/react-sparklines": ^1.7.0 - "@types/react-syntax-highlighter": ^15.0.0 - "@types/react-text-truncate": ^0.14.0 - "@types/react-virtualized-auto-sizer": ^1.0.1 - "@types/react-window": ^1.8.5 - "@types/zen-observable": ^0.8.0 - ansi-regex: ^6.0.1 - classnames: ^2.2.6 - cross-fetch: ^4.0.0 - d3-selection: ^3.0.0 - d3-shape: ^3.0.0 - d3-zoom: ^3.0.0 - dagre: ^0.8.5 - history: ^5.0.0 - immer: ^9.0.1 - linkify-react: 4.1.2 - linkifyjs: 4.1.2 - lodash: ^4.17.21 - msw: ^1.0.0 - pluralize: ^8.0.0 - qs: ^6.9.4 - rc-progress: 3.5.1 - react-helmet: 6.1.0 - react-hook-form: ^7.12.2 - react-idle-timer: 5.6.2 - react-markdown: ^8.0.0 - react-sparklines: ^1.7.0 - react-syntax-highlighter: ^15.4.5 - react-text-truncate: ^0.19.0 - react-use: ^17.3.2 - react-virtualized-auto-sizer: ^1.0.11 - react-window: ^1.8.6 - remark-gfm: ^3.0.1 - zen-observable: ^0.10.0 - zod: ^3.21.4 peerDependencies: react: ^16.13.1 || ^17.0.0 || ^18.0.0 - react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4173,7 +3886,151 @@ __metadata: languageName: node linkType: hard -"@backstage/core-plugin-api@^1.3.0, @backstage/core-plugin-api@^1.5.0, @backstage/core-plugin-api@^1.7.0, @backstage/core-plugin-api@workspace:^, @backstage/core-plugin-api@workspace:packages/core-plugin-api": +"@backstage/core-components@npm:^0.13.8": + version: 0.13.8 + resolution: "@backstage/core-components@npm:0.13.8" + dependencies: + "@backstage/config": ^1.1.1 + "@backstage/core-plugin-api": ^1.8.0 + "@backstage/errors": ^1.2.3 + "@backstage/theme": ^0.4.4 + "@backstage/version-bridge": ^1.0.7 + "@date-io/core": ^1.3.13 + "@material-table/core": ^3.1.0 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.61 + "@react-hookz/web": ^20.0.0 + "@types/react": ^16.13.1 || ^17.0.0 + "@types/react-sparklines": ^1.7.0 + "@types/react-text-truncate": ^0.14.0 + ansi-regex: ^6.0.1 + classnames: ^2.2.6 + d3-selection: ^3.0.0 + d3-shape: ^3.0.0 + d3-zoom: ^3.0.0 + dagre: ^0.8.5 + history: ^5.0.0 + immer: ^9.0.1 + linkify-react: 4.1.2 + linkifyjs: 4.1.2 + lodash: ^4.17.21 + pluralize: ^8.0.0 + qs: ^6.9.4 + rc-progress: 3.5.1 + react-helmet: 6.1.0 + react-hook-form: ^7.12.2 + react-idle-timer: 5.6.2 + react-markdown: ^8.0.0 + react-sparklines: ^1.7.0 + react-syntax-highlighter: ^15.4.5 + react-text-truncate: ^0.19.0 + react-use: ^17.3.2 + react-virtualized-auto-sizer: ^1.0.11 + react-window: ^1.8.6 + remark-gfm: ^3.0.1 + zen-observable: ^0.10.0 + zod: ^3.21.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: 45bbf5af46837611c8c7fecde2afba49b2f958f9a8f047fe956b382a9a420a7e80c29f56ac2a5ecc8aa43e87c3b7a8446256d42aa642171f3439b5dd2a84bb0b + languageName: node + linkType: hard + +"@backstage/core-components@workspace:^, @backstage/core-components@workspace:packages/core-components": + version: 0.0.0-use.local + resolution: "@backstage/core-components@workspace:packages/core-components" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" + "@backstage/version-bridge": "workspace:^" + "@date-io/core": ^1.3.13 + "@material-table/core": ^3.1.0 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.61 + "@react-hookz/web": ^23.0.0 + "@testing-library/dom": ^9.0.0 + "@testing-library/jest-dom": ^6.0.0 + "@testing-library/react": ^14.0.0 + "@testing-library/user-event": ^14.0.0 + "@types/ansi-regex": ^5.0.0 + "@types/classnames": ^2.2.9 + "@types/d3-selection": ^3.0.1 + "@types/d3-shape": ^3.0.1 + "@types/d3-zoom": ^3.0.1 + "@types/dagre": ^0.7.44 + "@types/google-protobuf": ^3.7.2 + "@types/react": ^16.13.1 || ^17.0.0 + "@types/react-helmet": ^6.1.0 + "@types/react-sparklines": ^1.7.0 + "@types/react-syntax-highlighter": ^15.0.0 + "@types/react-text-truncate": ^0.14.0 + "@types/react-virtualized-auto-sizer": ^1.0.1 + "@types/react-window": ^1.8.5 + "@types/zen-observable": ^0.8.0 + ansi-regex: ^6.0.1 + classnames: ^2.2.6 + cross-fetch: ^4.0.0 + d3-selection: ^3.0.0 + d3-shape: ^3.0.0 + d3-zoom: ^3.0.0 + dagre: ^0.8.5 + history: ^5.0.0 + immer: ^9.0.1 + linkify-react: 4.1.3 + linkifyjs: 4.1.3 + lodash: ^4.17.21 + msw: ^1.0.0 + pluralize: ^8.0.0 + qs: ^6.9.4 + rc-progress: 3.5.1 + react-helmet: 6.1.0 + react-hook-form: ^7.12.2 + react-idle-timer: 5.6.2 + react-markdown: ^8.0.0 + react-sparklines: ^1.7.0 + react-syntax-highlighter: ^15.4.5 + react-text-truncate: ^0.19.0 + react-use: ^17.3.2 + react-virtualized-auto-sizer: ^1.0.11 + react-window: ^1.8.6 + remark-gfm: ^3.0.1 + zen-observable: ^0.10.0 + zod: ^3.21.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + languageName: unknown + linkType: soft + +"@backstage/core-plugin-api@npm:^1.3.0, @backstage/core-plugin-api@npm:^1.5.0, @backstage/core-plugin-api@npm:^1.8.0": + version: 1.8.0 + resolution: "@backstage/core-plugin-api@npm:1.8.0" + dependencies: + "@backstage/config": ^1.1.1 + "@backstage/types": ^1.1.1 + "@backstage/version-bridge": ^1.0.7 + "@types/react": ^16.13.1 || ^17.0.0 + history: ^5.0.0 + i18next: ^22.4.15 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: 1f78c4737c0e30682a3169d967943698cb95b3dccea1e60bd72e82dd14847192f5180db658b8d0b6811d6fb13830085ca3ecc6ea0be58771d0b517f877c97bbb + languageName: node + linkType: hard + +"@backstage/core-plugin-api@workspace:^, @backstage/core-plugin-api@workspace:packages/core-plugin-api": version: 0.0.0-use.local resolution: "@backstage/core-plugin-api@workspace:packages/core-plugin-api" dependencies: @@ -4271,7 +4128,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/errors@^1.1.5, @backstage/errors@workspace:^, @backstage/errors@workspace:packages/errors": +"@backstage/errors@^1.1.5, @backstage/errors@^1.2.3, @backstage/errors@workspace:^, @backstage/errors@workspace:packages/errors": version: 0.0.0-use.local resolution: "@backstage/errors@workspace:packages/errors" dependencies: @@ -4318,14 +4175,36 @@ __metadata: languageName: unknown linkType: soft +"@backstage/frontend-plugin-api@npm:^0.3.0": + version: 0.3.0 + resolution: "@backstage/frontend-plugin-api@npm:0.3.0" + dependencies: + "@backstage/core-components": ^0.13.8 + "@backstage/core-plugin-api": ^1.8.0 + "@backstage/types": ^1.1.1 + "@backstage/version-bridge": ^1.0.7 + "@material-ui/core": ^4.12.4 + "@types/react": ^16.13.1 || ^17.0.0 + lodash: ^4.17.21 + zod: ^3.21.4 + zod-to-json-schema: ^3.21.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: 195b0cd480839ff54a07aa37eb3bc644c321ecd6bce258159ba457f63dc79486b59c73180aaf6f7e824d0dbf8dfd9cb96fe8d5843d5e64467e44551f78419dc2 + languageName: node + linkType: hard + "@backstage/frontend-plugin-api@workspace:^, @backstage/frontend-plugin-api@workspace:packages/frontend-plugin-api": version: 0.0.0-use.local resolution: "@backstage/frontend-plugin-api@workspace:packages/frontend-plugin-api" dependencies: "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/frontend-app-api": "workspace:^" + "@backstage/frontend-test-utils": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" "@backstage/version-bridge": "workspace:^" @@ -4343,6 +4222,22 @@ __metadata: languageName: unknown linkType: soft +"@backstage/frontend-test-utils@workspace:^, @backstage/frontend-test-utils@workspace:packages/frontend-test-utils": + version: 0.0.0-use.local + resolution: "@backstage/frontend-test-utils@workspace:packages/frontend-test-utils" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/frontend-app-api": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/types": "workspace:^" + "@testing-library/jest-dom": ^6.0.0 + peerDependencies: + "@testing-library/react": ^12.1.3 || ^13.0.0 || ^14.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + languageName: unknown + linkType: soft + "@backstage/integration-aws-node@workspace:^, @backstage/integration-aws-node@workspace:packages/integration-aws-node": version: 0.0.0-use.local resolution: "@backstage/integration-aws-node@workspace:packages/integration-aws-node" @@ -4362,7 +4257,25 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration-react@^1.1.20, @backstage/integration-react@workspace:^, @backstage/integration-react@workspace:packages/integration-react": +"@backstage/integration-react@npm:^1.1.21": + version: 1.1.21 + resolution: "@backstage/integration-react@npm:1.1.21" + dependencies: + "@backstage/config": ^1.1.1 + "@backstage/core-plugin-api": ^1.8.0 + "@backstage/integration": ^1.7.2 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@types/react": ^16.13.1 || ^17.0.0 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: 5acbd36910954fd640eb586281436a579c08a5de8f1b226c86aab5028dcb3746190e740f5631d647e717f2c8aacde4a3efcd54fced7a75a8dcf5827c15213ab7 + languageName: node + linkType: hard + +"@backstage/integration-react@workspace:^, @backstage/integration-react@workspace:packages/integration-react": version: 0.0.0-use.local resolution: "@backstage/integration-react@workspace:packages/integration-react" dependencies: @@ -4386,11 +4299,27 @@ __metadata: languageName: unknown linkType: soft +"@backstage/integration@npm:^1.7.2": + version: 1.7.2 + resolution: "@backstage/integration@npm:1.7.2" + dependencies: + "@azure/identity": ^3.2.1 + "@backstage/config": ^1.1.1 + "@octokit/auth-app": ^4.0.0 + "@octokit/rest": ^19.0.3 + cross-fetch: ^4.0.0 + git-url-parse: ^13.0.0 + lodash: ^4.17.21 + luxon: ^3.0.0 + checksum: 6e9c63ea9da6d8769eb8cd05db01f91be70dc13d86a09c7be9835b1f57dac4fb64a3089be3b84b5329b9bacc887cda1dec3860bb04c9f58f78c458f96c942384 + languageName: node + linkType: hard + "@backstage/integration@workspace:^, @backstage/integration@workspace:packages/integration": version: 0.0.0-use.local resolution: "@backstage/integration@workspace:packages/integration" dependencies: - "@azure/identity": ^3.2.1 + "@azure/identity": ^4.0.0 "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/config-loader": "workspace:^" @@ -4696,7 +4625,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-api-docs@workspace:plugins/api-docs" dependencies: - "@asyncapi/react-component": 1.0.0-next.48 + "@asyncapi/react-component": 1.2.6 "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/core-app-api": "workspace:^" @@ -4718,8 +4647,9 @@ __metadata: "@types/react": ^16.13.1 || ^17.0.0 "@types/swagger-ui-react": ^4.18.0 cross-fetch: ^4.0.0 - graphiql: 3.0.9 + graphiql: 3.0.10 graphql: ^16.0.0 + graphql-config: ^5.0.2 graphql-ws: ^5.4.1 isomorphic-form-data: ^2.0.0 msw: ^1.0.0 @@ -4736,7 +4666,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-apollo-explorer@workspace:plugins/apollo-explorer" dependencies: - "@apollo/explorer": ^2.0.0 + "@apollo/explorer": ^3.0.0 "@backstage/cli": "workspace:^" "@backstage/core-app-api": "workspace:^" "@backstage/core-components": "workspace:^" @@ -4803,6 +4733,24 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-auth-backend-module-atlassian-provider@workspace:^, @backstage/plugin-auth-backend-module-atlassian-provider@workspace:plugins/auth-backend-module-atlassian-provider": + version: 0.0.0-use.local + resolution: "@backstage/plugin-auth-backend-module-atlassian-provider@workspace:plugins/auth-backend-module-atlassian-provider" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-defaults": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/plugin-auth-backend": "workspace:^" + "@backstage/plugin-auth-node": "workspace:^" + express: ^4.18.2 + passport: ^0.7.0 + passport-atlassian-oauth2: ^2.1.0 + supertest: ^6.3.3 + languageName: unknown + linkType: soft + "@backstage/plugin-auth-backend-module-gcp-iap-provider@workspace:^, @backstage/plugin-auth-backend-module-gcp-iap-provider@workspace:plugins/auth-backend-module-gcp-iap-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-gcp-iap-provider@workspace:plugins/auth-backend-module-gcp-iap-provider" @@ -4848,7 +4796,7 @@ __metadata: "@backstage/plugin-auth-backend": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" express: ^4.18.2 - passport: ^0.6.0 + passport: ^0.7.0 passport-gitlab2: ^5.0.0 supertest: ^6.3.3 languageName: unknown @@ -4888,7 +4836,7 @@ __metadata: jose: ^4.6.0 msw: ^1.0.0 node-fetch: ^2.6.7 - passport: ^0.6.0 + passport: ^0.7.0 passport-microsoft: ^1.0.0 supertest: ^6.3.3 languageName: unknown @@ -4906,12 +4854,44 @@ __metadata: "@backstage/plugin-auth-backend": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" express: ^4.18.2 - passport: ^0.6.0 + passport: ^0.7.0 passport-oauth2: ^1.6.1 supertest: ^6.3.3 languageName: unknown linkType: soft +"@backstage/plugin-auth-backend-module-oauth2-proxy-provider@workspace:^, @backstage/plugin-auth-backend-module-oauth2-proxy-provider@workspace:plugins/auth-backend-module-oauth2-proxy-provider": + version: 0.0.0-use.local + resolution: "@backstage/plugin-auth-backend-module-oauth2-proxy-provider@workspace:plugins/auth-backend-module-oauth2-proxy-provider" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/plugin-auth-node": "workspace:^" + jose: ^4.6.0 + languageName: unknown + linkType: soft + +"@backstage/plugin-auth-backend-module-okta-provider@workspace:^, @backstage/plugin-auth-backend-module-okta-provider@workspace:plugins/auth-backend-module-okta-provider": + version: 0.0.0-use.local + resolution: "@backstage/plugin-auth-backend-module-okta-provider@workspace:plugins/auth-backend-module-okta-provider" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-defaults": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/plugin-auth-backend": "workspace:^" + "@backstage/plugin-auth-node": "workspace:^" + "@davidzemon/passport-okta-oauth": ^0.0.5 + express: ^4.18.2 + passport: ^0.7.0 + supertest: ^6.3.3 + languageName: unknown + linkType: soft + "@backstage/plugin-auth-backend-module-pinniped-provider@workspace:plugins/auth-backend-module-pinniped-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-pinniped-provider@workspace:plugins/auth-backend-module-pinniped-provider" @@ -4932,7 +4912,29 @@ __metadata: luxon: ^3.4.3 msw: ^1.3.0 openid-client: ^5.4.3 - passport: ^0.6.0 + passport: ^0.7.0 + supertest: ^6.3.3 + languageName: unknown + linkType: soft + +"@backstage/plugin-auth-backend-module-vmware-cloud-provider@workspace:plugins/auth-backend-module-vmware-cloud-provider": + version: 0.0.0-use.local + resolution: "@backstage/plugin-auth-backend-module-vmware-cloud-provider@workspace:plugins/auth-backend-module-vmware-cloud-provider" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-defaults": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/plugin-auth-backend": "workspace:^" + "@backstage/plugin-auth-node": "workspace:^" + "@types/passport-oauth2": ^1.4.15 + jose: ^4.6.0 + msw: ^2.0.8 + passport-oauth2: ^1.6.1 supertest: ^6.3.3 languageName: unknown linkType: soft @@ -4950,16 +4952,18 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/plugin-auth-backend-module-atlassian-provider": "workspace:^" "@backstage/plugin-auth-backend-module-gcp-iap-provider": "workspace:^" "@backstage/plugin-auth-backend-module-github-provider": "workspace:^" "@backstage/plugin-auth-backend-module-gitlab-provider": "workspace:^" "@backstage/plugin-auth-backend-module-google-provider": "workspace:^" "@backstage/plugin-auth-backend-module-oauth2-provider": "workspace:^" + "@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "workspace:^" + "@backstage/plugin-auth-backend-module-okta-provider": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/types": "workspace:^" - "@davidzemon/passport-okta-oauth": ^0.0.5 - "@google-cloud/firestore": ^6.0.0 + "@google-cloud/firestore": ^7.0.0 "@types/body-parser": ^1.19.0 "@types/cookie-parser": ^1.4.2 "@types/express": ^4.17.6 @@ -4993,7 +4997,7 @@ __metadata: node-cache: ^5.1.2 node-fetch: ^2.6.7 openid-client: ^5.2.1 - passport: ^0.6.0 + passport: ^0.7.0 passport-auth0: ^1.4.3 passport-bitbucket-oauth2: ^0.1.2 passport-github2: ^0.1.12 @@ -5032,7 +5036,7 @@ __metadata: lodash: ^4.17.21 msw: ^1.0.0 node-fetch: ^2.6.7 - passport: ^0.6.0 + passport: ^0.7.0 supertest: ^6.1.3 uuid: ^8.0.0 winston: ^3.2.1 @@ -5047,14 +5051,19 @@ __metadata: dependencies: "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" + "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" + "@backstage/integration": "workspace:^" "@backstage/plugin-azure-devops-common": "workspace:^" + "@backstage/plugin-catalog-common": "workspace:^" + "@backstage/plugin-catalog-node": "workspace:^" "@types/express": ^4.17.6 "@types/supertest": ^2.0.8 azure-devops-node-api: ^11.0.1 express: ^4.17.1 express-promise-router: ^4.1.0 + lodash: ^4.17.21 mime-types: ^2.1.27 msw: ^1.0.0 p-limit: ^3.1.0 @@ -5110,9 +5119,9 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-azure-sites-backend@workspace:plugins/azure-sites-backend" dependencies: - "@azure/arm-appservice": ^13.0.1 + "@azure/arm-appservice": ^14.0.0 "@azure/arm-resourcegraph": ^4.2.1 - "@azure/identity": ^3.2.1 + "@azure/identity": ^4.0.0 "@backstage/backend-common": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" @@ -5254,7 +5263,6 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/errors": "workspace:^" - "@backstage/plugin-catalog": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" "@backstage/theme": "workspace:^" "@date-io/luxon": 1.x @@ -5497,7 +5505,7 @@ __metadata: "@backstage/config": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-kubernetes-common": "workspace:^" - "@google-cloud/container": ^4.15.0 + "@google-cloud/container": ^5.0.0 winston: ^3.2.1 languageName: unknown linkType: soft @@ -5650,7 +5658,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-msgraph@workspace:plugins/catalog-backend-module-msgraph" dependencies: - "@azure/identity": ^3.2.1 + "@azure/identity": ^4.0.0 "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-tasks": "workspace:^" @@ -5774,6 +5782,7 @@ __metadata: "@types/core-js": ^2.5.4 "@types/express": ^4.17.6 "@types/git-url-parse": ^9.0.0 + "@types/glob": ^8.0.0 "@types/lodash": ^4.14.151 "@types/supertest": ^2.0.8 "@types/uuid": ^8.0.0 @@ -5803,7 +5812,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-common@^1.0.10, @backstage/plugin-catalog-common@workspace:^, @backstage/plugin-catalog-common@workspace:plugins/catalog-common": +"@backstage/plugin-catalog-common@^1.0.10, @backstage/plugin-catalog-common@^1.0.18, @backstage/plugin-catalog-common@workspace:^, @backstage/plugin-catalog-common@workspace:plugins/catalog-common": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-common@workspace:plugins/catalog-common" dependencies: @@ -5850,37 +5859,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-graphql@workspace:^, @backstage/plugin-catalog-graphql@workspace:plugins/catalog-graphql": - version: 0.0.0-use.local - resolution: "@backstage/plugin-catalog-graphql@workspace:plugins/catalog-graphql" - dependencies: - "@apollo/client": ^3.0.0 - "@apollo/server": ^4.0.0 - "@backstage/catalog-model": "workspace:^" - "@backstage/cli": "workspace:^" - "@backstage/config": "workspace:^" - "@backstage/test-utils": "workspace:^" - "@backstage/types": "workspace:^" - "@graphql-codegen/cli": ^3.0.0 - "@graphql-codegen/graphql-modules-preset": ^3.0.0 - "@graphql-codegen/typescript": ^3.0.0 - "@graphql-codegen/typescript-resolvers": ^3.0.0 - "@graphql-tools/schema": ^9.0.0 - "@types/react": ^16.13.1 || ^17.0.0 - graphql: ^16.0.0 - graphql-modules: ^2.0.0 - graphql-tag: ^2.11.0 - graphql-type-json: ^0.3.2 - msw: ^1.0.0 - node-fetch: ^2.6.7 - winston: ^3.2.1 - peerDependencies: - react: ^16.13.1 || ^17.0.0 || ^18.0.0 - react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - languageName: unknown - linkType: soft - "@backstage/plugin-catalog-import@workspace:^, @backstage/plugin-catalog-import@workspace:plugins/catalog-import": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-import@workspace:plugins/catalog-import" @@ -5936,11 +5914,50 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" + "@backstage/plugin-permission-common": "workspace:^" + "@backstage/plugin-permission-node": "workspace:^" "@backstage/types": "workspace:^" languageName: unknown linkType: soft -"@backstage/plugin-catalog-react@^1.2.4, @backstage/plugin-catalog-react@^1.8.5, @backstage/plugin-catalog-react@workspace:^, @backstage/plugin-catalog-react@workspace:plugins/catalog-react": +"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.9.1": + version: 1.9.1 + resolution: "@backstage/plugin-catalog-react@npm:1.9.1" + dependencies: + "@backstage/catalog-client": ^1.4.6 + "@backstage/catalog-model": ^1.4.3 + "@backstage/core-components": ^0.13.8 + "@backstage/core-plugin-api": ^1.8.0 + "@backstage/errors": ^1.2.3 + "@backstage/frontend-plugin-api": ^0.3.0 + "@backstage/integration-react": ^1.1.21 + "@backstage/plugin-catalog-common": ^1.0.18 + "@backstage/plugin-permission-common": ^0.7.10 + "@backstage/plugin-permission-react": ^0.4.17 + "@backstage/theme": ^0.4.4 + "@backstage/types": ^1.1.1 + "@backstage/version-bridge": ^1.0.7 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.61 + "@react-hookz/web": ^23.0.0 + "@types/react": ^16.13.1 || ^17.0.0 + classnames: ^2.2.6 + lodash: ^4.17.21 + material-ui-popup-state: ^1.9.3 + qs: ^6.9.4 + react-use: ^17.2.4 + yaml: ^2.0.0 + zen-observable: ^0.10.0 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: aa57e828a161db545353d06460ec62f13fa6ca9e44d378e903a8ce9bbbc24fb22dfe9ab264f4e8150ef7543afe26ee887afe7a305670b79e0818b9d8d098550e + languageName: node + linkType: hard + +"@backstage/plugin-catalog-react@workspace:^, @backstage/plugin-catalog-react@workspace:plugins/catalog-react": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-react@workspace:plugins/catalog-react" dependencies: @@ -6110,7 +6127,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-circleci@workspace:^, @backstage/plugin-circleci@workspace:plugins/circleci": +"@backstage/plugin-circleci@workspace:plugins/circleci": version: 0.0.0-use.local resolution: "@backstage/plugin-circleci@workspace:plugins/circleci" dependencies: @@ -6599,7 +6616,7 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@react-hookz/web": ^20.0.0 + "@react-hookz/web": ^23.0.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^14.0.0 @@ -6961,7 +6978,7 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@react-hookz/web": ^20.0.0 + "@react-hookz/web": ^23.0.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^14.0.0 @@ -7249,31 +7266,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-graphql-backend@workspace:^, @backstage/plugin-graphql-backend@workspace:plugins/graphql-backend": - version: 0.0.0-use.local - resolution: "@backstage/plugin-graphql-backend@workspace:plugins/graphql-backend" - dependencies: - "@apollo/server": ^4.0.0 - "@backstage/backend-common": "workspace:^" - "@backstage/cli": "workspace:^" - "@backstage/config": "workspace:^" - "@backstage/plugin-catalog-graphql": "workspace:^" - "@graphql-tools/schema": ^9.0.0 - "@types/express": ^4.17.6 - "@types/supertest": ^2.0.8 - express: ^4.17.1 - express-promise-router: ^4.1.0 - graphql: ^16.0.0 - graphql-modules: ^2.0.0 - helmet: ^6.0.0 - msw: ^1.0.0 - reflect-metadata: ^0.1.13 - supertest: ^6.1.3 - winston: ^3.2.1 - yn: ^4.0.0 - languageName: unknown - linkType: soft - "@backstage/plugin-graphql-voyager@workspace:plugins/graphql-voyager": version: 0.0.0-use.local resolution: "@backstage/plugin-graphql-voyager@workspace:plugins/graphql-voyager" @@ -7303,7 +7295,25 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-home-react@^0.1.4, @backstage/plugin-home-react@workspace:^, @backstage/plugin-home-react@workspace:plugins/home-react": +"@backstage/plugin-home-react@npm:^0.1.5": + version: 0.1.5 + resolution: "@backstage/plugin-home-react@npm:0.1.5" + dependencies: + "@backstage/core-components": ^0.13.8 + "@backstage/core-plugin-api": ^1.8.0 + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@rjsf/utils": 5.13.6 + "@types/react": ^16.13.1 || ^17.0.0 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: 9ea922ec0ade7f12721552266a5e0513778a42594039a05819ca6ab7c253b84bd281c302c0a56e5c49f895dbba8ac404ab8521b8493b5908fe8af01cbbda31d6 + languageName: node + linkType: hard + +"@backstage/plugin-home-react@workspace:^, @backstage/plugin-home-react@workspace:plugins/home-react": version: 0.0.0-use.local resolution: "@backstage/plugin-home-react@workspace:plugins/home-react" dependencies: @@ -7315,7 +7325,7 @@ __metadata: "@backstage/test-utils": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 - "@rjsf/utils": 5.13.6 + "@rjsf/utils": 5.14.3 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^14.0.0 @@ -7340,6 +7350,7 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/core-app-api": "workspace:^" + "@backstage/core-compat-api": "workspace:^" "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" @@ -7352,10 +7363,10 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@rjsf/core": 5.13.6 - "@rjsf/material-ui": 5.13.6 - "@rjsf/utils": 5.13.6 - "@rjsf/validator-ajv8": 5.13.6 + "@rjsf/core": 5.14.3 + "@rjsf/material-ui": 5.14.3 + "@rjsf/utils": 5.14.3 + "@rjsf/validator-ajv8": 5.14.3 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^14.0.0 @@ -7545,10 +7556,10 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-kubernetes-backend@workspace:plugins/kubernetes-backend" dependencies: - "@aws-crypto/sha256-js": ^3.0.0 + "@aws-crypto/sha256-js": ^5.0.0 "@aws-sdk/credential-providers": ^3.350.0 "@aws-sdk/signature-v4": ^3.347.0 - "@azure/identity": ^3.2.1 + "@azure/identity": ^4.0.0 "@backstage/backend-app-api": "workspace:^" "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" @@ -7566,9 +7577,9 @@ __metadata: "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-node": "workspace:^" "@backstage/types": "workspace:^" - "@google-cloud/container": ^4.0.0 + "@google-cloud/container": ^5.0.0 "@jest-mock/express": ^2.0.1 - "@kubernetes/client-node": 0.19.0 + "@kubernetes/client-node": 0.20.0 "@types/aws4": ^1.5.1 "@types/express": ^4.17.6 "@types/http-proxy-middleware": ^0.19.3 @@ -7642,12 +7653,11 @@ __metadata: "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/core-app-api": "workspace:^" - "@backstage/core-plugin-api": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" - "@kubernetes/client-node": 0.19.0 + "@kubernetes/client-node": 0.20.0 kubernetes-models: ^4.3.1 lodash: ^4.17.21 luxon: ^3.0.0 @@ -7681,7 +7691,7 @@ __metadata: "@backstage/types": "workspace:^" "@kubernetes-models/apimachinery": ^1.1.0 "@kubernetes-models/base": ^4.0.1 - "@kubernetes/client-node": ^0.19.0 + "@kubernetes/client-node": ^0.20.0 "@material-ui/core": ^4.9.13 "@material-ui/icons": ^4.11.3 "@material-ui/lab": ^4.0.0-alpha.61 @@ -7724,7 +7734,7 @@ __metadata: "@backstage/types": "workspace:^" "@kubernetes-models/apimachinery": ^1.1.0 "@kubernetes-models/base": ^4.0.1 - "@kubernetes/client-node": 0.19.0 + "@kubernetes/client-node": 0.20.0 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 @@ -8294,7 +8304,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-permission-common@workspace:^, @backstage/plugin-permission-common@workspace:plugins/permission-common": +"@backstage/plugin-permission-common@^0.7.10, @backstage/plugin-permission-common@workspace:^, @backstage/plugin-permission-common@workspace:plugins/permission-common": version: 0.0.0-use.local resolution: "@backstage/plugin-permission-common@workspace:plugins/permission-common" dependencies: @@ -8332,6 +8342,25 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-permission-react@npm:^0.4.17": + version: 0.4.17 + resolution: "@backstage/plugin-permission-react@npm:0.4.17" + dependencies: + "@backstage/config": ^1.1.1 + "@backstage/core-plugin-api": ^1.8.0 + "@backstage/plugin-permission-common": ^0.7.10 + "@types/react": ^16.13.1 || ^17.0.0 + cross-fetch: ^4.0.0 + react-use: ^17.2.4 + swr: ^2.0.0 + peerDependencies: + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: 6baa30e83b68d27fc06411453100cc5fe98895021fe5a3db88c677e68430a8561744bc4581205e20f8326394e749b5e2ff19bb8037ecc86af6cae75124498111 + languageName: node + linkType: hard + "@backstage/plugin-permission-react@workspace:^, @backstage/plugin-permission-react@workspace:plugins/permission-react": version: 0.0.0-use.local resolution: "@backstage/plugin-permission-react@workspace:plugins/permission-react" @@ -8639,10 +8668,14 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder-backend-module-sentry@workspace:plugins/scaffolder-backend-module-sentry" dependencies: + "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/plugin-scaffolder-node": "workspace:^" + "@backstage/types": "workspace:^" + msw: ^2.0.0 + yaml: ^2.3.3 languageName: unknown linkType: soft @@ -8789,11 +8822,11 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@react-hookz/web": ^20.0.0 - "@rjsf/core": 5.13.6 - "@rjsf/material-ui": 5.13.6 - "@rjsf/utils": 5.13.6 - "@rjsf/validator-ajv8": 5.13.6 + "@react-hookz/web": ^23.0.0 + "@rjsf/core": 5.14.3 + "@rjsf/material-ui": 5.14.3 + "@rjsf/utils": 5.14.3 + "@rjsf/validator-ajv8": 5.14.3 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^14.0.0 @@ -8852,11 +8885,11 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@react-hookz/web": ^20.0.0 - "@rjsf/core": 5.13.6 - "@rjsf/material-ui": 5.13.6 - "@rjsf/utils": 5.13.6 - "@rjsf/validator-ajv8": 5.13.6 + "@react-hookz/web": ^23.0.0 + "@rjsf/core": 5.14.3 + "@rjsf/material-ui": 5.14.3 + "@rjsf/utils": 5.14.3 + "@rjsf/validator-ajv8": 5.14.3 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^14.0.0 @@ -9089,6 +9122,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/frontend-app-api": "workspace:^" "@backstage/frontend-plugin-api": "workspace:^" + "@backstage/frontend-test-utils": "workspace:^" "@backstage/plugin-search-common": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" @@ -9530,6 +9564,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/frontend-plugin-api": "workspace:^" + "@backstage/frontend-test-utils": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" "@material-ui/core": ^4.12.2 @@ -9565,6 +9600,7 @@ __metadata: "@backstage/dev-utils": "workspace:^" "@backstage/integration-react": "workspace:^" "@backstage/plugin-catalog": "workspace:^" + "@backstage/plugin-catalog-react": "workspace:^" "@backstage/plugin-search-react": "workspace:^" "@backstage/plugin-techdocs": "workspace:^" "@backstage/plugin-techdocs-react": "workspace:^" @@ -9575,13 +9611,13 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 - "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 testing-library__dom: ^7.29.4-beta.1 peerDependencies: + "@testing-library/react": ^12.1.3 || ^13.0.0 || ^14.0.0 react: ^16.13.1 || ^17.0.0 || ^18.0.0 react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 @@ -9641,7 +9677,7 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@react-hookz/web": ^20.0.0 + "@react-hookz/web": ^23.0.0 "@testing-library/dom": ^9.0.0 "@testing-library/jest-dom": ^6.0.0 "@testing-library/react": ^14.0.0 @@ -9666,7 +9702,7 @@ __metadata: "@aws-sdk/credential-providers": ^3.350.0 "@aws-sdk/lib-storage": ^3.350.0 "@aws-sdk/types": ^3.347.0 - "@azure/identity": ^3.2.1 + "@azure/identity": ^4.0.0 "@azure/storage-blob": ^12.5.0 "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" @@ -9678,7 +9714,7 @@ __metadata: "@backstage/integration": "workspace:^" "@backstage/integration-aws-node": "workspace:^" "@backstage/plugin-search-common": "workspace:^" - "@google-cloud/storage": ^6.0.0 + "@google-cloud/storage": ^7.0.0 "@smithy/node-http-handler": ^2.1.7 "@trendyol-js/openstack-swift-sdk": ^0.0.6 "@types/express": ^4.17.6 @@ -10018,6 +10054,7 @@ __metadata: dependencies: "@apidevtools/swagger-parser": ^10.1.0 "@apisyouwonthate/style-guide": ^1.4.0 + "@backstage/backend-common": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" @@ -10027,13 +10064,14 @@ __metadata: "@manypkg/get-packages": ^1.1.3 "@microsoft/api-documenter": ^7.22.33 "@microsoft/api-extractor": ^7.36.4 + "@openapitools/openapi-generator-cli": ^2.7.0 "@stoplight/spectral-core": ^1.18.0 "@stoplight/spectral-formatters": ^1.1.0 "@stoplight/spectral-functions": ^1.7.2 "@stoplight/spectral-parsers": ^1.0.2 "@stoplight/spectral-rulesets": ^1.18.0 "@stoplight/spectral-runtime": ^1.1.2 - "@stoplight/types": ^13.14.0 + "@stoplight/types": ^14.0.0 "@types/is-glob": ^4.0.2 "@types/mock-fs": ^4.13.0 "@types/node": ^18.17.8 @@ -10095,23 +10133,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/theme@^0.4.3, @backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": - version: 0.0.0-use.local - resolution: "@backstage/theme@workspace:packages/theme" - dependencies: - "@backstage/cli": "workspace:^" - "@emotion/react": ^11.10.5 - "@emotion/styled": ^11.10.5 - "@mui/material": ^5.12.2 - "@types/react": ^16.13.1 || ^17.0.0 - peerDependencies: - "@material-ui/core": ^4.12.2 - "@types/react": ^16.13.1 || ^17.0.0 - react: ^16.13.1 || ^17.0.0 || ^18.0.0 - react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 - languageName: unknown - linkType: soft - "@backstage/theme@npm:^0.2.16, @backstage/theme@npm:^0.2.18": version: 0.2.19 resolution: "@backstage/theme@npm:0.2.19" @@ -10124,7 +10145,43 @@ __metadata: languageName: node linkType: hard -"@backstage/types@^1.0.2, @backstage/types@workspace:^, @backstage/types@workspace:packages/types": +"@backstage/theme@npm:^0.4.4": + version: 0.4.4 + resolution: "@backstage/theme@npm:0.4.4" + dependencies: + "@emotion/react": ^11.10.5 + "@emotion/styled": ^11.10.5 + "@mui/material": ^5.12.2 + peerDependencies: + "@material-ui/core": ^4.12.2 + "@types/react": ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + checksum: 562ce0f0fd07202b44971b55bba9c39cd13c91a65873034d2e68fb5833c0d9882c2fd967d6c779a8563618ce035ec159823c865b0163911b7004f1bfce3ce4a1 + languageName: node + linkType: hard + +"@backstage/theme@workspace:^, @backstage/theme@workspace:packages/theme": + version: 0.0.0-use.local + resolution: "@backstage/theme@workspace:packages/theme" + dependencies: + "@backstage/cli": "workspace:^" + "@emotion/react": ^11.10.5 + "@emotion/styled": ^11.10.5 + "@mui/material": ^5.12.2 + "@mui/styles": ^5.14.18 + "@testing-library/jest-dom": ^6.0.0 + "@testing-library/react": ^14.0.0 + "@types/react": ^16.13.1 || ^17.0.0 + peerDependencies: + "@material-ui/core": ^4.12.2 + "@types/react": ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 + react-dom: ^16.13.1 || ^17.0.0 || ^18.0.0 + languageName: unknown + linkType: soft + +"@backstage/types@^1.0.2, @backstage/types@^1.1.1, @backstage/types@workspace:^, @backstage/types@workspace:packages/types": version: 0.0.0-use.local resolution: "@backstage/types@workspace:packages/types" dependencies: @@ -10135,7 +10192,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/version-bridge@^1.0.3, @backstage/version-bridge@workspace:^, @backstage/version-bridge@workspace:packages/version-bridge": +"@backstage/version-bridge@^1.0.3, @backstage/version-bridge@^1.0.7, @backstage/version-bridge@workspace:^, @backstage/version-bridge@workspace:packages/version-bridge": version: 0.0.0-use.local resolution: "@backstage/version-bridge@workspace:packages/version-bridge" dependencies: @@ -10171,15 +10228,42 @@ __metadata: languageName: node linkType: hard -"@changesets/apply-release-plan@npm:^6.1.4": - version: 6.1.4 - resolution: "@changesets/apply-release-plan@npm:6.1.4" +"@bundled-es-modules/cookie@npm:^2.0.0": + version: 2.0.0 + resolution: "@bundled-es-modules/cookie@npm:2.0.0" + dependencies: + cookie: ^0.5.0 + checksum: 53114eabbedda20ba6c63f45dcea35c568616d22adf5d1882cef9761f65ae636bf47e0c66325572cc8e3a335e0257caf5f76ff1287990d9e9265be7bc9767a87 + languageName: node + linkType: hard + +"@bundled-es-modules/js-levenshtein@npm:^2.0.1": + version: 2.0.1 + resolution: "@bundled-es-modules/js-levenshtein@npm:2.0.1" + dependencies: + js-levenshtein: ^1.1.6 + checksum: 13d0cbd2b00e563e09a797559dcff8c7e208c1f71e1787535a3d248f7e3d33ef3f0809b9f498d41788ab5fd399882dcca79917d70d97921b7dde94a282c1b7d8 + languageName: node + linkType: hard + +"@bundled-es-modules/statuses@npm:^1.0.1": + version: 1.0.1 + resolution: "@bundled-es-modules/statuses@npm:1.0.1" + dependencies: + statuses: ^2.0.1 + checksum: bcaa7de192e73056950b5fd20e75140d8d09074b1adc4437924b2051bb02b4dbf568c96e67d53b220fb7d735c3446e2ba746599cb1793ab2d23dd2ef230a8622 + languageName: node + linkType: hard + +"@changesets/apply-release-plan@npm:^7.0.0": + version: 7.0.0 + resolution: "@changesets/apply-release-plan@npm:7.0.0" dependencies: "@babel/runtime": ^7.20.1 - "@changesets/config": ^2.3.1 - "@changesets/get-version-range-type": ^0.3.2 - "@changesets/git": ^2.0.0 - "@changesets/types": ^5.2.1 + "@changesets/config": ^3.0.0 + "@changesets/get-version-range-type": ^0.4.0 + "@changesets/git": ^3.0.0 + "@changesets/types": ^6.0.0 "@manypkg/get-packages": ^1.1.3 detect-indent: ^6.0.0 fs-extra: ^7.0.1 @@ -10188,61 +10272,60 @@ __metadata: prettier: ^2.7.1 resolve-from: ^5.0.0 semver: ^7.5.3 - checksum: d386aee70c5483c97d964c6fa1191878005b7050d34b2e1e4a1ad66d9ad44f8f20d1c884e01e770b954bd2d4364f935510e53ae896212669f67e5c37b2a610c7 + checksum: ad83f89a3d46cd5249fa960cb0324114532bd5f25e74466d181afd6661273824859d038a12ba587a5e044f9169810e4a6febbb61e23c3819b3b28c00176a8bdf languageName: node linkType: hard -"@changesets/assemble-release-plan@npm:^5.2.4": - version: 5.2.4 - resolution: "@changesets/assemble-release-plan@npm:5.2.4" +"@changesets/assemble-release-plan@npm:^6.0.0": + version: 6.0.0 + resolution: "@changesets/assemble-release-plan@npm:6.0.0" dependencies: "@babel/runtime": ^7.20.1 - "@changesets/errors": ^0.1.4 - "@changesets/get-dependents-graph": ^1.3.6 - "@changesets/types": ^5.2.1 + "@changesets/errors": ^0.2.0 + "@changesets/get-dependents-graph": ^2.0.0 + "@changesets/types": ^6.0.0 "@manypkg/get-packages": ^1.1.3 semver: ^7.5.3 - checksum: 32f443a0afec3d5a4afc68c8de32e8ff88531ea24976b50583b1d6870d71cec2729f27952af82854eb54e2ad0a619872d211d654c596ee0eb42c83ab54ad15ae + checksum: 0e6d25f25e0e3cc0e92aa8c43f5f496bae9464e2523be4ff81e31b6c9971b63bb1264821a2483c48d451d89d60af1acebe727e7f8c392ed48188a3ff26d0950e languageName: node linkType: hard -"@changesets/changelog-git@npm:^0.1.14": - version: 0.1.14 - resolution: "@changesets/changelog-git@npm:0.1.14" +"@changesets/changelog-git@npm:^0.2.0": + version: 0.2.0 + resolution: "@changesets/changelog-git@npm:0.2.0" dependencies: - "@changesets/types": ^5.2.1 - checksum: 60b45bb899e66cec669ab3884d5d18550cd30bf5a8b06f335eb72aa6c9e018dd3e0187e4df61c91a22076153e346b735b792f0e9c6186e6245b1b7aec2fc42d4 + "@changesets/types": ^6.0.0 + checksum: 132660f7fdabbdda00ac803cc822d6427a1a38a17a5f414e87ad32f6dc4cbef5280a147ecdc087a28dc06c8bd0762f8d6e7132d01b8a4142b59fbe1bc2177034 languageName: node linkType: hard "@changesets/cli@npm:^2.14.0": - version: 2.26.2 - resolution: "@changesets/cli@npm:2.26.2" + version: 2.27.1 + resolution: "@changesets/cli@npm:2.27.1" dependencies: "@babel/runtime": ^7.20.1 - "@changesets/apply-release-plan": ^6.1.4 - "@changesets/assemble-release-plan": ^5.2.4 - "@changesets/changelog-git": ^0.1.14 - "@changesets/config": ^2.3.1 - "@changesets/errors": ^0.1.4 - "@changesets/get-dependents-graph": ^1.3.6 - "@changesets/get-release-plan": ^3.0.17 - "@changesets/git": ^2.0.0 - "@changesets/logger": ^0.0.5 - "@changesets/pre": ^1.0.14 - "@changesets/read": ^0.5.9 - "@changesets/types": ^5.2.1 - "@changesets/write": ^0.2.3 + "@changesets/apply-release-plan": ^7.0.0 + "@changesets/assemble-release-plan": ^6.0.0 + "@changesets/changelog-git": ^0.2.0 + "@changesets/config": ^3.0.0 + "@changesets/errors": ^0.2.0 + "@changesets/get-dependents-graph": ^2.0.0 + "@changesets/get-release-plan": ^4.0.0 + "@changesets/git": ^3.0.0 + "@changesets/logger": ^0.1.0 + "@changesets/pre": ^2.0.0 + "@changesets/read": ^0.6.0 + "@changesets/types": ^6.0.0 + "@changesets/write": ^0.3.0 "@manypkg/get-packages": ^1.1.3 - "@types/is-ci": ^3.0.0 "@types/semver": ^7.5.0 ansi-colors: ^4.1.3 chalk: ^2.1.0 + ci-info: ^3.7.0 enquirer: ^2.3.0 external-editor: ^3.1.0 fs-extra: ^7.0.1 human-id: ^1.0.2 - is-ci: ^3.0.1 meow: ^6.0.0 outdent: ^0.5.0 p-limit: ^2.2.0 @@ -10254,129 +10337,129 @@ __metadata: tty-table: ^4.1.5 bin: changeset: bin.js - checksum: fc7b5bf319b19abed7a8d33a9fbd9ce49108af61c9c51920f609a49cb0c557f0b998711250d0cac149d0bed8a522f3109c4d8b0dda65b96ff2f823d16ca2f972 + checksum: 0d030dec7e0ef28626082a257d57f46cdf65edb65a95f5a3511a9d298ca052388d8ab7f9a714943864eddc59148c4afb0b802a9c75b5bea45aade4c0dc7a5fa6 languageName: node linkType: hard -"@changesets/config@npm:^2.3.1": - version: 2.3.1 - resolution: "@changesets/config@npm:2.3.1" +"@changesets/config@npm:^3.0.0": + version: 3.0.0 + resolution: "@changesets/config@npm:3.0.0" dependencies: - "@changesets/errors": ^0.1.4 - "@changesets/get-dependents-graph": ^1.3.6 - "@changesets/logger": ^0.0.5 - "@changesets/types": ^5.2.1 + "@changesets/errors": ^0.2.0 + "@changesets/get-dependents-graph": ^2.0.0 + "@changesets/logger": ^0.1.0 + "@changesets/types": ^6.0.0 "@manypkg/get-packages": ^1.1.3 fs-extra: ^7.0.1 micromatch: ^4.0.2 - checksum: 8af58e3add4751ac8ce2c01f026ac8843b8d1c07c9a3df6518496eaef67f56458a84cad310763c588f7eccbf6831afbf280df7e05e78b294027b6b847be3d0cc + checksum: 31a8c37e38768cf3676d24b7d371009dd1d691f221ecf086b79f0d96dc8e95aa408cda3659eb867a14615ea38a1c2be448bf0655c7570539af57c930ca784051 languageName: node linkType: hard -"@changesets/errors@npm:^0.1.4": - version: 0.1.4 - resolution: "@changesets/errors@npm:0.1.4" +"@changesets/errors@npm:^0.2.0": + version: 0.2.0 + resolution: "@changesets/errors@npm:0.2.0" dependencies: extendable-error: ^0.1.5 - checksum: 10734f1379715bf5a70b566dd42b50a75964d76f382bb67332776614454deda6d04a43dd7e727cd7cba56d7f2f7c95a07c7c0a19dd5d64fb1980b28322840733 + checksum: 4b79373f92287af4f723e8dbbccaf0299aa8735fc043243d0ad587f04a7614615ea50180be575d4438b9f00aa82d1cf85e902b77a55bdd3e0a8dd97e77b18c60 languageName: node linkType: hard -"@changesets/get-dependents-graph@npm:^1.3.6": - version: 1.3.6 - resolution: "@changesets/get-dependents-graph@npm:1.3.6" +"@changesets/get-dependents-graph@npm:^2.0.0": + version: 2.0.0 + resolution: "@changesets/get-dependents-graph@npm:2.0.0" dependencies: - "@changesets/types": ^5.2.1 + "@changesets/types": ^6.0.0 "@manypkg/get-packages": ^1.1.3 chalk: ^2.1.0 fs-extra: ^7.0.1 semver: ^7.5.3 - checksum: d2cbbc5041063b939899502d1b264a0d9edb655acefd7f6197883229156bb7cfd1ace642ae4a1f7f7b432f2c51429f5dc9851ff5a9ed47f1c0159916e66627a9 + checksum: 6690d3ed36e8a636bc2a985d209bd72ee1100601ccf00850ca1fbe8500af839a3f4e5bd2167858cf11383aa76360f853e481533157060ad882fb56319db3090a languageName: node linkType: hard -"@changesets/get-release-plan@npm:^3.0.17": - version: 3.0.17 - resolution: "@changesets/get-release-plan@npm:3.0.17" +"@changesets/get-release-plan@npm:^4.0.0": + version: 4.0.0 + resolution: "@changesets/get-release-plan@npm:4.0.0" dependencies: "@babel/runtime": ^7.20.1 - "@changesets/assemble-release-plan": ^5.2.4 - "@changesets/config": ^2.3.1 - "@changesets/pre": ^1.0.14 - "@changesets/read": ^0.5.9 - "@changesets/types": ^5.2.1 + "@changesets/assemble-release-plan": ^6.0.0 + "@changesets/config": ^3.0.0 + "@changesets/pre": ^2.0.0 + "@changesets/read": ^0.6.0 + "@changesets/types": ^6.0.0 "@manypkg/get-packages": ^1.1.3 - checksum: 8a0e3794d0f1e6220d173dbec96352ad69b585d013c3183888ca598dfdfcaa8a5ac3f7f36d5c511575cdc3559c2ad6f8cecfaa16ba9c24380899a81daa7af924 + checksum: 57672c1e94f95de8ac65aac969275e0cb225f02aa86b2cef69329fff6e36ba5fde04eadeb6af36f4d8ac41a8fd329028b4df4c23c15c10fd13e026c77463d576 languageName: node linkType: hard -"@changesets/get-version-range-type@npm:^0.3.2": - version: 0.3.2 - resolution: "@changesets/get-version-range-type@npm:0.3.2" - checksum: b7ee7127c472a3886906ca6db336ac11233a5e75abc882084bfb4794e79a8936e3faceec3c04bf61c26453cd7f74278d9bf22aea4cdca8c1cd992591925b3c9b +"@changesets/get-version-range-type@npm:^0.4.0": + version: 0.4.0 + resolution: "@changesets/get-version-range-type@npm:0.4.0" + checksum: 2e8c511e658e193f48de7f09522649c4cf072932f0cbe0f252a7f2703d7775b0b90b632254526338795d0658e340be9dff3879cfc8eba4534b8cd6071efff8c9 languageName: node linkType: hard -"@changesets/git@npm:^2.0.0": - version: 2.0.0 - resolution: "@changesets/git@npm:2.0.0" +"@changesets/git@npm:^3.0.0": + version: 3.0.0 + resolution: "@changesets/git@npm:3.0.0" dependencies: "@babel/runtime": ^7.20.1 - "@changesets/errors": ^0.1.4 - "@changesets/types": ^5.2.1 + "@changesets/errors": ^0.2.0 + "@changesets/types": ^6.0.0 "@manypkg/get-packages": ^1.1.3 is-subdir: ^1.1.1 micromatch: ^4.0.2 spawndamnit: ^2.0.0 - checksum: 3820b7b689bbe8dfb93222c766bee214e68a45f07b2b5c8056891f9ffe6f1e369c0f84388246a9eea5317b496ae80ffd1508319190f79c359f060ebf8ccb7b13 + checksum: a8fa66d77302b50d5e604aca898ee813247537d23a05004637ecee4aa1579d6a2859283c099bdcf3e2b232258c93ff81dd57aa867858788e457df40118c64c2b languageName: node linkType: hard -"@changesets/logger@npm:^0.0.5": - version: 0.0.5 - resolution: "@changesets/logger@npm:0.0.5" +"@changesets/logger@npm:^0.1.0": + version: 0.1.0 + resolution: "@changesets/logger@npm:0.1.0" dependencies: chalk: ^2.1.0 - checksum: bfec3cd9122b00c0ec25e96730f771ffd662ef3906d571bad1e4e9993f9d54d357d3eaf074b3dfaa4e23af759ce68efa2a97d8b845b0d8c951df5d21c6dfdff5 + checksum: d8ef1b7caf3d2c15a9e7743b7a9462e0c2e61c76d9a5bbed5eff805afa8226117505309c6e9095001136b4f6d9ae0aba61377e53af8aa0809f1febd1b5f787f1 languageName: node linkType: hard -"@changesets/parse@npm:^0.3.16": - version: 0.3.16 - resolution: "@changesets/parse@npm:0.3.16" +"@changesets/parse@npm:^0.4.0": + version: 0.4.0 + resolution: "@changesets/parse@npm:0.4.0" dependencies: - "@changesets/types": ^5.2.1 + "@changesets/types": ^6.0.0 js-yaml: ^3.13.1 - checksum: 475f808ac8d33ec90af3914d55af1da8eeb9336d6cab7dd9e5be74af844f0ec04f4a67d5237a1d3284a468e0c9198e2be01d0e5870a1b28e63bc240f5f1ffea9 + checksum: 3dd970b244479746233ebd357cfff3816cf9f344ebf2cf0c7c55ce8579adfd3f506978e86ad61222dc3acf1548a2105ffdd8b3e940b3f82b225741315cee2bf0 languageName: node linkType: hard -"@changesets/pre@npm:^1.0.14": - version: 1.0.14 - resolution: "@changesets/pre@npm:1.0.14" +"@changesets/pre@npm:^2.0.0": + version: 2.0.0 + resolution: "@changesets/pre@npm:2.0.0" dependencies: "@babel/runtime": ^7.20.1 - "@changesets/errors": ^0.1.4 - "@changesets/types": ^5.2.1 + "@changesets/errors": ^0.2.0 + "@changesets/types": ^6.0.0 "@manypkg/get-packages": ^1.1.3 fs-extra: ^7.0.1 - checksum: 6b849bd6f916476a5b5664bc4286020bee506985c82f723a757fa4e681b0b7129db81751f16072ac55a980ffd83a4b234d6b8d0f8b6bc889aa0c0fd5377431e8 + checksum: 6a01086405f4e4ce63abb8f222de39b69a5762c9c8c8f19c0d3c72f7798248d7a152937028f1be24be1f8a4a5e47e4cb23c54bc36f979539b24a728c893caf4e languageName: node linkType: hard -"@changesets/read@npm:^0.5.9": - version: 0.5.9 - resolution: "@changesets/read@npm:0.5.9" +"@changesets/read@npm:^0.6.0": + version: 0.6.0 + resolution: "@changesets/read@npm:0.6.0" dependencies: "@babel/runtime": ^7.20.1 - "@changesets/git": ^2.0.0 - "@changesets/logger": ^0.0.5 - "@changesets/parse": ^0.3.16 - "@changesets/types": ^5.2.1 + "@changesets/git": ^3.0.0 + "@changesets/logger": ^0.1.0 + "@changesets/parse": ^0.4.0 + "@changesets/types": ^6.0.0 chalk: ^2.1.0 fs-extra: ^7.0.1 p-filter: ^2.1.0 - checksum: 0875a80829186de2da55bc0347601cc31b269d54fb6967a5093abacbbd9f949e352907b8340b61348a304228fdade670ded151327f16eea3424b5b4b2bb9888c + checksum: 3da6428124b4983f6ccbdae324c73044cd6a84269bfdbaff545331042e3d6845c647613b5d8f4ffdd48bad5b791623eca2be1b507652ea47b77e136cd2e26c70 languageName: node linkType: hard @@ -10387,23 +10470,49 @@ __metadata: languageName: node linkType: hard -"@changesets/types@npm:^5.2.1": - version: 5.2.1 - resolution: "@changesets/types@npm:5.2.1" - checksum: 527dc1aa41b040fe35bcd55f7d07bec710320b179b000c429723e25b87aac18be487daf5047d4fecf2781aad78f73abff111e76e411b652f7a2e812a464c69f2 +"@changesets/types@npm:^6.0.0": + version: 6.0.0 + resolution: "@changesets/types@npm:6.0.0" + checksum: d528b5d712f62c26ea422c7d34ccf6eac57a353c0733d96716db3c796ecd9bba5d496d48b37d5d46b784dc45b69c06ce3345fa3515df981bb68456cad68e6465 languageName: node linkType: hard -"@changesets/write@npm:^0.2.3": - version: 0.2.3 - resolution: "@changesets/write@npm:0.2.3" +"@changesets/write@npm:^0.3.0": + version: 0.3.0 + resolution: "@changesets/write@npm:0.3.0" dependencies: "@babel/runtime": ^7.20.1 - "@changesets/types": ^5.2.1 + "@changesets/types": ^6.0.0 fs-extra: ^7.0.1 human-id: ^1.0.2 prettier: ^2.7.1 - checksum: 40ad8069f9adc565b78a5f25992e31b41a12e551d94c29e1b4def49ce98871a1e358feda6536be8b363a6dba18b1226a22ecfc60fdd7bc1e74bfcf46b07f91be + checksum: 37588eb3ef2af15b3ea09d46864c994780619d20b791ea5b654801a035a3a12540c7f953e6e4f36731678615edc6d1c32f8fe174d599d3e6ce2d68263865788b + languageName: node + linkType: hard + +"@circleci/backstage-plugin@npm:^0.1.1": + version: 0.1.1 + resolution: "@circleci/backstage-plugin@npm:0.1.1" + dependencies: + "@backstage/catalog-model": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/plugin-catalog-react": "workspace:^" + "@backstage/theme": "workspace:^" + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.61 + "@types/react": ^16.13.1 || ^17.0.0 + circleci-api: ^4.0.0 + humanize-duration: ^3.27.0 + lodash: ^4.17.21 + luxon: ^3.0.0 + react-use: ^17.2.4 + peerDependencies: + react: ^16.13.1 || ^17.0.0 + react-dom: ^16.13.1 || ^17.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + checksum: ded80e2eef1cec3f83f76e62b1362499c1662ae6307bdc829b78aed02101af6fd85134d94716fbbb60e8a0d5b3d2a4653df81fbdfcab576a47f7b59a332e580f languageName: node linkType: hard @@ -10437,8 +10546,8 @@ __metadata: linkType: hard "@codemirror/language@npm:^6.0.0": - version: 6.9.2 - resolution: "@codemirror/language@npm:6.9.2" + version: 6.9.3 + resolution: "@codemirror/language@npm:6.9.3" dependencies: "@codemirror/state": ^6.0.0 "@codemirror/view": ^6.0.0 @@ -10446,7 +10555,7 @@ __metadata: "@lezer/highlight": ^1.0.0 "@lezer/lr": ^1.0.0 style-mod: ^4.0.0 - checksum: eee7b861b5591114cac7502cd532d5b923639740081a4cd7e28696c252af8d759b14686aaf6d5eee7e0969ff647b7aaf03a5eea7235fb6d9858ee19433f1c74d + checksum: 774a40bc91c748d418a9a774161a5b083061124e4439bb753072bc657ec4c4784f595161c10c7c3935154b22291bf6dc74c9abe827033db32e217ac3963478f3 languageName: node linkType: hard @@ -10501,13 +10610,13 @@ __metadata: linkType: hard "@codemirror/view@npm:^6.0.0": - version: 6.22.0 - resolution: "@codemirror/view@npm:6.22.0" + version: 6.22.1 + resolution: "@codemirror/view@npm:6.22.1" dependencies: "@codemirror/state": ^6.1.4 style-mod: ^4.1.0 w3c-keyname: ^2.2.4 - checksum: 2a24674687fbde06898d0a131abe5f86a812d79e111cf8dc94110dac86eed8c20a2094b547c1b3c379fe8edf0c66318d03a7594158e4f6628ee060a03a5d1bab + checksum: 8643d86cf8c34433a410b28b1339c9a333c519e815890bf6494ca35a47d6ed38b51a13480cf4f6bea319ab2a17991e1ba47cd1b4a2c5a99fb76bad014682925a languageName: node linkType: hard @@ -10806,9 +10915,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/android-arm64@npm:0.19.5" +"@esbuild/android-arm64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/android-arm64@npm:0.19.8" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -10827,9 +10936,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/android-arm@npm:0.19.5" +"@esbuild/android-arm@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/android-arm@npm:0.19.8" conditions: os=android & cpu=arm languageName: node linkType: hard @@ -10848,9 +10957,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-x64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/android-x64@npm:0.19.5" +"@esbuild/android-x64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/android-x64@npm:0.19.8" conditions: os=android & cpu=x64 languageName: node linkType: hard @@ -10869,9 +10978,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/darwin-arm64@npm:0.19.5" +"@esbuild/darwin-arm64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/darwin-arm64@npm:0.19.8" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -10890,9 +10999,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/darwin-x64@npm:0.19.5" +"@esbuild/darwin-x64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/darwin-x64@npm:0.19.8" conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -10911,9 +11020,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/freebsd-arm64@npm:0.19.5" +"@esbuild/freebsd-arm64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/freebsd-arm64@npm:0.19.8" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard @@ -10932,9 +11041,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/freebsd-x64@npm:0.19.5" +"@esbuild/freebsd-x64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/freebsd-x64@npm:0.19.8" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard @@ -10953,9 +11062,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/linux-arm64@npm:0.19.5" +"@esbuild/linux-arm64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/linux-arm64@npm:0.19.8" conditions: os=linux & cpu=arm64 languageName: node linkType: hard @@ -10974,9 +11083,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/linux-arm@npm:0.19.5" +"@esbuild/linux-arm@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/linux-arm@npm:0.19.8" conditions: os=linux & cpu=arm languageName: node linkType: hard @@ -10995,9 +11104,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/linux-ia32@npm:0.19.5" +"@esbuild/linux-ia32@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/linux-ia32@npm:0.19.8" conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -11016,9 +11125,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/linux-loong64@npm:0.19.5" +"@esbuild/linux-loong64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/linux-loong64@npm:0.19.8" conditions: os=linux & cpu=loong64 languageName: node linkType: hard @@ -11037,9 +11146,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/linux-mips64el@npm:0.19.5" +"@esbuild/linux-mips64el@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/linux-mips64el@npm:0.19.8" conditions: os=linux & cpu=mips64el languageName: node linkType: hard @@ -11058,9 +11167,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/linux-ppc64@npm:0.19.5" +"@esbuild/linux-ppc64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/linux-ppc64@npm:0.19.8" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard @@ -11079,9 +11188,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/linux-riscv64@npm:0.19.5" +"@esbuild/linux-riscv64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/linux-riscv64@npm:0.19.8" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard @@ -11100,9 +11209,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/linux-s390x@npm:0.19.5" +"@esbuild/linux-s390x@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/linux-s390x@npm:0.19.8" conditions: os=linux & cpu=s390x languageName: node linkType: hard @@ -11121,9 +11230,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/linux-x64@npm:0.19.5" +"@esbuild/linux-x64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/linux-x64@npm:0.19.8" conditions: os=linux & cpu=x64 languageName: node linkType: hard @@ -11142,9 +11251,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/netbsd-x64@npm:0.19.5" +"@esbuild/netbsd-x64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/netbsd-x64@npm:0.19.8" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard @@ -11163,9 +11272,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/openbsd-x64@npm:0.19.5" +"@esbuild/openbsd-x64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/openbsd-x64@npm:0.19.8" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard @@ -11184,9 +11293,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/sunos-x64@npm:0.19.5" +"@esbuild/sunos-x64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/sunos-x64@npm:0.19.8" conditions: os=sunos & cpu=x64 languageName: node linkType: hard @@ -11205,9 +11314,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/win32-arm64@npm:0.19.5" +"@esbuild/win32-arm64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/win32-arm64@npm:0.19.8" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -11226,9 +11335,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/win32-ia32@npm:0.19.5" +"@esbuild/win32-ia32@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/win32-ia32@npm:0.19.8" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -11247,9 +11356,9 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.19.5": - version: 0.19.5 - resolution: "@esbuild/win32-x64@npm:0.19.5" +"@esbuild/win32-x64@npm:0.19.8": + version: 0.19.8 + resolution: "@esbuild/win32-x64@npm:0.19.8" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -11272,9 +11381,9 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.1.3": - version: 2.1.3 - resolution: "@eslint/eslintrc@npm:2.1.3" +"@eslint/eslintrc@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/eslintrc@npm:2.1.4" dependencies: ajv: ^6.12.4 debug: ^4.3.2 @@ -11285,14 +11394,14 @@ __metadata: js-yaml: ^4.1.0 minimatch: ^3.1.2 strip-json-comments: ^3.1.1 - checksum: 5c6c3878192fe0ddffa9aff08b4e2f3bcc8f1c10d6449b7295a5f58b662019896deabfc19890455ffd7e60a5bd28d25d0eaefb2f78b2d230aae3879af92b89e5 + checksum: 10957c7592b20ca0089262d8c2a8accbad14b4f6507e35416c32ee6b4dbf9cad67dfb77096bbd405405e9ada2b107f3797fe94362e1c55e0b09d6e90dd149127 languageName: node linkType: hard -"@eslint/js@npm:8.53.0": - version: 8.53.0 - resolution: "@eslint/js@npm:8.53.0" - checksum: e0d5cfb0000aaee237c8e6d6d6e366faa60b1ef7f928ce17778373aa44d3b886368f6d5e1f97f913f0f16801aad016db8b8df78418c9d18825c15590328028af +"@eslint/js@npm:8.55.0": + version: 8.55.0 + resolution: "@eslint/js@npm:8.55.0" + checksum: fa33ef619f0646ed15649b0c2e313e4d9ccee8425884bdbfc78020d6b6b64c0c42fa9d83061d0e6158e1d4274f03f0f9008786540e2efab8fcdc48082259908c languageName: node linkType: hard @@ -11398,15 +11507,6 @@ __metadata: languageName: node linkType: hard -"@fmvilas/pseudo-yaml-ast@npm:^0.3.1": - version: 0.3.1 - resolution: "@fmvilas/pseudo-yaml-ast@npm:0.3.1" - dependencies: - yaml-ast-parser: 0.0.43 - checksum: 94b825dcfe4295d3b3b275cccf756f4012f4c5260d2f8469f9004073635f9aefec204bb0c0dfa9f066a5f6998d32226cace293a6a4e78c2b3a1ba05457608647 - languageName: node - linkType: hard - "@gar/promisify@npm:^1.0.1, @gar/promisify@npm:^1.1.3": version: 1.1.3 resolution: "@gar/promisify@npm:1.1.3" @@ -11464,74 +11564,73 @@ __metadata: languageName: node linkType: hard -"@google-cloud/container@npm:^4.0.0, @google-cloud/container@npm:^4.15.0": - version: 4.16.0 - resolution: "@google-cloud/container@npm:4.16.0" +"@google-cloud/container@npm:^5.0.0": + version: 5.4.0 + resolution: "@google-cloud/container@npm:5.4.0" dependencies: - google-gax: ^3.5.8 - checksum: 324d31a45e21ce8e4734a861d5abc5a3ed8f5d0a4825db37ea4a8d6ae6658b395f5e70a29b02fe8964cbf9bd6a00387652b55a670113b941394a9dc54d34ec52 + google-gax: ^4.0.3 + checksum: ab6a6f0d6e6dc7feb30c848f40109ada5464c2594d9bbb467dbd522e097f0dc1108d366becfae268831d0ca203fa06dcedf28014d4d9161838bb2bb550162465 languageName: node linkType: hard -"@google-cloud/firestore@npm:^6.0.0": - version: 6.8.0 - resolution: "@google-cloud/firestore@npm:6.8.0" +"@google-cloud/firestore@npm:^7.0.0": + version: 7.1.0 + resolution: "@google-cloud/firestore@npm:7.1.0" dependencies: fast-deep-equal: ^3.1.1 functional-red-black-tree: ^1.0.1 - google-gax: ^3.5.7 + google-gax: ^4.0.4 protobufjs: ^7.2.5 - checksum: e8e1fd7cc6fd688e771c3d2f62c2f33d23357e11ee03f6d2f2aeb0ea29378f8e62f2511936011b515bbeedf304b5e831e4f4a46b8905dbc421fe2fa521d2e43f + checksum: 271deeb1fbf389237f34e0a6fa90336ddd3beccc8ff4b6519c22ee1edd2da4c74aa7ee3b14a669fb16dc67ea21bf3c3baf5d1ffb01218c121fd9ac71bb4e873b languageName: node linkType: hard -"@google-cloud/paginator@npm:^3.0.7": - version: 3.0.7 - resolution: "@google-cloud/paginator@npm:3.0.7" +"@google-cloud/paginator@npm:^5.0.0": + version: 5.0.0 + resolution: "@google-cloud/paginator@npm:5.0.0" dependencies: arrify: ^2.0.0 extend: ^3.0.2 - checksum: bdecce8a894a0c7f47f13d0e42b2fa142098e1dd34ce571b7216ad624057214baf9066ecf091501b3770da9d7be20b983eda30185c8c6596192cb748f8a0090c + checksum: 7b8236ce610bef5c5de62a0ec267b0e4368480397621a692d213c56ffe66b20a8e6d4de0fe0606fd165672c873467ea313493f035a582e674df72c29dd20b7ef languageName: node linkType: hard -"@google-cloud/projectify@npm:^3.0.0": - version: 3.0.0 - resolution: "@google-cloud/projectify@npm:3.0.0" - checksum: 4fa7ad689422b0b9c152fb00260e54e39d81678f9c51518bdb34bc57ee00604524fcdd5837fa97eb2f8ff4811afee3f345b1b0993bc4a2fa1b803bdd6554839a +"@google-cloud/projectify@npm:^4.0.0": + version: 4.0.0 + resolution: "@google-cloud/projectify@npm:4.0.0" + checksum: 973d28414ae200433333a3c315aebb881ced42ea4afe6f3f8520d2fecded75e76c913f5189fea8fb29ce6ca36117c4f44001b3c503eecdd3ac7f02597a98354a languageName: node linkType: hard -"@google-cloud/promisify@npm:^3.0.0": - version: 3.0.0 - resolution: "@google-cloud/promisify@npm:3.0.0" - checksum: 5339e36bd5bc7957ae72b959e21c5d50fe028ad8eae9affb6e8e172aab715f3bf6a7b3c01720d6b4b67ea080d91dd30ac00f0dc88d455620c8bb10df263385a2 +"@google-cloud/promisify@npm:^4.0.0": + version: 4.0.0 + resolution: "@google-cloud/promisify@npm:4.0.0" + checksum: edd189398c5ed5b7b64a373177d77c87d076a248c31b8ae878bb91e2411d89860108bcb948c349f32628973a823bd131beb53ec008fd613a8cb466ef1d89de49 languageName: node linkType: hard -"@google-cloud/storage@npm:^6.0.0": - version: 6.12.0 - resolution: "@google-cloud/storage@npm:6.12.0" +"@google-cloud/storage@npm:^7.0.0": + version: 7.7.0 + resolution: "@google-cloud/storage@npm:7.7.0" dependencies: - "@google-cloud/paginator": ^3.0.7 - "@google-cloud/projectify": ^3.0.0 - "@google-cloud/promisify": ^3.0.0 + "@google-cloud/paginator": ^5.0.0 + "@google-cloud/projectify": ^4.0.0 + "@google-cloud/promisify": ^4.0.0 abort-controller: ^3.0.0 async-retry: ^1.3.3 compressible: ^2.0.12 duplexify: ^4.0.0 ent: ^2.2.0 - extend: ^3.0.2 - fast-xml-parser: ^4.2.2 - gaxios: ^5.0.0 - google-auth-library: ^8.0.1 + fast-xml-parser: ^4.3.0 + gaxios: ^6.0.2 + google-auth-library: ^9.0.0 mime: ^3.0.0 mime-types: ^2.0.8 p-limit: ^3.0.1 - retry-request: ^5.0.0 - teeny-request: ^8.0.0 + retry-request: ^7.0.0 + teeny-request: ^9.0.0 uuid: ^8.0.0 - checksum: cfe44e3f4d1bacd8eeefa7885d261f421c4ff84e82abe50200b5b77e28322baf9cb67497872b9868b25b43b14197b1a155d5eb7b70afb39d3476fa4bdead3338 + checksum: b63069b7e591e55f9132aab9e8f9cd03b72a5b6e531c1f37fc44c4cd34eb02dd50e8007739dad6f0ac2ddb216eb5a80bc3b062d1d8c42aad7351e6cc6008d27f languageName: node linkType: hard @@ -11578,197 +11677,9 @@ __metadata: languageName: node linkType: hard -"@graphql-codegen/cli@npm:^3.0.0": - version: 3.3.1 - resolution: "@graphql-codegen/cli@npm:3.3.1" - dependencies: - "@babel/generator": ^7.18.13 - "@babel/template": ^7.18.10 - "@babel/types": ^7.18.13 - "@graphql-codegen/core": ^3.1.0 - "@graphql-codegen/plugin-helpers": ^4.2.0 - "@graphql-tools/apollo-engine-loader": ^7.3.6 - "@graphql-tools/code-file-loader": ^7.3.17 - "@graphql-tools/git-loader": ^7.2.13 - "@graphql-tools/github-loader": ^7.3.20 - "@graphql-tools/graphql-file-loader": ^7.5.0 - "@graphql-tools/json-file-loader": ^7.4.1 - "@graphql-tools/load": ^7.8.0 - "@graphql-tools/prisma-loader": ^7.2.49 - "@graphql-tools/url-loader": ^7.13.2 - "@graphql-tools/utils": ^9.0.0 - "@parcel/watcher": ^2.1.0 - "@whatwg-node/fetch": ^0.8.0 - chalk: ^4.1.0 - cosmiconfig: ^7.0.0 - debounce: ^1.2.0 - detect-indent: ^6.0.0 - graphql-config: ^4.5.0 - inquirer: ^8.0.0 - is-glob: ^4.0.1 - jiti: ^1.17.1 - json-to-pretty-yaml: ^1.2.2 - listr2: ^4.0.5 - log-symbols: ^4.0.0 - micromatch: ^4.0.5 - shell-quote: ^1.7.3 - string-env-interpolation: ^1.0.1 - ts-log: ^2.2.3 - tslib: ^2.4.0 - yaml: ^1.10.0 - yargs: ^17.0.0 - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - bin: - gql-gen: cjs/bin.js - graphql-code-generator: cjs/bin.js - graphql-codegen: cjs/bin.js - graphql-codegen-esm: esm/bin.js - checksum: cc3c0b8f1fd8150591b35b549a04577e84ac9c30396ad100196f594f741dd34e69ec9b1335ec41c00afe4ecf1d7e3505c1859fa244bdef1d10753d2b441de962 - languageName: node - linkType: hard - -"@graphql-codegen/core@npm:^3.1.0": - version: 3.1.0 - resolution: "@graphql-codegen/core@npm:3.1.0" - dependencies: - "@graphql-codegen/plugin-helpers": ^4.1.0 - "@graphql-tools/schema": ^9.0.0 - "@graphql-tools/utils": ^9.1.1 - tslib: ~2.5.0 - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: 7ace2b185242d00575b877b0bbb884c66915d246ba17a98c0ab82c2ee3a93ff2c9ae9d7d75a1d346de02ca8f12eb02801ffe2da4846da6e164b43176cd02dd8c - languageName: node - linkType: hard - -"@graphql-codegen/graphql-modules-preset@npm:^3.0.0": - version: 3.1.3 - resolution: "@graphql-codegen/graphql-modules-preset@npm:3.1.3" - dependencies: - "@graphql-codegen/plugin-helpers": ^4.2.0 - "@graphql-codegen/visitor-plugin-common": 3.1.1 - "@graphql-tools/utils": ^9.0.0 - change-case-all: 1.0.15 - parse-filepath: ^1.0.2 - tslib: ~2.5.0 - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: 6e7303a850984c3c414a96784f499dab188d94cf3d13b6f44cb3c59de4b5f127080df610a316554511cfe669283ac745d8b2537afbe6d8113e58f4b30a27c28b - languageName: node - linkType: hard - -"@graphql-codegen/plugin-helpers@npm:^4.1.0, @graphql-codegen/plugin-helpers@npm:^4.2.0": - version: 4.2.0 - resolution: "@graphql-codegen/plugin-helpers@npm:4.2.0" - dependencies: - "@graphql-tools/utils": ^9.0.0 - change-case-all: 1.0.15 - common-tags: 1.8.2 - import-from: 4.0.0 - lodash: ~4.17.0 - tslib: ~2.5.0 - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: 5d26adc132026916db061d23b06fc2c329f372f19ecf56e39bd2b30082bff642f2030cd6dc0bad8d2d3ab781c1e145384e040310a479b83d85ec804b2983646d - languageName: node - linkType: hard - -"@graphql-codegen/schema-ast@npm:^3.0.1": - version: 3.0.1 - resolution: "@graphql-codegen/schema-ast@npm:3.0.1" - dependencies: - "@graphql-codegen/plugin-helpers": ^4.1.0 - "@graphql-tools/utils": ^9.0.0 - tslib: ~2.5.0 - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: 620aa67a4ae59ccb4609763b7347d05e2cec62bf1362be3e1e01fc00969cdbb858398542aa261128e5b5e3cb6808b77861bdcf82662e80326e72b418f25f465f - languageName: node - linkType: hard - -"@graphql-codegen/typescript-resolvers@npm:^3.0.0": - version: 3.2.1 - resolution: "@graphql-codegen/typescript-resolvers@npm:3.2.1" - dependencies: - "@graphql-codegen/plugin-helpers": ^4.2.0 - "@graphql-codegen/typescript": ^3.0.4 - "@graphql-codegen/visitor-plugin-common": 3.1.1 - "@graphql-tools/utils": ^9.0.0 - auto-bind: ~4.0.0 - tslib: ~2.5.0 - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: a84f8fc68fe778beabbf537f1312699a220a3a605d972403075d8307fb7fe9aec73ae2eb5b42dea9f3a7c91deabfe6e1271d607e1b2c84b346686107f39354fb - languageName: node - linkType: hard - -"@graphql-codegen/typescript@npm:^3.0.0, @graphql-codegen/typescript@npm:^3.0.4": - version: 3.0.4 - resolution: "@graphql-codegen/typescript@npm:3.0.4" - dependencies: - "@graphql-codegen/plugin-helpers": ^4.2.0 - "@graphql-codegen/schema-ast": ^3.0.1 - "@graphql-codegen/visitor-plugin-common": 3.1.1 - auto-bind: ~4.0.0 - tslib: ~2.5.0 - peerDependencies: - graphql: ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: ede5311c5f620e16c3e98f51bdcedc7fd42f2c552a8ca5a946f757dc9709c384a12d32d088769d04041461d3318159ad0644f70056aea1877ee80a0bdc48de1f - languageName: node - linkType: hard - -"@graphql-codegen/visitor-plugin-common@npm:3.1.1": - version: 3.1.1 - resolution: "@graphql-codegen/visitor-plugin-common@npm:3.1.1" - dependencies: - "@graphql-codegen/plugin-helpers": ^4.2.0 - "@graphql-tools/optimize": ^1.3.0 - "@graphql-tools/relay-operation-optimizer": ^6.5.0 - "@graphql-tools/utils": ^9.0.0 - auto-bind: ~4.0.0 - change-case-all: 1.0.15 - dependency-graph: ^0.11.0 - graphql-tag: ^2.11.0 - parse-filepath: ^1.0.2 - tslib: ~2.5.0 - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: 8dbef75ba0576a7de5e134b53778d64d818084df01e74554adc979f08db8446e9734889575c820449b6ef9febd6a9005fb89c7c9c101a9e398c195b5c3279353 - languageName: node - linkType: hard - -"@graphql-tools/apollo-engine-loader@npm:^7.3.6": - version: 7.3.6 - resolution: "@graphql-tools/apollo-engine-loader@npm:7.3.6" - dependencies: - "@ardatan/sync-fetch": 0.0.1 - "@graphql-tools/utils": 8.9.0 - "@whatwg-node/fetch": ^0.2.4 - tslib: ^2.4.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: e9711b32fd90d41c97ea8eb6bcc68e5a78374114fdd628ae9f1d4855cc163aecda78d22697c0f6ab556f816a01d27d684bd756ed1b777e7fa42b63200c240b90 - languageName: node - linkType: hard - -"@graphql-tools/batch-execute@npm:8.5.14": - version: 8.5.14 - resolution: "@graphql-tools/batch-execute@npm:8.5.14" - dependencies: - "@graphql-tools/utils": 9.1.3 - dataloader: 2.1.0 - tslib: ^2.4.0 - value-or-promise: 1.0.11 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: a48a11f471fe804852abb60f361eb8e398e5fd9d3b8bc61e3734983a5c8c284f3087b903b5277a2c7e365434947af534a881e67c147b0a3d47849617e124ac33 - languageName: node - linkType: hard - "@graphql-tools/batch-execute@npm:^9.0.1": - version: 9.0.1 - resolution: "@graphql-tools/batch-execute@npm:9.0.1" + version: 9.0.2 + resolution: "@graphql-tools/batch-execute@npm:9.0.2" dependencies: "@graphql-tools/utils": ^10.0.5 dataloader: ^2.2.2 @@ -11776,45 +11687,13 @@ __metadata: value-or-promise: ^1.0.12 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: c2bcf9dbcd3d08b2e04708fddad7f587677b62e189b0357b8a5495693e17b257b3022f5983d503966baaf32cbdc92a0a00dc95be7f5b6039357a31ffdde29a19 + checksum: 35da796959dbdb9bf59c913b2db25ab6db244243a5d3adb011f528841ac4c54f36d0731d2cb5b5ea8d0f2d28b61e34fe47a9afc905072848c1cc362193583f1b languageName: node linkType: hard -"@graphql-tools/code-file-loader@npm:^7.3.17": - version: 7.3.21 - resolution: "@graphql-tools/code-file-loader@npm:7.3.21" - dependencies: - "@graphql-tools/graphql-tag-pluck": 7.5.0 - "@graphql-tools/utils": 9.2.1 - globby: ^11.0.3 - tslib: ^2.4.0 - unixify: ^1.0.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 5d0d0a70bac673b4925a65f2283e3fcc5c093d2466a144cc577cb515d3de92ca2458d92842e02fe82a95d57d30ce6d2998b8ee5674393f7cd3df52f69671d565 - languageName: node - linkType: hard - -"@graphql-tools/delegate@npm:9.0.21": - version: 9.0.21 - resolution: "@graphql-tools/delegate@npm:9.0.21" - dependencies: - "@graphql-tools/batch-execute": 8.5.14 - "@graphql-tools/executor": 0.0.11 - "@graphql-tools/schema": 9.0.12 - "@graphql-tools/utils": 9.1.3 - dataloader: 2.1.0 - tslib: ~2.4.0 - value-or-promise: 1.0.11 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: fab07abfb06325d82382e6de45bbf2bc6501f18ebabbe50661772b58f512d6e713565be16bd7f99f71fcb00ffeed25bba871d4d459a705880803878e20c2a183 - languageName: node - linkType: hard - -"@graphql-tools/delegate@npm:^10.0.0": - version: 10.0.2 - resolution: "@graphql-tools/delegate@npm:10.0.2" +"@graphql-tools/delegate@npm:^10.0.0, @graphql-tools/delegate@npm:^10.0.3": + version: 10.0.3 + resolution: "@graphql-tools/delegate@npm:10.0.3" dependencies: "@graphql-tools/batch-execute": ^9.0.1 "@graphql-tools/executor": ^1.0.0 @@ -11824,72 +11703,55 @@ __metadata: tslib: ^2.5.0 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 3641dd03b241234cc0bc15221e1bd7e82f003f0bdb59a04cfaba23b5dc43d3aed1f068cc79d526dd731f6e4acfd90c9e20287feb565b9c881ed441c5008e32db + checksum: 999b04ebcf92bb0978b1d1c059a8b152bd42a4d6aaa47441305fd662d40dcd27f2a2b5b35e3c4da96661a2f15178bee4235af8f918db0788c0f1454555a667b2 languageName: node linkType: hard -"@graphql-tools/executor-graphql-ws@npm:0.0.5": - version: 0.0.5 - resolution: "@graphql-tools/executor-graphql-ws@npm:0.0.5" +"@graphql-tools/executor-graphql-ws@npm:^1.0.0": + version: 1.1.1 + resolution: "@graphql-tools/executor-graphql-ws@npm:1.1.1" dependencies: - "@graphql-tools/utils": 9.1.3 - "@repeaterjs/repeater": 3.0.4 + "@graphql-tools/utils": ^10.0.2 "@types/ws": ^8.0.0 - graphql-ws: 5.11.2 - isomorphic-ws: 5.0.0 + graphql-ws: ^5.14.0 + isomorphic-ws: ^5.0.0 tslib: ^2.4.0 - ws: 8.11.0 + ws: ^8.13.0 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 79ced279e56b7508282859f805ca8fe1286eec3b53592893e35517f93e5204eca2db327258599749b0d832918d9d709962059087b4e6a894eacc16ceb0142273 + checksum: 30d29e2ef8fbedf07d7c279218f31a7279e714328f6c24d28ea76536fb4c5ed857ab5e486922000fcf9f85b83a9f3e995b8fd066b01ea4ab31d35efaa770c133 languageName: node linkType: hard -"@graphql-tools/executor-http@npm:0.0.7": - version: 0.0.7 - resolution: "@graphql-tools/executor-http@npm:0.0.7" +"@graphql-tools/executor-http@npm:^1.0.0": + version: 1.0.3 + resolution: "@graphql-tools/executor-http@npm:1.0.3" dependencies: - "@graphql-tools/utils": 9.1.3 - "@repeaterjs/repeater": 3.0.4 - "@whatwg-node/fetch": 0.5.3 - dset: 3.1.2 + "@graphql-tools/utils": ^10.0.2 + "@repeaterjs/repeater": ^3.0.4 + "@whatwg-node/fetch": ^0.9.0 extract-files: ^11.0.0 - meros: 1.2.1 + meros: ^1.2.1 tslib: ^2.4.0 - value-or-promise: 1.0.11 + value-or-promise: ^1.0.12 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 05918ee65cb7d3e927e707acddb184ba2efbccf03656454ff8b172654aa41c4ad35bed487c0399ca085ba39ca434421cdaadb78dec4d7ebabbd25fe3c5cbb81c + checksum: a6d757bfb1cba4b28b098c6775f2093d34059820bf8fa4cc6a2ef9007464a8e0d3b431f354cbc9b7c5388604d4b8dd245b32c9c43e0be74d5d4cd3da9d5d5da8 languageName: node linkType: hard -"@graphql-tools/executor-legacy-ws@npm:0.0.5": - version: 0.0.5 - resolution: "@graphql-tools/executor-legacy-ws@npm:0.0.5" +"@graphql-tools/executor-legacy-ws@npm:^1.0.0": + version: 1.0.4 + resolution: "@graphql-tools/executor-legacy-ws@npm:1.0.4" dependencies: - "@graphql-tools/utils": 9.1.3 + "@graphql-tools/utils": ^10.0.0 "@types/ws": ^8.0.0 isomorphic-ws: 5.0.0 tslib: ^2.4.0 - ws: 8.11.0 + ws: 8.14.2 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 2705e57ae81fbe3117d14900d50ab2459618d93192f795db97e2b98e9a772ebfe2308c17e72d92735123ec32fbedad014158d20fd1cc569fa287d47c90037a71 - languageName: node - linkType: hard - -"@graphql-tools/executor@npm:0.0.11": - version: 0.0.11 - resolution: "@graphql-tools/executor@npm:0.0.11" - dependencies: - "@graphql-tools/utils": 9.1.3 - "@graphql-typed-document-node/core": 3.1.1 - "@repeaterjs/repeater": 3.0.4 - tslib: ^2.4.0 - value-or-promise: 1.0.11 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 9f4c5d50eb574ab788a70684150502d4ad25b2681a3933a9415a0bbd78bfdf5ee203dca8bccc4cef93727157254216f0c22c5359bef1c1738f652b3122048b17 + checksum: d271e7b0860dfa47b29ca56aa761e555c804a3223ed9f42784b2f1dcc872b15976a2c89db9b34ca26143a0b5cf6f45c771ddc23c0c012f5dabf222334c59635e languageName: node linkType: hard @@ -11908,122 +11770,59 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/git-loader@npm:^7.2.13": - version: 7.2.13 - resolution: "@graphql-tools/git-loader@npm:7.2.13" +"@graphql-tools/graphql-file-loader@npm:^8.0.0": + version: 8.0.0 + resolution: "@graphql-tools/graphql-file-loader@npm:8.0.0" dependencies: - "@graphql-tools/graphql-tag-pluck": 7.4.0 - "@graphql-tools/utils": 9.1.1 - is-glob: 4.0.3 - micromatch: ^4.0.4 - tslib: ^2.4.0 - unixify: ^1.0.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 4690d473bb05d91765ee54fbfd0cb3859bda8cef776feced26e477b6aef22c582923ff18bdc963adcb649d8fa975344371001af60867d1e2cfd5624917cf6e91 - languageName: node - linkType: hard - -"@graphql-tools/github-loader@npm:^7.3.20": - version: 7.3.20 - resolution: "@graphql-tools/github-loader@npm:7.3.20" - dependencies: - "@ardatan/sync-fetch": 0.0.1 - "@graphql-tools/graphql-tag-pluck": 7.4.0 - "@graphql-tools/utils": 9.1.1 - "@whatwg-node/fetch": ^0.5.0 - tslib: ^2.4.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 96292e59f8b394fb1e69fae91b3fdf037962e8feadd15da7461043c9559450fc35c2438b669727b14a6d509f784f0c5401477f3f90f693a93fc8c59c246d0c77 - languageName: node - linkType: hard - -"@graphql-tools/graphql-file-loader@npm:^7.3.7, @graphql-tools/graphql-file-loader@npm:^7.5.0": - version: 7.5.0 - resolution: "@graphql-tools/graphql-file-loader@npm:7.5.0" - dependencies: - "@graphql-tools/import": 6.7.1 - "@graphql-tools/utils": 8.9.0 + "@graphql-tools/import": 7.0.0 + "@graphql-tools/utils": ^10.0.0 globby: ^11.0.3 tslib: ^2.4.0 unixify: ^1.0.0 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 57f9f64a26f62d25fcb65282d27a8f6cce8d99fd0ec8f1d5b31ab43fd5698876760e4df42fd96f2b5ea524f2e755768496ee2b3516d559d43270330551371359 + checksum: 62c5150132a044c396dddd55b6acfe88e1bee21911bbe7905eb35516e0dd969e18ca558a77bb62c5b243bf877fee0a66a5ef2e7dce611d44ef1d5ad8edda151b languageName: node linkType: hard -"@graphql-tools/graphql-tag-pluck@npm:7.4.0": - version: 7.4.0 - resolution: "@graphql-tools/graphql-tag-pluck@npm:7.4.0" +"@graphql-tools/import@npm:7.0.0": + version: 7.0.0 + resolution: "@graphql-tools/import@npm:7.0.0" dependencies: - "@babel/parser": ^7.16.8 - "@babel/plugin-syntax-import-assertions": 7.20.0 - "@babel/traverse": ^7.16.8 - "@babel/types": ^7.16.8 - "@graphql-tools/utils": 9.1.1 - tslib: ^2.4.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 670888e691707d430066a84ddcc9a34f64c6146e3f1406ab9fbdf74d5805fcbac8d32462cd387c411fbb81a5fc6bfb4d4d14e0568c5b887c72df8ebb7ef66c1b - languageName: node - linkType: hard - -"@graphql-tools/graphql-tag-pluck@npm:7.5.0": - version: 7.5.0 - resolution: "@graphql-tools/graphql-tag-pluck@npm:7.5.0" - dependencies: - "@babel/parser": ^7.16.8 - "@babel/plugin-syntax-import-assertions": 7.20.0 - "@babel/traverse": ^7.16.8 - "@babel/types": ^7.16.8 - "@graphql-tools/utils": 9.2.1 - tslib: ^2.4.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 47edaacdeafc4a464f8a51e047cafbb82a9a2700536a5b075eb4afad43c80b513a7b0ac4ad49a1e8a74b566ed7dfd677ebb0d0a967fe1e2ee66408cd5d4f294b - languageName: node - linkType: hard - -"@graphql-tools/import@npm:6.7.1": - version: 6.7.1 - resolution: "@graphql-tools/import@npm:6.7.1" - dependencies: - "@graphql-tools/utils": 8.9.0 + "@graphql-tools/utils": ^10.0.0 resolve-from: 5.0.0 tslib: ^2.4.0 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 1ba6ff176851eff345ccfd37616bd2d800fba074b88abb9a777b59fe153a1e55f2c24d8c033b141303267212f6a01eb874088e403b7efdf10c01c9ec7833af49 + checksum: 24f7f2096b635b84983932b53d2953edf77f2d35f22d892569aa0c8303a5eb1dd5cff5922dc0264cfe22891730a17cf69392a9fd4b1b682a89553d8e16247498 languageName: node linkType: hard -"@graphql-tools/json-file-loader@npm:^7.3.7, @graphql-tools/json-file-loader@npm:^7.4.1": - version: 7.4.1 - resolution: "@graphql-tools/json-file-loader@npm:7.4.1" +"@graphql-tools/json-file-loader@npm:^8.0.0": + version: 8.0.0 + resolution: "@graphql-tools/json-file-loader@npm:8.0.0" dependencies: - "@graphql-tools/utils": 8.9.0 + "@graphql-tools/utils": ^10.0.0 globby: ^11.0.3 tslib: ^2.4.0 unixify: ^1.0.0 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 9eae0fd4229b60fa93d3e523e7255eeb2400bda44a2e73ba036955c514be4f02c83e7578c4749c4a7e84b44d318d4c65979b745ddb34fa4d219449f455e3e873 + checksum: 5fe0ab7b2cb0a4fac7a223928803a4f193628d51ef6da06cf9fbed63b742b39efa2dac45cef69febcb49d1c7122b2b4447b1e6af46ab799ce529e44f9f974d7f languageName: node linkType: hard -"@graphql-tools/load@npm:^7.5.5, @graphql-tools/load@npm:^7.8.0": - version: 7.8.10 - resolution: "@graphql-tools/load@npm:7.8.10" +"@graphql-tools/load@npm:^8.0.0": + version: 8.0.0 + resolution: "@graphql-tools/load@npm:8.0.0" dependencies: - "@graphql-tools/schema": 9.0.14 - "@graphql-tools/utils": 9.1.4 + "@graphql-tools/schema": ^10.0.0 + "@graphql-tools/utils": ^10.0.0 p-limit: 3.1.0 tslib: ^2.4.0 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 9b1fd7041fc69072c4f7d6bc320c9de7f990e1792db567d3d913b9cc77f5c164ffee968dd90a688d89856e1e8c01beb8e1bbe9f22464fa8c563553229c3a3f28 + checksum: e1126bef8917e8a7e89c12cc95b127de727c04502e57f379d93dd3027ce72dc38b16a52a417263959a938b4660a1d362836eed59f941cd30ee3d5452c793a50d languageName: node linkType: hard @@ -12039,42 +11838,6 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/merge@npm:8.3.14": - version: 8.3.14 - resolution: "@graphql-tools/merge@npm:8.3.14" - dependencies: - "@graphql-tools/utils": 9.1.3 - tslib: ^2.4.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: d77098959a7ecf1346958eb6731f7354fc1155d253aa25169ca48b73053784f3db203ff88ada6a1cdfa9a0b026e55ce02afb83ac61b501223c018e97accf7cdc - languageName: node - linkType: hard - -"@graphql-tools/merge@npm:8.3.16": - version: 8.3.16 - resolution: "@graphql-tools/merge@npm:8.3.16" - dependencies: - "@graphql-tools/utils": 9.1.4 - tslib: ^2.4.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 4d7fa594e0d97b6d596c85619a8203cb9c88452b75efac4191697de00db5d043639ed47f6bf0a3ccc11e8638714d92a4a8bc37e77b61b46790ddf4a1e5d4bb87 - languageName: node - linkType: hard - -"@graphql-tools/merge@npm:^8.2.6, @graphql-tools/merge@npm:^8.4.1": - version: 8.4.1 - resolution: "@graphql-tools/merge@npm:8.4.1" - dependencies: - "@graphql-tools/utils": ^9.2.1 - tslib: ^2.4.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: badb094e2eb29688d39d451a83909dc6f92a28c98dbb485a2f745a963813ad1310b1624c7618e97477c90f7935c99b06792bf63c4957a58c642af1609bcec143 - languageName: node - linkType: hard - "@graphql-tools/merge@npm:^9.0.0": version: 9.0.0 resolution: "@graphql-tools/merge@npm:9.0.0" @@ -12087,87 +11850,6 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/optimize@npm:^1.3.0": - version: 1.3.0 - resolution: "@graphql-tools/optimize@npm:1.3.0" - dependencies: - tslib: ^2.4.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 56a5e8e3079a7ac69639410143315bafd43175c0366a95cf037698b64799ff80fc737b747b7751a4de31b44a679f67b7499468c556ca457932d5d1052db73f19 - languageName: node - linkType: hard - -"@graphql-tools/prisma-loader@npm:^7.2.49": - version: 7.2.49 - resolution: "@graphql-tools/prisma-loader@npm:7.2.49" - dependencies: - "@graphql-tools/url-loader": 7.16.28 - "@graphql-tools/utils": 9.1.3 - "@types/js-yaml": ^4.0.0 - "@types/json-stable-stringify": ^1.0.32 - "@types/jsonwebtoken": ^8.5.0 - chalk: ^4.1.0 - debug: ^4.3.1 - dotenv: ^16.0.0 - graphql-request: ^5.0.0 - http-proxy-agent: ^5.0.0 - https-proxy-agent: ^5.0.0 - isomorphic-fetch: ^3.0.0 - js-yaml: ^4.0.0 - json-stable-stringify: ^1.0.1 - jsonwebtoken: ^9.0.0 - lodash: ^4.17.20 - scuid: ^1.1.0 - tslib: ^2.4.0 - yaml-ast-parser: ^0.0.43 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 9a392346107ec5e468a8725c1d931b638e1899c25a80e34e9c888c050abf85dfde85faea9fdb19a8bfd9425bdb97949e14e759157d083aa91812fcff516ad82d - languageName: node - linkType: hard - -"@graphql-tools/relay-operation-optimizer@npm:^6.5.0": - version: 6.5.0 - resolution: "@graphql-tools/relay-operation-optimizer@npm:6.5.0" - dependencies: - "@ardatan/relay-compiler": 12.0.0 - "@graphql-tools/utils": 8.8.0 - tslib: ^2.4.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: eea705c0508b801806d36a6031997868d1aa35a2bee0a21c36e5ac345691a9fec88c9c00bc3c96fa998aa28deb2be667d65e6123ac469f22072f3eba2781b5ad - languageName: node - linkType: hard - -"@graphql-tools/schema@npm:9.0.12": - version: 9.0.12 - resolution: "@graphql-tools/schema@npm:9.0.12" - dependencies: - "@graphql-tools/merge": 8.3.14 - "@graphql-tools/utils": 9.1.3 - tslib: ^2.4.0 - value-or-promise: 1.0.11 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: c5ea750466181b425dd77822b1dc774227bcdb3a01631f114734d450cfc2dabeac60b3fac40e047090d6035b6a559b614716f1b61068889cf5aae0785650c31b - languageName: node - linkType: hard - -"@graphql-tools/schema@npm:9.0.14": - version: 9.0.14 - resolution: "@graphql-tools/schema@npm:9.0.14" - dependencies: - "@graphql-tools/merge": 8.3.16 - "@graphql-tools/utils": 9.1.4 - tslib: ^2.4.0 - value-or-promise: 1.0.12 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: ae958892363fe8b1715a9fd3c4bdb56d0d5d429693dbb9774ce930d104ed5a7c94db3c41c12d91fd930bf90ab186337d3ba660e765a99a98bde892f0d2dcf40e - languageName: node - linkType: hard - "@graphql-tools/schema@npm:^10.0.0": version: 10.0.0 resolution: "@graphql-tools/schema@npm:10.0.0" @@ -12196,51 +11878,26 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/schema@npm:^9.0.0": - version: 9.0.19 - resolution: "@graphql-tools/schema@npm:9.0.19" +"@graphql-tools/url-loader@npm:^8.0.0": + version: 8.0.0 + resolution: "@graphql-tools/url-loader@npm:8.0.0" dependencies: - "@graphql-tools/merge": ^8.4.1 - "@graphql-tools/utils": ^9.2.1 - tslib: ^2.4.0 - value-or-promise: ^1.0.12 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 1be91f61bf4be0c1c9aa640a6ad5b58328d5434d15e78ba73a47263420939db6741ad6723dece4611257e7e1e56518e116b76513a3014305d3f52d67aafb62fb - languageName: node - linkType: hard - -"@graphql-tools/url-loader@npm:7.16.28, @graphql-tools/url-loader@npm:^7.13.2, @graphql-tools/url-loader@npm:^7.9.7": - version: 7.16.28 - resolution: "@graphql-tools/url-loader@npm:7.16.28" - dependencies: - "@ardatan/sync-fetch": 0.0.1 - "@graphql-tools/delegate": 9.0.21 - "@graphql-tools/executor-graphql-ws": 0.0.5 - "@graphql-tools/executor-http": 0.0.7 - "@graphql-tools/executor-legacy-ws": 0.0.5 - "@graphql-tools/utils": 9.1.3 - "@graphql-tools/wrap": 9.2.23 + "@ardatan/sync-fetch": ^0.0.1 + "@graphql-tools/delegate": ^10.0.0 + "@graphql-tools/executor-graphql-ws": ^1.0.0 + "@graphql-tools/executor-http": ^1.0.0 + "@graphql-tools/executor-legacy-ws": ^1.0.0 + "@graphql-tools/utils": ^10.0.0 + "@graphql-tools/wrap": ^10.0.0 "@types/ws": ^8.0.0 - "@whatwg-node/fetch": ^0.5.0 - isomorphic-ws: 5.0.0 + "@whatwg-node/fetch": ^0.9.0 + isomorphic-ws: ^5.0.0 tslib: ^2.4.0 value-or-promise: ^1.0.11 - ws: 8.11.0 + ws: ^8.12.0 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: fca2dada0d80c051358f928a321eda0cfa96bb71704b4feb7e61dfd7226f78fb1dd2e8268f4e81080a2984cf57ee92ef6c8608c89c6f931860a0cbdd63bcb031 - languageName: node - linkType: hard - -"@graphql-tools/utils@npm:8.8.0": - version: 8.8.0 - resolution: "@graphql-tools/utils@npm:8.8.0" - dependencies: - tslib: ^2.4.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 631aa690fcf7c01c42829af93f2af1c62d2eeaca99a74f2ae9d6424b7662383391fff37443d61f76fd9f00243b33d0ba0a7df8792c835e1db1fd1b4cee2f32f0 + checksum: ddb77848d62a1705e09058e2de16342b0c4f3cf4a3a690e06a65ccaf4d1f72d1fe19f1862cce445cc4a7e8891cb61d6f1aa81540138076cf59a6ceaf3696a7e1 languageName: node linkType: hard @@ -12255,61 +11912,17 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/utils@npm:9.1.1": - version: 9.1.1 - resolution: "@graphql-tools/utils@npm:9.1.1" - dependencies: - tslib: ^2.4.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 5a5120417c00b0f8a834b69dca9b7496022f8b1ed3719c2cf7de8253ff639ecc0f4a8e2bcaf0193ce44bd59431098180e94bdd96406e9f260e058b16c0e26975 - languageName: node - linkType: hard - -"@graphql-tools/utils@npm:9.1.3": - version: 9.1.3 - resolution: "@graphql-tools/utils@npm:9.1.3" - dependencies: - tslib: ^2.4.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 3b5acd41ae939e2811f496b1676e6219be61a95f3e502bb3783542a67e7703d7709d4ae87fc9deb7284280aea687fb4b0e596f538d7f1cdf5a8827a2952ee994 - languageName: node - linkType: hard - -"@graphql-tools/utils@npm:9.1.4": - version: 9.1.4 - resolution: "@graphql-tools/utils@npm:9.1.4" - dependencies: - tslib: ^2.4.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 467135297a07b21bdd706ca03385354931db85fcf2accc514d69b7415c8cb0fb9e551e4bba0870278eab58bf4de757d354d53c88fd0f55b52d8562dbcba71869 - languageName: node - linkType: hard - -"@graphql-tools/utils@npm:9.2.1, @graphql-tools/utils@npm:^9.0.0, @graphql-tools/utils@npm:^9.1.1, @graphql-tools/utils@npm:^9.2.1": - version: 9.2.1 - resolution: "@graphql-tools/utils@npm:9.2.1" - dependencies: - "@graphql-typed-document-node/core": ^3.1.1 - tslib: ^2.4.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 94ed12df5f49e5c338322ffd931236a687a3d5c443bf499f9baab5d4fcd9792234111142be8aa506a01ca2e82732996c4e1d8f6159ff9cc7fdc5c97f63e55226 - languageName: node - linkType: hard - -"@graphql-tools/utils@npm:^10.0.0, @graphql-tools/utils@npm:^10.0.5": - version: 10.0.5 - resolution: "@graphql-tools/utils@npm:10.0.5" +"@graphql-tools/utils@npm:^10.0.0, @graphql-tools/utils@npm:^10.0.2, @graphql-tools/utils@npm:^10.0.5": + version: 10.0.8 + resolution: "@graphql-tools/utils@npm:10.0.8" dependencies: "@graphql-typed-document-node/core": ^3.1.1 + cross-inspect: 1.0.0 dset: ^3.1.2 tslib: ^2.4.0 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 600eb668b0a80264a56d1bfc2b431073a620de8ffea959362a1d13c4e0dd5738b627cc508ead8ecdbd7c1a2da05d5664e43443e15d3b221a809fa1a0e2740193 + checksum: 75d4f17592b5b93c1a60efb583decd96cc0f7cacfb68f483569d28bb9afd5a8d0b4e85a0136fa54c222c090d55bfc085798f1acccd5db41f7971673547cf2a34 languageName: node linkType: hard @@ -12324,46 +11937,22 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/wrap@npm:9.2.23": - version: 9.2.23 - resolution: "@graphql-tools/wrap@npm:9.2.23" - dependencies: - "@graphql-tools/delegate": 9.0.21 - "@graphql-tools/schema": 9.0.12 - "@graphql-tools/utils": 9.1.3 - tslib: ^2.4.0 - value-or-promise: 1.0.11 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 8f4f289d51adb92a7099940892c52b710e61f76d02580a3223e80aaed790d32f769cae33a4afeff398357f33a55267427d9703de6f0bd30ec9ba57ee3bd5ef5c - languageName: node - linkType: hard - "@graphql-tools/wrap@npm:^10.0.0": - version: 10.0.0 - resolution: "@graphql-tools/wrap@npm:10.0.0" + version: 10.0.1 + resolution: "@graphql-tools/wrap@npm:10.0.1" dependencies: - "@graphql-tools/delegate": ^10.0.0 + "@graphql-tools/delegate": ^10.0.3 "@graphql-tools/schema": ^10.0.0 "@graphql-tools/utils": ^10.0.0 tslib: ^2.4.0 value-or-promise: ^1.0.12 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: f7ce366cdd479c3f73c3c98f66fa13c528c63e2f791083e78ca14e010ebcd359b5c9bd78e2e8bd437a705418b87584eb6512f1eeb1971b81560c79c6fb3a4a6e + checksum: e94d63301c045688cd7bfd6cff4375de42b344eea3c4e604b9e98d29c3544d2222435e2e3f5ada0c0db690e364af630246ccc56f2b299addc93c2e77d6dd72d1 languageName: node linkType: hard -"@graphql-typed-document-node/core@npm:3.1.1": - version: 3.1.1 - resolution: "@graphql-typed-document-node/core@npm:3.1.1" - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: 87ff4cee308f1075f4472b80f9f9409667979940f8f701e87f0aa35ce5cf104d94b41258ea8192d05a0893475cd0f086a3929a07663b4fe8d0e805a277f07ed5 - languageName: node - linkType: hard - -"@graphql-typed-document-node/core@npm:3.2.0, @graphql-typed-document-node/core@npm:^3.1.0, @graphql-typed-document-node/core@npm:^3.1.1": +"@graphql-typed-document-node/core@npm:3.2.0, @graphql-typed-document-node/core@npm:^3.1.1": version: 3.2.0 resolution: "@graphql-typed-document-node/core@npm:3.2.0" peerDependencies: @@ -12372,28 +11961,27 @@ __metadata: languageName: node linkType: hard -"@grpc/grpc-js@npm:~1.8.0": - version: 1.8.9 - resolution: "@grpc/grpc-js@npm:1.8.9" +"@grpc/grpc-js@npm:~1.9.6": + version: 1.9.11 + resolution: "@grpc/grpc-js@npm:1.9.11" dependencies: - "@grpc/proto-loader": ^0.7.0 + "@grpc/proto-loader": ^0.7.8 "@types/node": ">=12.12.47" - checksum: 40408af0c0e2b61dbb0fe1c246ae30404c89c601f3e9f9f8447f82d01d8dc0c8befccf2afe9ded07dfc8bd89c927bcbfb5925d4b1ae887299112b2ab549f519c + checksum: ed11ebcb0f8c34e2ada1d16ac2eef2465e1812871dd42bf40a405dfa06e2bfe895e680aff10644f9d51c33ce1ee1882ee466237ee478365c5ed265c0d7c5c015 languageName: node linkType: hard -"@grpc/proto-loader@npm:^0.7.0": - version: 0.7.2 - resolution: "@grpc/proto-loader@npm:0.7.2" +"@grpc/proto-loader@npm:^0.7.0, @grpc/proto-loader@npm:^0.7.8": + version: 0.7.10 + resolution: "@grpc/proto-loader@npm:0.7.10" dependencies: - "@types/long": ^4.0.1 lodash.camelcase: ^4.3.0 - long: ^4.0.0 - protobufjs: ^7.0.0 - yargs: ^16.2.0 + long: ^5.0.0 + protobufjs: ^7.2.4 + yargs: ^17.7.2 bin: proto-loader-gen-types: build/bin/proto-loader-gen-types.js - checksum: b6b45b3da96d634886cae149be67c8754de6e6ed03fee974308610b99df417d7b33f12c22b2770755482634193876baeff13469f9d82898e0a5ccf4e5d8b3535 + checksum: 4987e23b57942c2363b6a6a106e63efae636666cefa348778dfafef2ff72da7343c8587667521cb1d52482827bcd001dd535bdc27065110af56d9c7c176334c9 languageName: node linkType: hard @@ -12901,13 +12489,6 @@ __metadata: languageName: node linkType: hard -"@josephg/resolvable@npm:^1.0.0": - version: 1.0.1 - resolution: "@josephg/resolvable@npm:1.0.1" - checksum: 64eb763b5138bdae4fb59c0c0e89ed261b690917ae6bd777b533257668f151b8868698fb73dfd7665746ad07c7c917fe89ccfdf2404048d39f373f57f1a14e34 - languageName: node - linkType: hard - "@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": version: 0.3.2 resolution: "@jridgewell/gen-mapping@npm:0.3.2" @@ -12943,7 +12524,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.13, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15": +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15": version: 1.4.15 resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 @@ -12977,15 +12558,6 @@ __metadata: languageName: node linkType: hard -"@jsdoc/salty@npm:^0.2.1": - version: 0.2.3 - resolution: "@jsdoc/salty@npm:0.2.3" - dependencies: - lodash: ^4.17.21 - checksum: d2b29089e6ba942bf3228087d35379ada248c34f136357d1a4bf5c0350a0d5bde0f90dc68d5e7271728bac1951f85fe749075df0a32a9d584ad5d198492bf7f1 - languageName: node - linkType: hard - "@jsep-plugin/regex@npm:^1.0.1": version: 1.0.3 resolution: "@jsep-plugin/regex@npm:1.0.3" @@ -13064,9 +12636,9 @@ __metadata: languageName: node linkType: hard -"@kubernetes/client-node@npm:0.19.0, @kubernetes/client-node@npm:^0.19.0": - version: 0.19.0 - resolution: "@kubernetes/client-node@npm:0.19.0" +"@kubernetes/client-node@npm:0.20.0, @kubernetes/client-node@npm:^0.20.0": + version: 0.20.0 + resolution: "@kubernetes/client-node@npm:0.20.0" dependencies: "@types/js-yaml": ^4.0.1 "@types/node": ^20.1.1 @@ -13086,7 +12658,7 @@ __metadata: dependenciesMeta: openid-client: optional: true - checksum: d29ccfb562ac51a81f74de570eb832d150be6b73ba887ae1be682df9a34c3ab846d4d4ba74f0a9f0e0ce4da573f949ba712115e1d0513148cdf683a22d729e7f + checksum: c7c2ec9c597b5579ec452bcc13647feeaa3eaf93601afa5d9a4e06b5fe91d2cafa444a1da07b5330a7596f0e07e107d6abe4acabc5998f7bedf43cd0ab8bf343 languageName: node linkType: hard @@ -13560,9 +13132,9 @@ __metadata: linkType: hard "@microsoft/microsoft-graph-types@npm:^2.25.0, @microsoft/microsoft-graph-types@npm:^2.6.0": - version: 2.38.0 - resolution: "@microsoft/microsoft-graph-types@npm:2.38.0" - checksum: f5778650655034a6d92fbb932376002aefcf0cd358de323267b65fbec59284e8c0208e895c5523dcbbe79c4b583f3822c6beea01b70c687da26929c92de93c92 + version: 2.40.0 + resolution: "@microsoft/microsoft-graph-types@npm:2.40.0" + checksum: 3892e910baf4fcf2d1bcee4c71683e3707818be6ff1b4b9dbc29b9e2eab942ea0b171b3023d4620213f10d93d03611e6615706a3d1af4ca44028491a0544ccaf languageName: node linkType: hard @@ -13660,6 +13232,13 @@ __metadata: languageName: node linkType: hard +"@mswjs/cookies@npm:^1.1.0": + version: 1.1.0 + resolution: "@mswjs/cookies@npm:1.1.0" + checksum: 1d9be44548907b92ff6acd46795292968661be19f1c04c43fdb2beb98bc7e58b8ffcef3be19d0f2cb58df07a36a6b53b4bbc0ea34e023b7366dbc28ffee90338 + languageName: node + linkType: hard + "@mswjs/interceptors@npm:^0.17.10": version: 0.17.10 resolution: "@mswjs/interceptors@npm:0.17.10" @@ -13676,14 +13255,28 @@ __metadata: languageName: node linkType: hard -"@mui/base@npm:5.0.0-beta.24": - version: 5.0.0-beta.24 - resolution: "@mui/base@npm:5.0.0-beta.24" +"@mswjs/interceptors@npm:^0.25.11": + version: 0.25.12 + resolution: "@mswjs/interceptors@npm:0.25.12" dependencies: - "@babel/runtime": ^7.23.2 + "@open-draft/deferred-promise": ^2.2.0 + "@open-draft/logger": ^0.3.0 + "@open-draft/until": ^2.0.0 + is-node-process: ^1.2.0 + outvariant: ^1.2.1 + strict-event-emitter: ^0.5.1 + checksum: 0676808700059f55536b51ffe38e9ea07e26b4d9c284fbbdf7a52b7282b7a93703f18d93b109c384205fe5f72b585506d5550cc8f3559267892b01a0f7561d3d + languageName: node + linkType: hard + +"@mui/base@npm:5.0.0-beta.25": + version: 5.0.0-beta.25 + resolution: "@mui/base@npm:5.0.0-beta.25" + dependencies: + "@babel/runtime": ^7.23.4 "@floating-ui/react-dom": ^2.0.4 - "@mui/types": ^7.2.9 - "@mui/utils": ^5.14.18 + "@mui/types": ^7.2.10 + "@mui/utils": ^5.14.19 "@popperjs/core": ^2.11.8 clsx: ^2.0.0 prop-types: ^15.8.1 @@ -13694,28 +13287,28 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: dbd6eb0af7cb89389b1dccd6a84d07128c41f60d297d8f1d484919950c9b45a5d8767042b622c74e311bce0368ee3f760afb34d80ad97af61f5b5650ae990c60 + checksum: ce22c38593db1bbbb162574bd297bc3f2f5040ed6e304965e17aff55e4d15782e813196bd67c9b82757ee67675ad6d557e22541f84e4d7a4b6f3349dc83741f3 languageName: node linkType: hard -"@mui/core-downloads-tracker@npm:^5.14.18": - version: 5.14.18 - resolution: "@mui/core-downloads-tracker@npm:5.14.18" - checksum: 3d367797282e4b93eacee997667d62bc4eeac979e9664724e9db8d632278d8629f2a141894cf53d706f1d2a9f19965bffe2858aa2bc9833722e674cd560b896e +"@mui/core-downloads-tracker@npm:^5.14.19": + version: 5.14.19 + resolution: "@mui/core-downloads-tracker@npm:5.14.19" + checksum: e71c886f12bbd83791638545017c0b8439c3c6b51125979fea105f938f2f5b109629d4deddd38448c05b8be10b3249334324f1505c1306c52a2b8d315a1005c3 languageName: node linkType: hard "@mui/material@npm:^5.12.2": - version: 5.14.18 - resolution: "@mui/material@npm:5.14.18" + version: 5.14.19 + resolution: "@mui/material@npm:5.14.19" dependencies: - "@babel/runtime": ^7.23.2 - "@mui/base": 5.0.0-beta.24 - "@mui/core-downloads-tracker": ^5.14.18 - "@mui/system": ^5.14.18 - "@mui/types": ^7.2.9 - "@mui/utils": ^5.14.18 - "@types/react-transition-group": ^4.4.8 + "@babel/runtime": ^7.23.4 + "@mui/base": 5.0.0-beta.25 + "@mui/core-downloads-tracker": ^5.14.19 + "@mui/system": ^5.14.19 + "@mui/types": ^7.2.10 + "@mui/utils": ^5.14.19 + "@types/react-transition-group": ^4.4.9 clsx: ^2.0.0 csstype: ^3.1.2 prop-types: ^15.8.1 @@ -13734,16 +13327,16 @@ __metadata: optional: true "@types/react": optional: true - checksum: 488322f09638a71bb5d4bb5c027dde69d5cf89bcfd433594e3b90fea9fefa302bc85b9d2bf386493bf68d360107b59c6d148f46a68477e7f472f4f2d14d698a3 + checksum: 8fc63b7ecb98c5eb8f67190cde096f83100af9271fe2113e1d3edb13a08650f611e7ff186b04c66695958cc88480011ab31dc950cf0fd6e0fbb6c727ec834cbd languageName: node linkType: hard -"@mui/private-theming@npm:^5.14.18": - version: 5.14.18 - resolution: "@mui/private-theming@npm:5.14.18" +"@mui/private-theming@npm:^5.14.19": + version: 5.14.19 + resolution: "@mui/private-theming@npm:5.14.19" dependencies: - "@babel/runtime": ^7.23.2 - "@mui/utils": ^5.14.18 + "@babel/runtime": ^7.23.4 + "@mui/utils": ^5.14.19 prop-types: ^15.8.1 peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 @@ -13751,15 +13344,15 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: e7ba8e945f589db16ed05d507b0821d2e07b3d760bf78c9f745a75d75b5a94d1e546278629de15b090de289a9244591bfa2c09bb9f9f8679fb4e1d8cec360833 + checksum: ee17fa123ae671fcfb6e59787e9a5b6d650d4a53ea575f5d5519dd187c9b04fbb50f12f2da5a663d3ba3a82d503086faa18bf3b68923237de78f44e401e04935 languageName: node linkType: hard -"@mui/styled-engine@npm:^5.14.18": - version: 5.14.18 - resolution: "@mui/styled-engine@npm:5.14.18" +"@mui/styled-engine@npm:^5.14.19": + version: 5.14.19 + resolution: "@mui/styled-engine@npm:5.14.19" dependencies: - "@babel/runtime": ^7.23.2 + "@babel/runtime": ^7.23.4 "@emotion/cache": ^11.11.0 csstype: ^3.1.2 prop-types: ^15.8.1 @@ -13772,19 +13365,50 @@ __metadata: optional: true "@emotion/styled": optional: true - checksum: 6eba307d95ef462f8b80aaa50ec1db7409d19cead985eba28e86aec066ad4bc70b0daa6d89158a7aae88ea43d614cace5f890cbebe0d8636573e894b7da9cae1 + checksum: 2b8dc8e08e47e18ad6345d25539d5978ef153cb23abff3d98c3cf2795f836e446279021392c2071142ffbae17e19906235acfb3e73dc0f14440b138f919a26a4 languageName: node linkType: hard -"@mui/system@npm:^5.14.18": - version: 5.14.18 - resolution: "@mui/system@npm:5.14.18" +"@mui/styles@npm:^5.14.18": + version: 5.14.19 + resolution: "@mui/styles@npm:5.14.19" dependencies: - "@babel/runtime": ^7.23.2 - "@mui/private-theming": ^5.14.18 - "@mui/styled-engine": ^5.14.18 - "@mui/types": ^7.2.9 - "@mui/utils": ^5.14.18 + "@babel/runtime": ^7.23.4 + "@emotion/hash": ^0.9.1 + "@mui/private-theming": ^5.14.19 + "@mui/types": ^7.2.10 + "@mui/utils": ^5.14.19 + clsx: ^2.0.0 + csstype: ^3.1.2 + hoist-non-react-statics: ^3.3.2 + jss: ^10.10.0 + jss-plugin-camel-case: ^10.10.0 + jss-plugin-default-unit: ^10.10.0 + jss-plugin-global: ^10.10.0 + jss-plugin-nested: ^10.10.0 + jss-plugin-props-sort: ^10.10.0 + jss-plugin-rule-value-function: ^10.10.0 + jss-plugin-vendor-prefixer: ^10.10.0 + prop-types: ^15.8.1 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 03780cba63ee5dca4bd3f81aa8634039e6a18291eb2f89cdcee236669e4b05a2593a3e5e74c21378950cc34a790163d2d3b80d2b649fd368a5b09439f198489e + languageName: node + linkType: hard + +"@mui/system@npm:^5.14.19": + version: 5.14.19 + resolution: "@mui/system@npm:5.14.19" + dependencies: + "@babel/runtime": ^7.23.4 + "@mui/private-theming": ^5.14.19 + "@mui/styled-engine": ^5.14.19 + "@mui/types": ^7.2.10 + "@mui/utils": ^5.14.19 clsx: ^2.0.0 csstype: ^3.1.2 prop-types: ^15.8.1 @@ -13800,28 +13424,28 @@ __metadata: optional: true "@types/react": optional: true - checksum: 8f7c4f3555ee64467826e1a40cfdb34b5c02520fd9f27779b8e6aa97cb9bbd27d98386a194d2e4c44b148babe5f67e3a715f8a09c03a1d71f2f14ddf60045174 + checksum: aea4935cf72a7c4fe3d03eb040491204b0c20fbae19fc73173ec925c9025375601f6b7007e53b5ab6ea44a4dd74b94e9acc9ada85461db1deae9062f8506a99a languageName: node linkType: hard -"@mui/types@npm:^7.2.9": - version: 7.2.9 - resolution: "@mui/types@npm:7.2.9" +"@mui/types@npm:^7.2.10": + version: 7.2.10 + resolution: "@mui/types@npm:7.2.10" peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: 4888a1cf9a1adbae1c2f53ba9f8a0cf23eb5e0954bca00b958c240c87b5287771cb5e99bedb61a2c04f5dcbdef13a5b1f238153e98d8959ba51c5470db2c4b32 + checksum: b9c4629929450e243015d79cf6b102824336db07b852e55f114aca85dbad0b39f831e9c65ad94b028a65c08d33be9f7de1afb530a4e6a80be5702b396ccb90b1 languageName: node linkType: hard -"@mui/utils@npm:^5.14.15, @mui/utils@npm:^5.14.18": - version: 5.14.18 - resolution: "@mui/utils@npm:5.14.18" +"@mui/utils@npm:^5.14.15, @mui/utils@npm:^5.14.19": + version: 5.14.19 + resolution: "@mui/utils@npm:5.14.19" dependencies: - "@babel/runtime": ^7.23.2 - "@types/prop-types": ^15.7.10 + "@babel/runtime": ^7.23.4 + "@types/prop-types": ^15.7.11 prop-types: ^15.8.1 react-is: ^18.2.0 peerDependencies: @@ -13830,7 +13454,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: f24badcb6b026b392b94919f65c7f3bea6cfb0f741c1b8ebd74b02bba9ffc61f72e35bdea887e47dfd97d37ff465863aa29c7c5cfd33fb83224f4ff2300432b3 + checksum: f53f746eb33bc5d700b9f2b454e211ca17f5aa320cd30f54a82a347e4da0c61b872f323f01ff4b5247d3f992ac4f72a69ac79974300a6dedf01ff6b8f6d75b49 languageName: node linkType: hard @@ -13907,14 +13531,14 @@ __metadata: linkType: hard "@newrelic/browser-agent@npm:^1.236.0": - version: 1.247.0 - resolution: "@newrelic/browser-agent@npm:1.247.0" + version: 1.248.0 + resolution: "@newrelic/browser-agent@npm:1.248.0" dependencies: core-js: ^3.26.0 fflate: ^0.7.4 rrweb: 2.0.0-alpha.11 web-vitals: ^3.1.0 - checksum: 5920119c784394637222b9547d4f758bff1e006a0e30411beae7a747c16f18cf39be7389d0f12b3e23168f9aa16ac6c3bd9d2063f673d6e0f0aef7af58ef61ed + checksum: 0db9d85304e687f6d0e0be89306d26ab99469475ecb8107e224d9757da98627d67c5a652d65782092aa543738976bcb0ae701c92a7fcac7b2ef72c283342cba5 languageName: node linkType: hard @@ -14577,6 +14201,23 @@ __metadata: languageName: node linkType: hard +"@open-draft/deferred-promise@npm:^2.2.0": + version: 2.2.0 + resolution: "@open-draft/deferred-promise@npm:2.2.0" + checksum: 7f29d39725bb8ab5b62f89d88a4202ce2439ac740860979f9e3d0015dfe4bc3daddcfa5727fa4eed482fdbee770aa591b1136b98b0a0f0569a65294f35bdf56a + languageName: node + linkType: hard + +"@open-draft/logger@npm:^0.3.0": + version: 0.3.0 + resolution: "@open-draft/logger@npm:0.3.0" + dependencies: + is-node-process: ^1.2.0 + outvariant: ^1.4.0 + checksum: 7adfe3d0ed8ca32333ce2a77f9a93d561ebc89c989eaa9722f1dc8a2d2854f5de1bef6fa6894cdf58e16fa4dd9cfa99444ea1f5cac6eb1518e9247911ed042d5 + languageName: node + linkType: hard + "@open-draft/until@npm:^1.0.3": version: 1.0.3 resolution: "@open-draft/until@npm:1.0.3" @@ -14584,17 +14225,23 @@ __metadata: languageName: node linkType: hard -"@openapi-contrib/openapi-schema-to-json-schema@npm:^3.0.0": - version: 3.0.3 - resolution: "@openapi-contrib/openapi-schema-to-json-schema@npm:3.0.3" - dependencies: - fast-deep-equal: ^3.1.3 - lodash.clonedeep: ^4.5.0 - checksum: 2296925669a4a78548f8ba055fbfc1f292274572ecb082d1465b6a6255799f43f0538880009bf4010b2fa9e7c84e97f8aa04d22b330fd469677c594ed98df314 +"@open-draft/until@npm:^2.0.0, @open-draft/until@npm:^2.1.0": + version: 2.1.0 + resolution: "@open-draft/until@npm:2.1.0" + checksum: 140ea3b16f4a3a6a729c1256050e20a93d408d7aa1e125648ce2665b3c526ed452510c6e4a6f4b15d95fb5e41203fb51510eb8fbc8812d5e5a91880293d66471 languageName: node linkType: hard -"@openapitools/openapi-generator-cli@npm:^2.4.26": +"@openapi-contrib/openapi-schema-to-json-schema@npm:~3.2.0": + version: 3.2.0 + resolution: "@openapi-contrib/openapi-schema-to-json-schema@npm:3.2.0" + dependencies: + fast-deep-equal: ^3.1.3 + checksum: c47cbf85bee3e38e06a627efbbdffd78c95cdadebf6d935092c8ff616e31a69fcfd739a5d9cca5b4b2c6aef49f8dbced6c300eac1f8ade66b3fab403df19ccb2 + languageName: node + linkType: hard + +"@openapitools/openapi-generator-cli@npm:^2.4.26, @openapitools/openapi-generator-cli@npm:^2.7.0": version: 2.7.0 resolution: "@openapitools/openapi-generator-cli@npm:2.7.0" dependencies: @@ -14720,52 +14367,6 @@ __metadata: languageName: node linkType: hard -"@parcel/watcher@npm:^2.1.0": - version: 2.1.0 - resolution: "@parcel/watcher@npm:2.1.0" - dependencies: - is-glob: ^4.0.3 - micromatch: ^4.0.5 - node-addon-api: ^3.2.1 - node-gyp: latest - node-gyp-build: ^4.3.0 - checksum: 17f512ad6d5dbb40053ceea7091f8af754afc63786b8f050b225b89a8ba24900468aad8bc4edb25c0349b4c0c8d061f50aa19242c0af52cbc30e6ebf50c7bf4c - languageName: node - linkType: hard - -"@peculiar/asn1-schema@npm:^2.1.6": - version: 2.2.0 - resolution: "@peculiar/asn1-schema@npm:2.2.0" - dependencies: - asn1js: ^3.0.5 - pvtsutils: ^1.3.2 - tslib: ^2.4.0 - checksum: 83c8b4e82d8f829ece3ad1aa96d4e2f0c5f16a5255bb066a1174bd020b031d456469d82786a561e5758af0e56d0391ae5e8c6b3657e73d438f49998ff3cf471f - languageName: node - linkType: hard - -"@peculiar/json-schema@npm:^1.1.12": - version: 1.1.12 - resolution: "@peculiar/json-schema@npm:1.1.12" - dependencies: - tslib: ^2.0.0 - checksum: b26ececdc23c5ef25837f8be8d1eb5e1c8bb6e9ae7227ac59ffea57fff56bd05137734e7685e9100595d3d88d906dff638ef8d1df54264c388d3eac1b05aa060 - languageName: node - linkType: hard - -"@peculiar/webcrypto@npm:^1.4.0": - version: 1.4.0 - resolution: "@peculiar/webcrypto@npm:1.4.0" - dependencies: - "@peculiar/asn1-schema": ^2.1.6 - "@peculiar/json-schema": ^1.1.12 - pvtsutils: ^1.3.2 - tslib: ^2.4.0 - webcrypto-core: ^1.7.4 - checksum: 3a7a3c8f253170436f353a61b807d2e2e7a686e6a9607487fde6459ddfff34c8000414287a6cd904bd81e002ce4564811b3c7789a0fd932cf015df6c4002fd02 - languageName: node - linkType: hard - "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -14774,13 +14375,13 @@ __metadata: linkType: hard "@playwright/test@npm:^1.32.3": - version: 1.39.0 - resolution: "@playwright/test@npm:1.39.0" + version: 1.40.1 + resolution: "@playwright/test@npm:1.40.1" dependencies: - playwright: 1.39.0 + playwright: 1.40.1 bin: playwright: cli.js - checksum: e93e58fc1af4239f239b890374f066c9a758e2492d25e2c1a532f3f00782ab8e7706956a07540fd14882c74e75f5de36273621adce9b79afb8e36e6c15f1d539 + checksum: ae094e6cb809365c0707ee2b184e42d2a2542569ada020d2d44ca5866066941262bd9a67af185f86c2fb0133c9b712ea8cb73e2959a289e4261c5fd17077283c languageName: node linkType: hard @@ -15500,10 +15101,10 @@ __metadata: languageName: node linkType: hard -"@remix-run/router@npm:1.11.0": - version: 1.11.0 - resolution: "@remix-run/router@npm:1.11.0" - checksum: 1966436ab3ab982862195e4871790644ce21e01511aa3f4350436296224e4dec2e6ee35f1f4cb83db69f7aa0e8ad4a0a01928b05359ae654edc8e2aa82bf754b +"@remix-run/router@npm:1.13.1": + version: 1.13.1 + resolution: "@remix-run/router@npm:1.13.1" + checksum: cebbf0a8cf31cafd818d8ce42d5b6a0bfdd0e1f81b9ffb7a88c5d7a9d2a81d1fdf098cc8610d34ef3d6cfe7bc778b2ca1fe336a740eb7a175d1234d017927f8a languageName: node linkType: hard @@ -15514,16 +15115,16 @@ __metadata: languageName: node linkType: hard -"@repeaterjs/repeater@npm:3.0.4, @repeaterjs/repeater@npm:^3.0.4": - version: 3.0.4 - resolution: "@repeaterjs/repeater@npm:3.0.4" - checksum: cca0db3e802bc26fcce0b4a574074d9956da53bf43094de03c0e4732d05e13441279a92f0b96e2a7a39da50933684947a138c1213406eaafe39cfd4683d6c0df +"@repeaterjs/repeater@npm:^3.0.4": + version: 3.0.5 + resolution: "@repeaterjs/repeater@npm:3.0.5" + checksum: 4f66020679a2e7a93fbd43d40a7ae6a187d6d7d148b019cca025791dade452599848bd20cd225861a65629571806c551a18cd40190426eb74b050710ac3ae865 languageName: node linkType: hard -"@rjsf/core@npm:5.13.6": - version: 5.13.6 - resolution: "@rjsf/core@npm:5.13.6" +"@rjsf/core@npm:5.14.3": + version: 5.14.3 + resolution: "@rjsf/core@npm:5.14.3" dependencies: lodash: ^4.17.21 lodash-es: ^4.17.21 @@ -15533,20 +15134,20 @@ __metadata: peerDependencies: "@rjsf/utils": ^5.12.x react: ^16.14.0 || >=17 - checksum: 7c8782030ac661fccd36226d84bca701af8e42717cb0560fb606784d358b1724288275f7ec2f9905b2a006ab65aa51525176d180908c6817b432afff4e989bdb + checksum: 9929ae7b99f1c79dc108095c3338a30fe373cd0fc6c613f65d163f7729cda2509070bb7da581ce3ad068a41ea5050f4e8417508c12e53feb41c56119082d3aac languageName: node linkType: hard -"@rjsf/material-ui@npm:5.13.6": - version: 5.13.6 - resolution: "@rjsf/material-ui@npm:5.13.6" +"@rjsf/material-ui@npm:5.14.3": + version: 5.14.3 + resolution: "@rjsf/material-ui@npm:5.14.3" peerDependencies: "@material-ui/core": ^4.12.3 "@material-ui/icons": ^4.11.2 "@rjsf/core": ^5.12.x "@rjsf/utils": ^5.12.x react: ^16.14.0 || >=17 - checksum: 4c7646c96f57576700dd4f62c2c58c7f93c5dcee1db0ca77a3594efc39084ad94e24241d93b3e8fb0d9136c226f9c56c9ab9af78a1972fc088de3f109fa84050 + checksum: fa9b9a831fa333bb794ccde85f415c8daf18334d975a0f2aa1cd497017e7a03c398d5b4f4209eafd4aed4aa476578ef82e95cf544c5542ee030b080226f09388 languageName: node linkType: hard @@ -15565,9 +15166,24 @@ __metadata: languageName: node linkType: hard -"@rjsf/validator-ajv8@npm:5.13.6": - version: 5.13.6 - resolution: "@rjsf/validator-ajv8@npm:5.13.6" +"@rjsf/utils@npm:5.14.3": + version: 5.14.3 + resolution: "@rjsf/utils@npm:5.14.3" + dependencies: + json-schema-merge-allof: ^0.8.1 + jsonpointer: ^5.0.1 + lodash: ^4.17.21 + lodash-es: ^4.17.21 + react-is: ^18.2.0 + peerDependencies: + react: ^16.14.0 || >=17 + checksum: 759f85e1d205d360024e569ab04c57543cbec4af8293636ba0af0ec7797bdcb361cd0b33c176ede464f101b33eb4240b60e241537ba19edefc04b91b80e6051e + languageName: node + linkType: hard + +"@rjsf/validator-ajv8@npm:5.14.3": + version: 5.14.3 + resolution: "@rjsf/validator-ajv8@npm:5.14.3" dependencies: ajv: ^8.12.0 ajv-formats: ^2.1.1 @@ -15575,19 +15191,19 @@ __metadata: lodash-es: ^4.17.21 peerDependencies: "@rjsf/utils": ^5.12.x - checksum: 1909cb6b23344dd32b6bc825cc49c5a0efef2aecda2df5a903c3e70449b0ee546d9d915c450bdebd89384490689e43584933b74c3d4439c624b4cd9e481c7c1d + checksum: 8b7caa0d5a81ecffaee1a538625c93ff8fdf860d67b80e75901df62112d00479bed6987c25427b84957b4e483c80c80d91713922bdb21ae8dd440242f0e8f5e3 languageName: node linkType: hard "@roadiehq/backstage-plugin-buildkite@npm:^2.0.8": - version: 2.1.16 - resolution: "@roadiehq/backstage-plugin-buildkite@npm:2.1.16" + version: 2.1.17 + resolution: "@roadiehq/backstage-plugin-buildkite@npm:2.1.17" dependencies: "@backstage/catalog-model": ^1.4.3 - "@backstage/core-components": ^0.13.7 - "@backstage/core-plugin-api": ^1.7.0 - "@backstage/plugin-catalog-react": ^1.8.5 - "@backstage/theme": ^0.4.3 + "@backstage/core-components": ^0.13.8 + "@backstage/core-plugin-api": ^1.8.0 + "@backstage/plugin-catalog-react": ^1.9.1 + "@backstage/theme": ^0.4.4 "@material-ui/core": ^4.12.1 "@material-ui/icons": ^4.11.2 "@material-ui/lab": 4.0.0-alpha.57 @@ -15599,20 +15215,20 @@ __metadata: react-dom: ^16.13.1 || ^17.0.0 react-router: 6.0.0-beta.0 || ^6.3.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 716755abfc85c452382ca1535d819a7ebb9a52d024557c51d240df7193a15b98567dad5fe0dcbbf72df0b27f773f1be0f25a5e876024f3a1f03c0eff99fc7a2c + checksum: 218a614d81ee89b2a1613979258788d612c675da2af7ffdcecaa6e47206d6aa4f463defc376f5c4a53ba2136038d0e0659ba80182bd8001c144323e40f3ff5ab languageName: node linkType: hard "@roadiehq/backstage-plugin-github-insights@npm:^2.0.5": - version: 2.3.22 - resolution: "@roadiehq/backstage-plugin-github-insights@npm:2.3.22" + version: 2.3.23 + resolution: "@roadiehq/backstage-plugin-github-insights@npm:2.3.23" dependencies: "@backstage/catalog-model": ^1.4.3 - "@backstage/core-components": ^0.13.7 - "@backstage/core-plugin-api": ^1.7.0 - "@backstage/integration-react": ^1.1.20 - "@backstage/plugin-catalog-react": ^1.8.5 - "@backstage/theme": ^0.4.3 + "@backstage/core-components": ^0.13.8 + "@backstage/core-plugin-api": ^1.8.0 + "@backstage/integration-react": ^1.1.21 + "@backstage/plugin-catalog-react": ^1.9.1 + "@backstage/theme": ^0.4.4 "@date-io/core": 2.10.7 "@material-ui/core": ^4.11.0 "@material-ui/icons": ^4.9.1 @@ -15627,19 +15243,19 @@ __metadata: react: ^16.13.1 || ^17.0.0 react-dom: ^16.13.1 || ^17.0.0 react-router: 6.0.0-beta.0 || ^6.3.0 - checksum: 1bdfa2dc1fca12f5a47a11a2df54a774992c1a91d294e646b70f1a197575b96c34da78356d230d0a65695348a1caef6ab62f2553e7e75a01504e58407108135a + checksum: 07dd3df1d8f99ea6f2910d343c361bd27b249fbd1e982fc42630ddc8e530901ef42e9a3cf5a944c80abd0c5be25cca716c12a838057ec1e83ad538a9462033e4 languageName: node linkType: hard "@roadiehq/backstage-plugin-github-pull-requests@npm:^2.2.7": - version: 2.5.19 - resolution: "@roadiehq/backstage-plugin-github-pull-requests@npm:2.5.19" + version: 2.5.20 + resolution: "@roadiehq/backstage-plugin-github-pull-requests@npm:2.5.20" dependencies: "@backstage/catalog-model": ^1.4.3 - "@backstage/core-components": ^0.13.7 - "@backstage/core-plugin-api": ^1.7.0 - "@backstage/plugin-catalog-react": ^1.8.5 - "@backstage/plugin-home-react": ^0.1.4 + "@backstage/core-components": ^0.13.8 + "@backstage/core-plugin-api": ^1.8.0 + "@backstage/plugin-catalog-react": ^1.9.1 + "@backstage/plugin-home-react": ^0.1.5 "@material-ui/core": ^4.11.0 "@material-ui/icons": ^4.9.1 "@material-ui/lab": ^4.0.0-alpha.60 @@ -15656,19 +15272,19 @@ __metadata: react: ^16.13.1 || ^17.0.0 react-dom: ^16.13.1 || ^17.0.0 react-router: 6.0.0-beta.0 || ^6.3.0 - checksum: 35d760d22626d6d76438db66e36610aff8f1b171ae4d60944edcd631427b55f2a0489339db761764d2d406c5d3480ec8786db16ffb803d28eb96544b8c8e75a7 + checksum: f9ac5bbff5173eff98002f3f8bd7b7fe349723039481651b1e81b7aa5bbaaa799f4cd51d5425a5d74cebf3d0f5bb7340a0c4091b858addc45791881c3802f7a7 languageName: node linkType: hard "@roadiehq/backstage-plugin-travis-ci@npm:^2.0.5": - version: 2.1.16 - resolution: "@roadiehq/backstage-plugin-travis-ci@npm:2.1.16" + version: 2.1.17 + resolution: "@roadiehq/backstage-plugin-travis-ci@npm:2.1.17" dependencies: "@backstage/catalog-model": ^1.4.3 - "@backstage/core-components": ^0.13.7 - "@backstage/core-plugin-api": ^1.7.0 - "@backstage/plugin-catalog-react": ^1.8.5 - "@backstage/theme": ^0.4.3 + "@backstage/core-components": ^0.13.8 + "@backstage/core-plugin-api": ^1.8.0 + "@backstage/plugin-catalog-react": ^1.9.1 + "@backstage/theme": ^0.4.4 "@material-ui/core": ^4.11.3 "@material-ui/icons": ^4.11.2 "@material-ui/lab": 4.0.0-alpha.57 @@ -15682,26 +15298,26 @@ __metadata: react-dom: ^16.13.1 || ^17.0.0 react-router: 6.0.0-beta.0 || ^6.3.0 react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: 175cbae49d6f990cdc0c0d75d27dfe36717f615fea1d4faf350d618bfa4420995c378e3735546ec403ad3c726d18c6ab2bdfc0f72edea26001eb4798e4093305 + checksum: fcf0b788a2f004a6eff181ff9f9babd07aceb630333b1a3e8ce7fb37b6e9a303444ecc9521a920f6aced2c9a081fa3024ee9079d1bb9f453e2d322af04f57113 languageName: node linkType: hard -"@rollup/plugin-commonjs@npm:^23.0.0": - version: 23.0.7 - resolution: "@rollup/plugin-commonjs@npm:23.0.7" +"@rollup/plugin-commonjs@npm:^25.0.0": + version: 25.0.7 + resolution: "@rollup/plugin-commonjs@npm:25.0.7" dependencies: "@rollup/pluginutils": ^5.0.1 commondir: ^1.0.1 estree-walker: ^2.0.2 glob: ^8.0.3 is-reference: 1.2.1 - magic-string: ^0.27.0 + magic-string: ^0.30.3 peerDependencies: - rollup: ^2.68.0||^3.0.0 + rollup: ^2.68.0||^3.0.0||^4.0.0 peerDependenciesMeta: rollup: optional: true - checksum: 01d90947bd4aa664c568cec172399825921f29afc035a6d8aec153868ab151ce7901ad56a101c76655e31b21567ddc70313c4bca476685b872218f041757a8c9 + checksum: 052e11839a9edc556eda5dcc759ab816dcc57e9f0f905a1e6e14fff954eaa6b1e2d0d544f5bd18d863993c5eba43d8ac9c19d9bb53b1c3b1213f32cfc9d50b2e languageName: node linkType: hard @@ -15721,33 +15337,36 @@ __metadata: languageName: node linkType: hard -"@rollup/plugin-json@npm:^5.0.0": - version: 5.0.2 - resolution: "@rollup/plugin-json@npm:5.0.2" +"@rollup/plugin-json@npm:^6.0.0": + version: 6.0.1 + resolution: "@rollup/plugin-json@npm:6.0.1" dependencies: "@rollup/pluginutils": ^5.0.1 peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 peerDependenciesMeta: rollup: optional: true - checksum: 9b5f90ea311dfcfacf0f38af39bbb1954ea56d6faecdee3d528f73d0e02da96a0706ab21fae0c8eef9bb5d756f6f50b40b5a252ffd9800397012b5bac6764b6f + checksum: 86995e3ceec0205bd0b5ae3075f4592e0ab3e6e6327a5dcfc825b44113eaae5819d26d5403d29b177ac59299e0b08c641c8d030e0c72805b92805ededc9cac44 languageName: node linkType: hard -"@rollup/plugin-node-resolve@npm:^13.0.6": - version: 13.3.0 - resolution: "@rollup/plugin-node-resolve@npm:13.3.0" +"@rollup/plugin-node-resolve@npm:^15.0.0": + version: 15.2.3 + resolution: "@rollup/plugin-node-resolve@npm:15.2.3" dependencies: - "@rollup/pluginutils": ^3.1.0 - "@types/resolve": 1.17.1 + "@rollup/pluginutils": ^5.0.1 + "@types/resolve": 1.20.2 deepmerge: ^4.2.2 - is-builtin-module: ^3.1.0 + is-builtin-module: ^3.2.1 is-module: ^1.0.0 - resolve: ^1.19.0 + resolve: ^1.22.1 peerDependencies: - rollup: ^2.42.0 - checksum: ec5418e6b3c23a9e30683056b3010e9d325316dcfae93fbc673ae64dad8e56a2ce761c15c48f5e2dcfe0c822fdc4a4905ee6346e3dcf90603ba2260afef5a5e6 + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 730f32c2f8fdddff07cf0fca86a5dac7c475605fb96930197a868c066e62eb6388c557545e4f7d99b7a283411754c9fbf98944ab086b6074e04fc1292e234aa8 languageName: node linkType: hard @@ -15767,19 +15386,6 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^3.1.0": - version: 3.1.0 - resolution: "@rollup/pluginutils@npm:3.1.0" - dependencies: - "@types/estree": 0.0.39 - estree-walker: ^1.0.1 - picomatch: ^2.2.2 - peerDependencies: - rollup: ^1.20.0||^2.0.0 - checksum: 8be16e27863c219edbb25a4e6ec2fe0e1e451d9e917b6a43cf2ae5bc025a6b8faaa40f82a6e53b66d0de37b58ff472c6c3d57a83037ae635041f8df959d6d9aa - languageName: node - linkType: hard - "@rollup/pluginutils@npm:^4.1.1, @rollup/pluginutils@npm:^4.2.0, @rollup/pluginutils@npm:^4.2.1": version: 4.2.1 resolution: "@rollup/pluginutils@npm:4.2.1" @@ -16049,13 +15655,13 @@ __metadata: languageName: node linkType: hard -"@smithy/abort-controller@npm:^2.0.1, @smithy/abort-controller@npm:^2.0.13": - version: 2.0.13 - resolution: "@smithy/abort-controller@npm:2.0.13" +"@smithy/abort-controller@npm:^2.0.1, @smithy/abort-controller@npm:^2.0.13, @smithy/abort-controller@npm:^2.0.14": + version: 2.0.14 + resolution: "@smithy/abort-controller@npm:2.0.14" dependencies: - "@smithy/types": ^2.5.0 + "@smithy/types": ^2.6.0 tslib: ^2.5.0 - checksum: 6f62555669d7fec47427343b82b135cf5a87613a7479e32e6324e9090a7b4e2b3da1be0a916848478062841e619c48ba5f71f5ba8ce9be73115cb293776aa9aa + checksum: f89c7b0523fcb4df7dd7057d15a6deff9aa0b9ac5fe816a2f1331353d3874cf8d3e9b2280a1daa903c32be0fe280ef034a2222f6e62f733fc7dc40be3b1cbe38 languageName: node linkType: hard @@ -16312,15 +15918,15 @@ __metadata: linkType: hard "@smithy/node-http-handler@npm:^2.1.7, @smithy/node-http-handler@npm:^2.1.9": - version: 2.1.9 - resolution: "@smithy/node-http-handler@npm:2.1.9" + version: 2.1.10 + resolution: "@smithy/node-http-handler@npm:2.1.10" dependencies: - "@smithy/abort-controller": ^2.0.13 - "@smithy/protocol-http": ^3.0.9 - "@smithy/querystring-builder": ^2.0.13 - "@smithy/types": ^2.5.0 + "@smithy/abort-controller": ^2.0.14 + "@smithy/protocol-http": ^3.0.10 + "@smithy/querystring-builder": ^2.0.14 + "@smithy/types": ^2.6.0 tslib: ^2.5.0 - checksum: 43f85155bcf08cfe2d2ca91decae932def73e41925151d4c5e039db5c2f3cd9ab0fcf04b05958e8861d1a0df7d4f9667e4434800db3408024c23832a2395d148 + checksum: b24a3d2ebf87458f92274ba099af05a1a8d933d8df3767ab5d3baf273890c1cfd4be291b06b5323e5119898ba07e88a1f257b8970f7e75fc8944b7071090fa55 languageName: node linkType: hard @@ -16334,24 +15940,24 @@ __metadata: languageName: node linkType: hard -"@smithy/protocol-http@npm:^3.0.9": - version: 3.0.9 - resolution: "@smithy/protocol-http@npm:3.0.9" +"@smithy/protocol-http@npm:^3.0.10, @smithy/protocol-http@npm:^3.0.9": + version: 3.0.10 + resolution: "@smithy/protocol-http@npm:3.0.10" dependencies: - "@smithy/types": ^2.5.0 + "@smithy/types": ^2.6.0 tslib: ^2.5.0 - checksum: d10f57da9c60f1b0806ae10b0482ee97b227b76151c55daebc57c7dab55dbee2329b3f36d6d7811b547994b8c2db5dddff0aedead9eede459856b5bc5b104723 + checksum: 77bda5c76e00e0fee6a0654d10a0127287402484522dcdcb0eda84a6be196304301a68d263ba27639fb288dbcbb891bfa3efa50a24ea9a9878915a0e1ddc8620 languageName: node linkType: hard -"@smithy/querystring-builder@npm:^2.0.13": - version: 2.0.13 - resolution: "@smithy/querystring-builder@npm:2.0.13" +"@smithy/querystring-builder@npm:^2.0.13, @smithy/querystring-builder@npm:^2.0.14": + version: 2.0.14 + resolution: "@smithy/querystring-builder@npm:2.0.14" dependencies: - "@smithy/types": ^2.5.0 + "@smithy/types": ^2.6.0 "@smithy/util-uri-escape": ^2.0.0 tslib: ^2.5.0 - checksum: 453cdd8b28b310bd9d591f54e884c68b2215c03684aa7b8ae9844e57709e3f22c5ee5abc6441d8446023a7c4197232b7b7aa6fa7068af9f2654491a9a7c35ce6 + checksum: e1287709055abd016b214e4cede9d976a63aa73aff8f3092db60a0fe7e103f7a1294bdedf39a7bbea4b2bf1b959682cbcf8e078ca0489a8a58b8b5706679b55d languageName: node linkType: hard @@ -16421,12 +16027,12 @@ __metadata: languageName: node linkType: hard -"@smithy/types@npm:^2.0.2, @smithy/types@npm:^2.5.0": - version: 2.5.0 - resolution: "@smithy/types@npm:2.5.0" +"@smithy/types@npm:^2.0.2, @smithy/types@npm:^2.5.0, @smithy/types@npm:^2.6.0": + version: 2.6.0 + resolution: "@smithy/types@npm:2.6.0" dependencies: tslib: ^2.5.0 - checksum: 9e03dcf6c9ae7239218ccecae0a04d5f0aaab42e17a326590becfd68f1b15ba1291ed408501efab4a20a0542d995b5a859ab58ca83cd4f3e2dbf430785e207a6 + checksum: 9233d1e6e414a8b807f9fe7a7c30064626f77b0242d8634b9b1c192f77b27a997a3caf90ecf7f4361d5926c9e9cc761991eecfb47bbfa6ce2be21c5533a3bea6 languageName: node linkType: hard @@ -16666,7 +16272,7 @@ __metadata: languageName: node linkType: hard -"@stoplight/json-ref-readers@npm:1.2.2": +"@stoplight/json-ref-readers@npm:1.2.2, @stoplight/json-ref-readers@npm:^1.2.2": version: 1.2.2 resolution: "@stoplight/json-ref-readers@npm:1.2.2" dependencies: @@ -16676,11 +16282,11 @@ __metadata: languageName: node linkType: hard -"@stoplight/json-ref-resolver@npm:~3.1.5": - version: 3.1.5 - resolution: "@stoplight/json-ref-resolver@npm:3.1.5" +"@stoplight/json-ref-resolver@npm:^3.1.5, @stoplight/json-ref-resolver@npm:~3.1.6": + version: 3.1.6 + resolution: "@stoplight/json-ref-resolver@npm:3.1.6" dependencies: - "@stoplight/json": ^3.17.0 + "@stoplight/json": ^3.21.0 "@stoplight/path": ^1.3.2 "@stoplight/types": ^12.3.0 || ^13.0.0 "@types/urijs": ^1.19.19 @@ -16688,13 +16294,13 @@ __metadata: fast-memoize: ^2.5.2 immer: ^9.0.6 lodash: ^4.17.21 - tslib: ^2.3.1 + tslib: ^2.6.0 urijs: ^1.19.11 - checksum: b2df82e899717ffa7bab9ec4c380f206511b3971d242724afd34e8b964e5aa7be2a52e32ba48d435548a9ac13a63a2271ca69182abec8506fc3bb3cc129f6380 + checksum: 57c944cc8cee51b18fd8165aae7431eddf3b6ca96f2de7a264d890f18a869e5abb7750d48a77455ee1c688ac440efa4115bc8e912efce7c83140834bae49879e languageName: node linkType: hard -"@stoplight/json@npm:^3.17.0, @stoplight/json@npm:^3.17.1, @stoplight/json@npm:~3.21.0": +"@stoplight/json@npm:^3.17.0, @stoplight/json@npm:^3.17.1, @stoplight/json@npm:^3.20.2, @stoplight/json@npm:^3.21.0, @stoplight/json@npm:~3.21.0": version: 3.21.0 resolution: "@stoplight/json@npm:3.21.0" dependencies: @@ -16722,7 +16328,7 @@ __metadata: languageName: node linkType: hard -"@stoplight/spectral-core@npm:^1.15.1, @stoplight/spectral-core@npm:^1.18.0, @stoplight/spectral-core@npm:^1.7.0, @stoplight/spectral-core@npm:^1.8.0, @stoplight/spectral-core@npm:^1.8.1": +"@stoplight/spectral-core@npm:^1.15.1, @stoplight/spectral-core@npm:^1.16.1, @stoplight/spectral-core@npm:^1.18.0, @stoplight/spectral-core@npm:^1.7.0, @stoplight/spectral-core@npm:^1.8.0, @stoplight/spectral-core@npm:^1.8.1": version: 1.18.3 resolution: "@stoplight/spectral-core@npm:1.18.3" dependencies: @@ -16813,16 +16419,16 @@ __metadata: languageName: node linkType: hard -"@stoplight/spectral-ref-resolver@npm:^1.0.0": - version: 1.0.3 - resolution: "@stoplight/spectral-ref-resolver@npm:1.0.3" +"@stoplight/spectral-ref-resolver@npm:^1.0.0, @stoplight/spectral-ref-resolver@npm:^1.0.3": + version: 1.0.4 + resolution: "@stoplight/spectral-ref-resolver@npm:1.0.4" dependencies: "@stoplight/json-ref-readers": 1.2.2 - "@stoplight/json-ref-resolver": ~3.1.5 + "@stoplight/json-ref-resolver": ~3.1.6 "@stoplight/spectral-runtime": ^1.1.2 dependency-graph: 0.11.0 tslib: ^2.3.1 - checksum: efe93b1d1d32647b675c221530ecb20c55303dfcd1009efd8e036f6415eb1255fff19781358a74046160516a7b7088b6329885bb507a444c14db32fa23392bc9 + checksum: 1e9b2e211d2724e0bab7d817a5128f7b6cab9f0f5281d07223ace1d541a51a0eb3901b9f7b02d4b0484df1cb2a3f7239ec33a974321438d3d08ce7996fd6fcc4 languageName: node linkType: hard @@ -16873,7 +16479,7 @@ __metadata: languageName: node linkType: hard -"@stoplight/types@npm:^12.3.0 || ^13.0.0, @stoplight/types@npm:^13.0.0, @stoplight/types@npm:^13.14.0, @stoplight/types@npm:^13.15.0, @stoplight/types@npm:^13.6.0": +"@stoplight/types@npm:^12.3.0 || ^13.0.0, @stoplight/types@npm:^13.0.0, @stoplight/types@npm:^13.12.0, @stoplight/types@npm:^13.15.0, @stoplight/types@npm:^13.6.0": version: 13.20.0 resolution: "@stoplight/types@npm:13.20.0" dependencies: @@ -16883,6 +16489,16 @@ __metadata: languageName: node linkType: hard +"@stoplight/types@npm:^14.0.0": + version: 14.0.0 + resolution: "@stoplight/types@npm:14.0.0" + dependencies: + "@types/json-schema": ^7.0.4 + utility-types: ^3.10.0 + checksum: 462fb6c718a2679927421ca1fffb5e31be2d150130e95a2771ffba04f68fc0e0f8ef3d4ae050e63fd4044bc4103e2ea82c98e1f5c7ff192a78914838eb250e5e + languageName: node + linkType: hard + "@stoplight/types@npm:~13.6.0": version: 13.6.0 resolution: "@stoplight/types@npm:13.6.0" @@ -17539,90 +17155,82 @@ __metadata: languageName: node linkType: hard -"@swc/core-darwin-arm64@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-darwin-arm64@npm:1.3.96" +"@swc/core-darwin-arm64@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-darwin-arm64@npm:1.3.100" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@swc/core-darwin-x64@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-darwin-x64@npm:1.3.96" +"@swc/core-darwin-x64@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-darwin-x64@npm:1.3.100" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@swc/core-linux-arm-gnueabihf@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.96" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@swc/core-linux-arm64-gnu@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-arm64-gnu@npm:1.3.96" +"@swc/core-linux-arm64-gnu@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-linux-arm64-gnu@npm:1.3.100" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-arm64-musl@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-arm64-musl@npm:1.3.96" +"@swc/core-linux-arm64-musl@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-linux-arm64-musl@npm:1.3.100" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@swc/core-linux-x64-gnu@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-x64-gnu@npm:1.3.96" +"@swc/core-linux-x64-gnu@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-linux-x64-gnu@npm:1.3.100" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@swc/core-linux-x64-musl@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-linux-x64-musl@npm:1.3.96" +"@swc/core-linux-x64-musl@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-linux-x64-musl@npm:1.3.100" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/core-win32-arm64-msvc@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-win32-arm64-msvc@npm:1.3.96" +"@swc/core-win32-arm64-msvc@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-win32-arm64-msvc@npm:1.3.100" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/core-win32-ia32-msvc@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-win32-ia32-msvc@npm:1.3.96" +"@swc/core-win32-ia32-msvc@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-win32-ia32-msvc@npm:1.3.100" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@swc/core-win32-x64-msvc@npm:1.3.96": - version: 1.3.96 - resolution: "@swc/core-win32-x64-msvc@npm:1.3.96" +"@swc/core-win32-x64-msvc@npm:1.3.100": + version: 1.3.100 + resolution: "@swc/core-win32-x64-msvc@npm:1.3.100" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "@swc/core@npm:^1.3.46": - version: 1.3.96 - resolution: "@swc/core@npm:1.3.96" + version: 1.3.100 + resolution: "@swc/core@npm:1.3.100" dependencies: - "@swc/core-darwin-arm64": 1.3.96 - "@swc/core-darwin-x64": 1.3.96 - "@swc/core-linux-arm-gnueabihf": 1.3.96 - "@swc/core-linux-arm64-gnu": 1.3.96 - "@swc/core-linux-arm64-musl": 1.3.96 - "@swc/core-linux-x64-gnu": 1.3.96 - "@swc/core-linux-x64-musl": 1.3.96 - "@swc/core-win32-arm64-msvc": 1.3.96 - "@swc/core-win32-ia32-msvc": 1.3.96 - "@swc/core-win32-x64-msvc": 1.3.96 + "@swc/core-darwin-arm64": 1.3.100 + "@swc/core-darwin-x64": 1.3.100 + "@swc/core-linux-arm64-gnu": 1.3.100 + "@swc/core-linux-arm64-musl": 1.3.100 + "@swc/core-linux-x64-gnu": 1.3.100 + "@swc/core-linux-x64-musl": 1.3.100 + "@swc/core-win32-arm64-msvc": 1.3.100 + "@swc/core-win32-ia32-msvc": 1.3.100 + "@swc/core-win32-x64-msvc": 1.3.100 "@swc/counter": ^0.1.1 "@swc/types": ^0.1.5 peerDependencies: @@ -17632,8 +17240,6 @@ __metadata: optional: true "@swc/core-darwin-x64": optional: true - "@swc/core-linux-arm-gnueabihf": - optional: true "@swc/core-linux-arm64-gnu": optional: true "@swc/core-linux-arm64-musl": @@ -17651,7 +17257,7 @@ __metadata: peerDependenciesMeta: "@swc/helpers": optional: true - checksum: 41d4a4461b2952aaf8d3be945d373d0f3bd126115ee1aad0f76f2690e2b5635b6ec5bb54a7638deb9afedb1ad6f7d8453468a704e54e5fbb8234dd4a43b80205 + checksum: b68553db388c36b1859f0e8b5231a608277e17ae7fd7a928ea8b448432532176914f84675426d40aa9710617b2e7fb626aaa8358b6b2506b3c43f82db725c41e languageName: node linkType: hard @@ -17785,8 +17391,8 @@ __metadata: linkType: hard "@testing-library/jest-dom@npm:^6.0.0": - version: 6.1.4 - resolution: "@testing-library/jest-dom@npm:6.1.4" + version: 6.1.5 + resolution: "@testing-library/jest-dom@npm:6.1.5" dependencies: "@adobe/css-tools": ^4.3.1 "@babel/runtime": ^7.9.2 @@ -17810,7 +17416,7 @@ __metadata: optional: true vitest: optional: true - checksum: c6bd9469554136a25d94b55ea16736d56b8c5d200526023774dbf35ca35551a721257e6734f1b404bbd07ae0a1950f1912b5be60e113db2ff2ff50af14f7085c + checksum: 67f1433c7eb8649db6676df97d1144cf288e2d94c61e89531c05c587b56f2277454c558c97bcca567d5060ebd39caba5ba01d49dc57b3f005837477a401ad113 languageName: node linkType: hard @@ -17837,8 +17443,8 @@ __metadata: linkType: hard "@testing-library/react@npm:^14.0.0": - version: 14.1.0 - resolution: "@testing-library/react@npm:14.1.0" + version: 14.1.2 + resolution: "@testing-library/react@npm:14.1.2" dependencies: "@babel/runtime": ^7.12.5 "@testing-library/dom": ^9.0.0 @@ -17846,7 +17452,7 @@ __metadata: peerDependencies: react: ^18.0.0 react-dom: ^18.0.0 - checksum: e76681911947f0981a1a72802ea01abeacdc4973c62deaf19c206cb9ff8d23eff5e3888c572303614686f029ee8a2a2dad6d0f0a9fb222944dbd9e0ea573b248 + checksum: 0269903e53412cf96fddb55c8a97a9987a89c3308d71fa1418fe61c47d275445e7044c5387f57cf39b8cda319a41623dbad2cce7a17016aed3a9e85185aac75a languageName: node linkType: hard @@ -17955,7 +17561,7 @@ __metadata: languageName: node linkType: hard -"@types/archiver@npm:^5.1.0, @types/archiver@npm:^5.3.1": +"@types/archiver@npm:^5.3.1": version: 5.3.4 resolution: "@types/archiver@npm:5.3.4" dependencies: @@ -17964,6 +17570,15 @@ __metadata: languageName: node linkType: hard +"@types/archiver@npm:^6.0.0": + version: 6.0.2 + resolution: "@types/archiver@npm:6.0.2" + dependencies: + "@types/readdir-glob": "*" + checksum: 4bef71e5b95863be9880339275ad92c2513dd78d56587653614dc5a74af1d078f5f5926ec996de06e7071a1003e0c2764d0e9d2bb0893a2ffb14ab1718eaf5ca + languageName: node + linkType: hard + "@types/argparse@npm:1.0.38": version: 1.0.38 resolution: "@types/argparse@npm:1.0.38" @@ -17994,16 +17609,16 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.20.3": - version: 7.20.3 - resolution: "@types/babel__core@npm:7.20.3" +"@types/babel__core@npm:^7.1.14, @types/babel__core@npm:^7.20.4": + version: 7.20.4 + resolution: "@types/babel__core@npm:7.20.4" dependencies: "@babel/parser": ^7.20.7 "@babel/types": ^7.20.7 "@types/babel__generator": "*" "@types/babel__template": "*" "@types/babel__traverse": "*" - checksum: 8d14acc14d99b4b8bf36c00da368f6d597bd9ae3344aa7048f83f0f701b0463fa7c7bf2e50c3e4382fdbcfd1e4187b3452a0f0888b0f3ae8fad975591f7bdb94 + checksum: 75ed6072213423d2b827740d68bbf96f5a7050ce8bd842dde0ceec8d352d06e847166bac757df4beba55525b65f8727c0432adeb5cb4f83aa42e155ac555767e languageName: node linkType: hard @@ -18121,11 +17736,11 @@ __metadata: linkType: hard "@types/codemirror@npm:^5.0.0, @types/codemirror@npm:^5.60.8": - version: 5.60.13 - resolution: "@types/codemirror@npm:5.60.13" + version: 5.60.15 + resolution: "@types/codemirror@npm:5.60.15" dependencies: "@types/tern": "*" - checksum: 48d5ca1fa01f1e89f4c5ad4030e3d63780bebc3d3285b1a5beb0dc9038c306879c2fc089e39174b2b4bcd0b37ee858b38c7cc270ce9e5c71dd80dcd85eecc54d + checksum: cfad3f569de48fba3efa44fdfeba77933e231486a52cc80cff7ce6eeeed5b447a5bc2b11e2226bc00ccee332c661e53e35a15cf14eb835f434a6a402d9462f5f languageName: node linkType: hard @@ -18180,11 +17795,11 @@ __metadata: linkType: hard "@types/concat-stream@npm:^2.0.0": - version: 2.0.2 - resolution: "@types/concat-stream@npm:2.0.2" + version: 2.0.3 + resolution: "@types/concat-stream@npm:2.0.3" dependencies: "@types/node": "*" - checksum: 7340b17f073356d4b06e611b343cae5bcb348f40916785705632495807d3c88b110a329e049618eed32e8d605636235604cac3929ba691599f7c7dd56c2a4b21 + checksum: e829fde246528665b31a9b8f64c369ffc66aa2a1337d2bab1d38f4d4145701480af7c67e877dd09a7fa97fcbaa0f3baa816ed1b3e71c3ad430930acd37f4eb1f languageName: node linkType: hard @@ -18238,11 +17853,11 @@ __metadata: linkType: hard "@types/cors@npm:^2.8.6": - version: 2.8.16 - resolution: "@types/cors@npm:2.8.16" + version: 2.8.17 + resolution: "@types/cors@npm:2.8.17" dependencies: "@types/node": "*" - checksum: 0c760aa826167a42bfbccff00d67e39c9dd9852e0cd88610f6d3ea1ed17e438df0f8f1f3175c77bfbfdee4c77bf677b12f6b5bd309358c30b5d0e758624b7250 + checksum: 469bd85e29a35977099a3745c78e489916011169a664e97c4c3d6538143b0a16e4cc72b05b407dc008df3892ed7bf595f9b7c0f1f4680e169565ee9d64966bde languageName: node linkType: hard @@ -18257,11 +17872,11 @@ __metadata: linkType: hard "@types/cross-spawn@npm:^6.0.2": - version: 6.0.5 - resolution: "@types/cross-spawn@npm:6.0.5" + version: 6.0.6 + resolution: "@types/cross-spawn@npm:6.0.6" dependencies: "@types/node": "*" - checksum: 9b9cf332e49319903df3abeeb91882730f26ef80eed2e5d5ab1feb432f3f0804f72a07296c305daf5a310e771d5e3bbfc5395f993ba17e35d399bf6996860771 + checksum: b4172927cd1387cf037c3ade785ef46c87537b7bc2803d7f6663b4904d0c5d6f726415d1adb2fee4fecb21746738f11336076449265d46be4ce110cc3a8c8436 languageName: node linkType: hard @@ -18340,20 +17955,20 @@ __metadata: linkType: hard "@types/d3-shape@npm:^1": - version: 1.3.11 - resolution: "@types/d3-shape@npm:1.3.11" + version: 1.3.12 + resolution: "@types/d3-shape@npm:1.3.12" dependencies: "@types/d3-path": ^1 - checksum: e53113a1e18f3398bbe9a885657640c2080f3a52c5d745a44ed161239bf64b009a3de1aa621ee3befb295de3e71116f69dd2837e7acab60a947fac714452e1ad + checksum: 3a62a0a20ef3f767ecd396b2331b836aeaba43a87926a33bb257e3bbe9c70013a2be60718dd94539e287d628da2c5b6f80675c12c0c3a086a3f4129b04ac2285 languageName: node linkType: hard "@types/d3-shape@npm:^3.0.1, @types/d3-shape@npm:^3.1.0": - version: 3.1.5 - resolution: "@types/d3-shape@npm:3.1.5" + version: 3.1.6 + resolution: "@types/d3-shape@npm:3.1.6" dependencies: "@types/d3-path": "*" - checksum: 8476c3908ec70637c8d1e5b103eebd0155fe2b398280c782e318007b444b9abaed65aba35b426f701af14a880cec3f4e47bdbf3a2a45545e0f40fa45e7492708 + checksum: bd765be021019c43c8dca066a798a1de28a051d1213db6ca25f76c9e577da7ec40a592e3bda7628383ab48cb87164fe60b95eb5ec23761b2012bd0adb30c549a languageName: node linkType: hard @@ -18484,9 +18099,9 @@ __metadata: linkType: hard "@types/event-source-polyfill@npm:^1.0.0": - version: 1.0.4 - resolution: "@types/event-source-polyfill@npm:1.0.4" - checksum: fbb2197ccab6eec3a3b412b269ded3bc9617d5ce358c2d71d978dfb913dbca74d0ef66da3e9f0c4c6a8bcd5ab35237f36f3191ba3717bb3ca4314ccc6afc0e3d + version: 1.0.5 + resolution: "@types/event-source-polyfill@npm:1.0.5" + checksum: f506b68710162f2ade1bccbc5691b8c67e5a703e565df2bc0b7b5be2637ba838ef81ec6c10b03248fe4d054386d95a6e827c7aace6e924986c2b9985f77b55de languageName: node linkType: hard @@ -18497,7 +18112,7 @@ __metadata: languageName: node linkType: hard -"@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.30, @types/express-serve-static-core@npm:^4.17.33, @types/express-serve-static-core@npm:^4.17.5": +"@types/express-serve-static-core@npm:*, @types/express-serve-static-core@npm:^4.17.33, @types/express-serve-static-core@npm:^4.17.5": version: 4.17.41 resolution: "@types/express-serve-static-core@npm:4.17.41" dependencies: @@ -18553,20 +18168,20 @@ __metadata: languageName: node linkType: hard -"@types/glob@npm:*": - version: 7.1.3 - resolution: "@types/glob@npm:7.1.3" +"@types/glob@npm:^8.0.0": + version: 8.1.0 + resolution: "@types/glob@npm:8.1.0" dependencies: - "@types/minimatch": "*" + "@types/minimatch": ^5.1.2 "@types/node": "*" - checksum: e0eef12285f548f15d887145590594a04ccce7f7e645fb047cbac18cb093f25d507ffbcc725312294c224bb78cf980fce33e5807de8d6f8a868b4186253499d4 + checksum: 9101f3a9061e40137190f70626aa0e202369b5ec4012c3fabe6f5d229cce04772db9a94fa5a0eb39655e2e4ad105c38afbb4af56a56c0996a8c7d4fc72350e3d languageName: node linkType: hard "@types/google-protobuf@npm:^3.7.2": - version: 3.15.10 - resolution: "@types/google-protobuf@npm:3.15.10" - checksum: a0c4696717d7a47f2aa4837d552583c2a5a69fe5790b38b8393850a53ea37a197dcd5b3ab19bc32f8604213eb04ff0b52ee94ac8b6d4f35cd700e8f7bb94f6a1 + version: 3.15.12 + resolution: "@types/google-protobuf@npm:3.15.12" + checksum: c64efd268170eac0865a42c9616b05100e5ac07e7fa1ed87c827c9d2a58eb02cb2d01cb3248c7ddd563468ecb079295b81ab966e399ba08858f525896631e961 languageName: node linkType: hard @@ -18665,15 +18280,6 @@ __metadata: languageName: node linkType: hard -"@types/is-ci@npm:^3.0.0": - version: 3.0.0 - resolution: "@types/is-ci@npm:3.0.0" - dependencies: - ci-info: ^3.1.0 - checksum: 7c1f1f16c1fa2134de7400d82766c83fa76057261ba890628af77a09382ebb92d945bb077b98cfcf3d40ab1469c9ffbd2278112867edbe57aa655f53547eb139 - languageName: node - linkType: hard - "@types/is-glob@npm:^4.0.2": version: 4.0.4 resolution: "@types/is-glob@npm:4.0.4" @@ -18726,12 +18332,12 @@ __metadata: linkType: hard "@types/jest@npm:*, @types/jest@npm:^29.0.0": - version: 29.5.8 - resolution: "@types/jest@npm:29.5.8" + version: 29.5.10 + resolution: "@types/jest@npm:29.5.10" dependencies: expect: ^29.0.0 pretty-format: ^29.0.0 - checksum: ca8438a5b4c098c8c023e9d5b279ea306494a1d0b5291cfb498100fa780377145f068b2a021d545b0398bbe0328dcc37044dd3aaf3c6c0fe9b0bef7b46a63453 + checksum: ef385905787db528de9b6beb2688865c0bb276e64256ed60b9a1a6ffc0b75737456cb5e27e952a3241c5845b6a1da487470010dd30f3ca59c8581624c564a823 languageName: node linkType: hard @@ -18746,11 +18352,11 @@ __metadata: linkType: hard "@types/jquery@npm:^3.3.34": - version: 3.5.27 - resolution: "@types/jquery@npm:3.5.27" + version: 3.5.29 + resolution: "@types/jquery@npm:3.5.29" dependencies: "@types/sizzle": "*" - checksum: a217d3dbf134134e1b1e10bb0a197523eb362d8e2aa2ae2ad909ae8db0d625f5784203a0794a498b7a09e495ae7822512b3112440cc96b8374eda4afc33b0d6e + checksum: 5e959762d6f7050b07b4387b6507a308113384566a77cfc4f8d0f54c2fb0a79f6bc8c057706c6aa4840cde56f32ad0e5814fb53c5f078c5db9e01670a1ecd535 languageName: node linkType: hard @@ -18776,12 +18382,12 @@ __metadata: linkType: hard "@types/jscodeshift@npm:^0.11.0": - version: 0.11.10 - resolution: "@types/jscodeshift@npm:0.11.10" + version: 0.11.11 + resolution: "@types/jscodeshift@npm:0.11.11" dependencies: ast-types: ^0.14.1 recast: ^0.20.3 - checksum: 91cd3ec925e4a9624fe0f5490ac1509b1f9b34bd7beed89c210eb0bec340c7b4627beef27912e5408aeb4dd6e2d7e37d2fd6a66a8436cd2c56c5cb7e0ddc2cbb + checksum: 6224b781cbbc8e095cae3cb8f9dd1ca102d6c42d9c882b76ea84dfd0cd43870ce317369480ed6b593352efe9fe7199bd6c40ec2cb37646c474ba15f5b43d2109 languageName: node linkType: hard @@ -18797,11 +18403,11 @@ __metadata: linkType: hard "@types/json-schema-merge-allof@npm:^0.6.0": - version: 0.6.4 - resolution: "@types/json-schema-merge-allof@npm:0.6.4" + version: 0.6.5 + resolution: "@types/json-schema-merge-allof@npm:0.6.5" dependencies: "@types/json-schema": "*" - checksum: 7ac71a8b6cda3e1e48153c0c00939daab2ae56353fd2e41f59a3b69a2a26eafddb9e389b8096068eea5ac60e6619927a2d854f317c67940a35488ce52507b472 + checksum: 704806bce36c830b971bcc26415d2a4c4102482808bf6aef343dd4c062678f7e69e537ffebf4fbb389e568e4056cab9259b2b6f06a988c8676d90da37bbbc4c4 languageName: node linkType: hard @@ -18812,13 +18418,6 @@ __metadata: languageName: node linkType: hard -"@types/json-stable-stringify@npm:^1.0.32": - version: 1.0.32 - resolution: "@types/json-stable-stringify@npm:1.0.32" - checksum: 3091ddc8d15c6cce1a847ba1f8db21e7c2564c7b8bc6923a873801d936228f775096b517d62653fbcebedcb2a7992555dc6ed11517ef050e75525cdf1d1bce8d - languageName: node - linkType: hard - "@types/json5@npm:^0.0.29": version: 0.0.29 resolution: "@types/json5@npm:0.0.29" @@ -18826,15 +18425,6 @@ __metadata: languageName: node linkType: hard -"@types/jsonwebtoken@npm:^8.5.0": - version: 8.5.0 - resolution: "@types/jsonwebtoken@npm:8.5.0" - dependencies: - "@types/node": "*" - checksum: e8f9ab96ec5cf76195c0d31cf555371824b673939064efec698ca99525ce46476af54debd1f66bd732e6079e134848b97163797009c4b47a767448a0c6ddaeda - languageName: node - linkType: hard - "@types/jsonwebtoken@npm:^9.0.0": version: 9.0.0 resolution: "@types/jsonwebtoken@npm:9.0.0" @@ -18888,21 +18478,14 @@ __metadata: languageName: node linkType: hard -"@types/linkify-it@npm:*": - version: 3.0.2 - resolution: "@types/linkify-it@npm:3.0.2" - checksum: dff8f10fafb885422474e456596f12d518ec4cdd6c33cca7a08e7c86b912d301ed91cf5a7613e148c45a12600dc9ab3d85ad16d5b48dc1aaeda151a68f16b536 - languageName: node - linkType: hard - "@types/lodash@npm:^4.14.151, @types/lodash@npm:^4.14.173, @types/lodash@npm:^4.14.175": - version: 4.14.201 - resolution: "@types/lodash@npm:4.14.201" - checksum: 484be655298e9b2dc2d218ea934071b2ea31e4a531c561dd220dbda65237e8d08c20dc2d457ac24f29be7fe167415bf7bb9360ea0d80bdb8b0f0ec8d8db92fae + version: 4.14.202 + resolution: "@types/lodash@npm:4.14.202" + checksum: a91acf3564a568c6f199912f3eb2c76c99c5a0d7e219394294213b3f2d54f672619f0fde4da22b29dc5d4c31457cd799acc2e5cb6bd90f9af04a1578483b6ff7 languageName: node linkType: hard -"@types/long@npm:^4.0.0, @types/long@npm:^4.0.1": +"@types/long@npm:^4.0.0": version: 4.0.2 resolution: "@types/long@npm:4.0.2" checksum: d16cde7240d834cf44ba1eaec49e78ae3180e724cd667052b194a372f350d024cba8dd3f37b0864931683dab09ca935d52f0c4c1687178af5ada9fc85b0635f4 @@ -18917,19 +18500,9 @@ __metadata: linkType: hard "@types/luxon@npm:*, @types/luxon@npm:^3.0.0, @types/luxon@npm:~3.3.0": - version: 3.3.4 - resolution: "@types/luxon@npm:3.3.4" - checksum: aa4862bd62d748e7966f9a0ec76058e9d74397ee426c7d64f61c677d83de0303c303cc78515001833df3f4ad16c95f572b0e2ffaee6e55bc50b80857e8437f3a - languageName: node - linkType: hard - -"@types/markdown-it@npm:^12.2.3": - version: 12.2.3 - resolution: "@types/markdown-it@npm:12.2.3" - dependencies: - "@types/linkify-it": "*" - "@types/mdurl": "*" - checksum: 868824a3e4d00718ba9cd4762cf16694762a670860f4b402e6e9f952b6841a2027488bdc55d05c2b960bf5078df21a9d041270af7e8949514645fe88fdb722ac + version: 3.3.6 + resolution: "@types/luxon@npm:3.3.6" + checksum: 44fd3e617fb5d9e370a8d5529de3e703b295bfe225936e786e0b5e7fce662ef82012a6ec29cd2763afbd59bf9a9ab43186bad5c51aa552d963cd5e8c8f4e1d4f languageName: node linkType: hard @@ -18949,7 +18522,7 @@ __metadata: languageName: node linkType: hard -"@types/mdurl@npm:*, @types/mdurl@npm:^1.0.0": +"@types/mdurl@npm:^1.0.0": version: 1.0.2 resolution: "@types/mdurl@npm:1.0.2" checksum: 79c7e523b377f53cf1f5a240fe23d0c6cae856667692bd21bf1d064eafe5ccc40ae39a2aa0a9a51e8c94d1307228c8f6b121e847124591a9a828c3baf65e86e2 @@ -18970,13 +18543,6 @@ __metadata: languageName: node linkType: hard -"@types/minimatch@npm:*, @types/minimatch@npm:^5.0.0": - version: 5.1.2 - resolution: "@types/minimatch@npm:5.1.2" - checksum: 0391a282860c7cb6fe262c12b99564732401bdaa5e395bee9ca323c312c1a0f45efbf34dce974682036e857db59a5c9b1da522f3d6055aeead7097264c8705a8 - languageName: node - linkType: hard - "@types/minimatch@npm:^3.0.3, @types/minimatch@npm:^3.0.5": version: 3.0.5 resolution: "@types/minimatch@npm:3.0.5" @@ -18984,6 +18550,13 @@ __metadata: languageName: node linkType: hard +"@types/minimatch@npm:^5.0.0, @types/minimatch@npm:^5.1.2": + version: 5.1.2 + resolution: "@types/minimatch@npm:5.1.2" + checksum: 0391a282860c7cb6fe262c12b99564732401bdaa5e395bee9ca323c312c1a0f45efbf34dce974682036e857db59a5c9b1da522f3d6055aeead7097264c8705a8 + languageName: node + linkType: hard + "@types/minimist@npm:^1.2.0": version: 1.2.5 resolution: "@types/minimist@npm:1.2.5" @@ -19035,7 +18608,7 @@ __metadata: languageName: node linkType: hard -"@types/node-fetch@npm:^2.5.0, @types/node-fetch@npm:^2.5.12, @types/node-fetch@npm:^2.5.7, @types/node-fetch@npm:^2.6.1": +"@types/node-fetch@npm:^2.5.0, @types/node-fetch@npm:^2.5.12, @types/node-fetch@npm:^2.5.7": version: 2.6.9 resolution: "@types/node-fetch@npm:2.6.9" dependencies: @@ -19046,20 +18619,20 @@ __metadata: linkType: hard "@types/node-forge@npm:^1.3.0": - version: 1.3.9 - resolution: "@types/node-forge@npm:1.3.9" + version: 1.3.10 + resolution: "@types/node-forge@npm:1.3.10" dependencies: "@types/node": "*" - checksum: 4ffab54136960b0944af942a44206470e98766b89b867b6126ebc65c6f21463fd9ea20b26714216e153fbbee7ca5ce689db9067ea286a92b34368a5e2f77601f + checksum: 363af42c83956c7e2483a71e398a02101ef6a55b4d86386c276315ca98bad02d6050b99fdbe13debcd1bcda250086b4a5b5c15a6fb2953d32420d269865ca7f8 languageName: node linkType: hard "@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0, @types/node@npm:^20.1.1": - version: 20.9.0 - resolution: "@types/node@npm:20.9.0" + version: 20.10.2 + resolution: "@types/node@npm:20.10.2" dependencies: undici-types: ~5.26.4 - checksum: bfd927da6bff8a32051fa44bb47ca32a56d2c8bc8ba0170770f181cc1fa3c0b05863c9b930f0ba8604a48d5eb0d319166601709ca53bf2deae0025d8b6c6b8a3 + checksum: c0c84e8270cdf7a47a18c0230c0321537cc59506adb0e3cba51949b6f1ad4879f2e2ec3a29161f2f5321ebb6415460712d9f0a25ac5c02be0f5435464fe77c23 languageName: node linkType: hard @@ -19078,9 +18651,9 @@ __metadata: linkType: hard "@types/node@npm:^16.11.26, @types/node@npm:^16.7.10, @types/node@npm:^16.9.2": - version: 16.18.61 - resolution: "@types/node@npm:16.18.61" - checksum: fdd162829eddc9b0b82a1ec485ba3876428ff3bd94c5869b13f4a36eb2aa9bddd22ea7e8ee3b2faa91a0f70ff08d8fd8d4be7dd0d143f8ee776907d6a1d2ed25 + version: 16.18.66 + resolution: "@types/node@npm:16.18.66" + checksum: 84408652068f8c7e3aa1fa6f333be8044ae802a700eb3b4101fc27d047eefcc742e636809a6318fb0100b1355658649f4a0fc2398fb04f27b1a357f6f3579cd0 languageName: node linkType: hard @@ -19092,11 +18665,11 @@ __metadata: linkType: hard "@types/node@npm:^18.17.8": - version: 18.18.9 - resolution: "@types/node@npm:18.18.9" + version: 18.19.1 + resolution: "@types/node@npm:18.19.1" dependencies: undici-types: ~5.26.4 - checksum: 629ce20357586144031cb43d601617eef45e59460dea6b1e123f708e6885664f44d54f65e5b72b2614af5b8613f3652ced832649c0b991accbc6a85139befa51 + checksum: f687338a6f1c463b03232337652804f62f5ae197ae9517a76cf6543ec5a3e358e41f26da0e4fc1afe4871c4a96eec3e3c440fb4ddb616cdc336b42ca203adb29 languageName: node linkType: hard @@ -19185,24 +18758,24 @@ __metadata: languageName: node linkType: hard -"@types/passport-oauth2@npm:*, @types/passport-oauth2@npm:^1.4.11": - version: 1.4.11 - resolution: "@types/passport-oauth2@npm:1.4.11" +"@types/passport-oauth2@npm:*, @types/passport-oauth2@npm:^1.4.11, @types/passport-oauth2@npm:^1.4.15": + version: 1.4.15 + resolution: "@types/passport-oauth2@npm:1.4.15" dependencies: "@types/express": "*" "@types/oauth": "*" "@types/passport": "*" - checksum: 09d047a6c09a05c036f7db0cf8f8c09bf5878fdd15949bb1baa09a35f439929d471048fa6595f09ea4a4ea25396ce3918b362136579cf4a2b2ee29a92c0dd1ce + checksum: 352c4e2d09a86f8fc0dcf2c917c221f302a35a14e7467e2fa3a1653c0a9a1f842c910a4e52f799856536522e6359c20d1afc319579d9edf4b2ac7ea11b183b52 languageName: node linkType: hard "@types/passport-saml@npm:^1.1.3": - version: 1.1.6 - resolution: "@types/passport-saml@npm:1.1.6" + version: 1.1.7 + resolution: "@types/passport-saml@npm:1.1.7" dependencies: "@types/express": "*" "@types/passport": "*" - checksum: 91609adca645d79d9248a7e21a77df37015a6ab9a051d9eded0beea983c36928ffa004f48d96c86182a34a30181e5dc204b983eabddf8cd2d91a7784a4ce6dc6 + checksum: cc112ac43d8a9ed586cfa04342afefef45ec96b7125a554534fb763986e3426b0316ee3d9e4705240c9c3df3b2b19914dba48ef6abccbd6946e9ae634f790332 languageName: node linkType: hard @@ -19217,11 +18790,11 @@ __metadata: linkType: hard "@types/passport@npm:*, @types/passport@npm:^1.0.3": - version: 1.0.15 - resolution: "@types/passport@npm:1.0.15" + version: 1.0.16 + resolution: "@types/passport@npm:1.0.16" dependencies: "@types/express": "*" - checksum: bf96312a2824b180a3202e01ffb19860813cf3d5fa617a0f0a8d0a4a36899c955280db5697b0b243b4dfbc2032e6b7695fdc6990a93f27ca1d0e2a072e01066a + checksum: e4a02fa338536eb82694ea548689a7214b1ca98df6a896080daa2b6a8859db02a1e6244eeefaf6f3cc9c268239bb4a7912049a9ed86192144a65c10e55219f80 languageName: node linkType: hard @@ -19257,10 +18830,19 @@ __metadata: languageName: node linkType: hard -"@types/prop-types@npm:*, @types/prop-types@npm:^15.0.0, @types/prop-types@npm:^15.7.10, @types/prop-types@npm:^15.7.3": - version: 15.7.10 - resolution: "@types/prop-types@npm:15.7.10" - checksum: 39ecc2d9e439ed16b32937a08d98b84ed4a70f53bcd52c8564c0cd7a36fe1004ca83a1fb94b13c1b7a5c048760f06445c3c6a91a6972c8eff652c0b50c9424b1 +"@types/prop-types@npm:*, @types/prop-types@npm:^15.0.0, @types/prop-types@npm:^15.7.11, @types/prop-types@npm:^15.7.3": + version: 15.7.11 + resolution: "@types/prop-types@npm:15.7.11" + checksum: 7519ff11d06fbf6b275029fe03fff9ec377b4cb6e864cac34d87d7146c7f5a7560fd164bdc1d2dbe00b60c43713631251af1fd3d34d46c69cd354602bc0c7c54 + languageName: node + linkType: hard + +"@types/protocol-buffers-schema@npm:^3.4.1": + version: 3.4.3 + resolution: "@types/protocol-buffers-schema@npm:3.4.3" + dependencies: + "@types/node": "*" + checksum: a07e150d4737fea79ea8b58be8b8828c9736319f3d8bce92d282b424629ebcd5e056d083b1f8c150a0a7213cdf518bd62c8c7725473f2214f23f5331adead5fb languageName: node linkType: hard @@ -19297,11 +18879,11 @@ __metadata: linkType: hard "@types/react-dom@npm:^18": - version: 18.2.15 - resolution: "@types/react-dom@npm:18.2.15" + version: 18.2.17 + resolution: "@types/react-dom@npm:18.2.17" dependencies: "@types/react": "*" - checksum: 8e9631600c21ff561328e38a951d1991b3b3b20f538af4c0efbd1327c883a5573a63f50e1b945c34fa51b114b30e1ca5e62317bd54f21e063d6697b4be843a03 + checksum: 7a4e704ed4be6e0c3ccd8a22ff69386fe548304bf4db090513f42e059ff4c65f7a427790320051524d6578a2e4c9667bb7a80a4c989b72361c019fbe851d9385 languageName: node linkType: hard @@ -19371,12 +18953,12 @@ __metadata: languageName: node linkType: hard -"@types/react-transition-group@npm:^4.2.0, @types/react-transition-group@npm:^4.4.8": - version: 4.4.8 - resolution: "@types/react-transition-group@npm:4.4.8" +"@types/react-transition-group@npm:^4.2.0, @types/react-transition-group@npm:^4.4.9": + version: 4.4.9 + resolution: "@types/react-transition-group@npm:4.4.9" dependencies: "@types/react": "*" - checksum: ad7ba2bce97631fda9d89b4ed9772489bd050fec3ccd7563041b206dbe219d37d22e0d7731b1f90f56e89daf40e69ba16beba8066c42165bf8a584533feb6a2c + checksum: be9e256e53919a7cf3b4a075f6d01c0a2dd3a67911dd28276aa6158be4beade4ca5327cbf1f096c28b413e04989f069122319b02e5a09c280d903a0accea9ead languageName: node linkType: hard @@ -19399,13 +18981,13 @@ __metadata: linkType: hard "@types/react@npm:^18": - version: 18.2.37 - resolution: "@types/react@npm:18.2.37" + version: 18.2.40 + resolution: "@types/react@npm:18.2.40" dependencies: "@types/prop-types": "*" "@types/scheduler": "*" csstype: ^3.0.2 - checksum: 2d2599f1a09e4f678509161fea8baeaf76d21deee460f4f3ccc1ca431ebe85f896d7d0b906127de17e97ed57240cec61955eb97d0b5d9cbf4e97fd6620b1acdb + checksum: c1d8cf29bc314e2d04203b4afe5673aea4ddec39a685c6aff72b01f5b01ae84fed6e994b5e1dbb9fbe4bc69625fdb65a295fae656a2ca9f6a8c949afb327b644 languageName: node linkType: hard @@ -19419,12 +19001,12 @@ __metadata: linkType: hard "@types/recharts@npm:^1.8.14, @types/recharts@npm:^1.8.15": - version: 1.8.27 - resolution: "@types/recharts@npm:1.8.27" + version: 1.8.28 + resolution: "@types/recharts@npm:1.8.28" dependencies: "@types/d3-shape": ^1 "@types/react": "*" - checksum: d37fa91a35c07dfc95587f2a9e06e661c35e26b070b04e8fb325b89aee676c3953aba9fe2b27f740dc5ecf111a38540c3f2bdb33f47f3249c60bb21c28c9c9df + checksum: b334ed1b34123483a2f03dd4b13bdae3048a4a50b2a46b69e6580545ecd3fd57874a9818e5c2c1d8a98dc0bf8a1b6d45b4790d31fb5c395d7b7c6c268b716634 languageName: node linkType: hard @@ -19438,30 +19020,28 @@ __metadata: linkType: hard "@types/regression@npm:^2.0.0": - version: 2.0.5 - resolution: "@types/regression@npm:2.0.5" - checksum: b8eac5c024838f7491d36fe277981ed56f2b4e31f9e228f1837d13e1346abc7f41ed5031eb876af462f4e05afb9a6b48c4a44b6cbabff97af64faae246313997 + version: 2.0.6 + resolution: "@types/regression@npm:2.0.6" + checksum: c412ddd924efd53395f0011b38a6b1dbc94fc71adfa80efcb6657f0f1b6123fb27c101798dda8d0aa638c925900b4b4a9c5c03504a0d1255edd160e3090a5ce9 languageName: node linkType: hard -"@types/request@npm:^2.47.1": - version: 2.48.8 - resolution: "@types/request@npm:2.48.8" +"@types/request@npm:^2.47.1, @types/request@npm:^2.48.8": + version: 2.48.12 + resolution: "@types/request@npm:2.48.12" dependencies: "@types/caseless": "*" "@types/node": "*" "@types/tough-cookie": "*" form-data: ^2.5.0 - checksum: 0b7754941e08205dce51635d894ec524df276d2b83ca13b9aab723f9281acecf1108841e9554494cb1cb60f6d6ddbb47ebea97392bcf2bf607f035b3a9b4af45 + checksum: 20dfad0a46b4249bf42f09c51fbd4d02ec6738c5152194b5c7c69bab80b00eae9cc71df4489ffa929d0968d453ef7d0823d1f98871efed563a4fdb57bf0a4c58 languageName: node linkType: hard -"@types/resolve@npm:1.17.1": - version: 1.17.1 - resolution: "@types/resolve@npm:1.17.1" - dependencies: - "@types/node": "*" - checksum: dc6a6df507656004e242dcb02c784479deca516d5f4b58a1707e708022b269ae147e1da0521f3e8ad0d63638869d87e0adc023f0bd5454aa6f72ac66c7525cf5 +"@types/resolve@npm:1.20.2": + version: 1.20.2 + resolution: "@types/resolve@npm:1.20.2" + checksum: 61c2cad2499ffc8eab36e3b773945d337d848d3ac6b7b0a87c805ba814bc838ef2f262fc0f109bfd8d2e0898ff8bd80ad1025f9ff64f1f71d3d4294c9f14e5f6 languageName: node linkType: hard @@ -19481,16 +19061,6 @@ __metadata: languageName: node linkType: hard -"@types/rimraf@npm:^3.0.2": - version: 3.0.2 - resolution: "@types/rimraf@npm:3.0.2" - dependencies: - "@types/glob": "*" - "@types/node": "*" - checksum: b47fa302f46434cba704d20465861ad250df79467d3d289f9d6490d3aeeb41e8cb32dd80bd1a8fd833d1e185ac719fbf9be12e05ad9ce9be094d8ee8f1405347 - languageName: node - linkType: hard - "@types/rollup-plugin-peer-deps-external@npm:^2.2.0": version: 2.2.4 resolution: "@types/rollup-plugin-peer-deps-external@npm:2.2.4" @@ -19511,11 +19081,11 @@ __metadata: linkType: hard "@types/sanitize-html@npm:^2.6.2": - version: 2.9.4 - resolution: "@types/sanitize-html@npm:2.9.4" + version: 2.9.5 + resolution: "@types/sanitize-html@npm:2.9.5" dependencies: htmlparser2: ^8.0.0 - checksum: 196c6b0a307b6e0482cbad4d28c5f3f7bf03001bdc30ad1a18b61a5074ddbf9c1f32adee539ecd83370fceea2ef501955a2c3f27f820c229974a265d31832c95 + checksum: fd0afee5dac91aa2c42391f0c8c9254204f4ee1f10b902aa04e8f7809043d785e28af2732f75277ef09e46838013ad60abedb02ba1424b6218264f3333437fb5 languageName: node linkType: hard @@ -19534,9 +19104,9 @@ __metadata: linkType: hard "@types/semver@npm:^7.3.12, @types/semver@npm:^7.3.8, @types/semver@npm:^7.5.0": - version: 7.5.5 - resolution: "@types/semver@npm:7.5.5" - checksum: 533e6c93d1262d65f449423d94a445f7f3db0672e7429f21b6a1636d6051dbab3a2989ddcda9b79c69bb37830931d09fc958a65305a891357f5cea3257c297f5 + version: 7.5.6 + resolution: "@types/semver@npm:7.5.6" + checksum: 563a0120ec0efcc326567db2ed920d5d98346f3638b6324ea6b50222b96f02a8add3c51a916b6897b51523aad8ac227d21d3dcf8913559f1bfc6c15b14d23037 languageName: node linkType: hard @@ -19645,6 +19215,13 @@ __metadata: languageName: node linkType: hard +"@types/statuses@npm:^2.0.1": + version: 2.0.4 + resolution: "@types/statuses@npm:2.0.4" + checksum: 3a806c3b96d1845e3e7441fbf0839037e95f717334760ddb7c29223c9a34a7206b68e2998631f89f1a1e3ef5b67b15652f6e8fa14987ebd7f6d38587c1bffd18 + languageName: node + linkType: hard + "@types/stoppable@npm:^1.1.0": version: 1.1.3 resolution: "@types/stoppable@npm:1.1.3" @@ -19701,12 +19278,12 @@ __metadata: linkType: hard "@types/tar@npm:^6.1.1": - version: 6.1.9 - resolution: "@types/tar@npm:6.1.9" + version: 6.1.10 + resolution: "@types/tar@npm:6.1.10" dependencies: "@types/node": "*" minipass: ^4.0.0 - checksum: d3765d47ab1d4ae35e40a1fd5f460e3413eea960e960443ed3de257425a62ba4d900dbe9ee5a2a740f4c68aa310597f56f74d274de070a06f45b8a913178a325 + checksum: 82d46f1246e830b98833ed94fbdfbcb3ffb8a5d7173609622d56c9326124523a3cc541607876c63a6ab9117eb59fb37ef8a6284b194164ab1d1d8c03a8ba59c6 languageName: node linkType: hard @@ -19840,11 +19417,11 @@ __metadata: linkType: hard "@types/ws@npm:*, @types/ws@npm:^8.0.0, @types/ws@npm:^8.5.3, @types/ws@npm:^8.5.5": - version: 8.5.8 - resolution: "@types/ws@npm:8.5.8" + version: 8.5.9 + resolution: "@types/ws@npm:8.5.9" dependencies: "@types/node": "*" - checksum: 4ad30de842834d4dd8e6e1476470752709d4165352a3a36780f23f4fdb686d4ac8ca5e16a0e0622940ddace910b856ff8a0baa2e24e41d204fb7a6a02ab2172b + checksum: 83f436b731d2cdc49a45ced31a0a65cdd2e39c24d7b882776c26efa190dad6553e266d624c7a7089f36ad3ed471e02e729f3219282c80689b435f665df4a2b0b languageName: node linkType: hard @@ -19906,21 +19483,21 @@ __metadata: linkType: hard "@types/zen-observable@npm:^0.8.0, @types/zen-observable@npm:^0.8.2": - version: 0.8.6 - resolution: "@types/zen-observable@npm:0.8.6" - checksum: 5110a0a019ff1c6571c9059d56910b3fa24862ae1211ee8cd71a304abd39aa415e3ea8110746e20db6757e4e08f4c0863216ab0f154c351bc89338bcde047868 + version: 0.8.7 + resolution: "@types/zen-observable@npm:0.8.7" + checksum: 6d4cdccded97f8e21b18224a70524e559abe2568863ed21ea000580aa3446c6d583253e83e8ecc0c93b4060ef3fb7f9d14739a57ee18925cc30e0e7d79713a15 languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:6.10.0": - version: 6.10.0 - resolution: "@typescript-eslint/eslint-plugin@npm:6.10.0" +"@typescript-eslint/eslint-plugin@npm:^6.12.0": + version: 6.13.1 + resolution: "@typescript-eslint/eslint-plugin@npm:6.13.1" dependencies: "@eslint-community/regexpp": ^4.5.1 - "@typescript-eslint/scope-manager": 6.10.0 - "@typescript-eslint/type-utils": 6.10.0 - "@typescript-eslint/utils": 6.10.0 - "@typescript-eslint/visitor-keys": 6.10.0 + "@typescript-eslint/scope-manager": 6.13.1 + "@typescript-eslint/type-utils": 6.13.1 + "@typescript-eslint/utils": 6.13.1 + "@typescript-eslint/visitor-keys": 6.13.1 debug: ^4.3.4 graphemer: ^1.4.0 ignore: ^5.2.4 @@ -19933,25 +19510,25 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: eaf1f66ae1915426dad8d229c8cb80d2b320572a30c3fbc57d560d40edc2d17d004101a2fcbe331bc458df19a00f8b705f2442ee02e028bb595f4e9f9152e99d + checksum: 568093d76c200a8502047d74f29300110a59b9f2a5cbf995a6cbe419c803a7ec22220e9592a884401d2dde72c79346b4cc0ee393e7b422924ad4a8a2040af3b0 languageName: node linkType: hard "@typescript-eslint/parser@npm:^6.7.2": - version: 6.11.0 - resolution: "@typescript-eslint/parser@npm:6.11.0" + version: 6.13.1 + resolution: "@typescript-eslint/parser@npm:6.13.1" dependencies: - "@typescript-eslint/scope-manager": 6.11.0 - "@typescript-eslint/types": 6.11.0 - "@typescript-eslint/typescript-estree": 6.11.0 - "@typescript-eslint/visitor-keys": 6.11.0 + "@typescript-eslint/scope-manager": 6.13.1 + "@typescript-eslint/types": 6.13.1 + "@typescript-eslint/typescript-estree": 6.13.1 + "@typescript-eslint/visitor-keys": 6.13.1 debug: ^4.3.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: e9cb175e3537b82aa8cd39641ecb4e656586f89f8365cf05400b5aa8794dac0c8c10c6aa2fd7c13a684f62c1493f5e41c5534df49d377abe9dc89d861a51195c + checksum: 58b7fef6f2d02c8f4737f9908a8d335a20bee20dba648233a69f28e7b39237791d2b9fbb818e628dcc053ddf16507b161ace7f1139e093d72365f1270c426de3 languageName: node linkType: hard @@ -19965,32 +19542,22 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.10.0": - version: 6.10.0 - resolution: "@typescript-eslint/scope-manager@npm:6.10.0" +"@typescript-eslint/scope-manager@npm:6.13.1": + version: 6.13.1 + resolution: "@typescript-eslint/scope-manager@npm:6.13.1" dependencies: - "@typescript-eslint/types": 6.10.0 - "@typescript-eslint/visitor-keys": 6.10.0 - checksum: c9b9483082ae853f10b888cf04d4a14f666ac55e749bfdb7b7f726fc51127a6340b5e2f50d93f134a8854ddcc41f7b116b214753251a8b033d0d84c600439c54 + "@typescript-eslint/types": 6.13.1 + "@typescript-eslint/visitor-keys": 6.13.1 + checksum: 109a213f82719e10f8c6a0168f2e105dc1369c7e0c075c1f30af137030fc866a3a585a77ff78a9a3538afc213061c8aedbb4462a91f26cbd90eefbab8b89ea10 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.11.0": - version: 6.11.0 - resolution: "@typescript-eslint/scope-manager@npm:6.11.0" +"@typescript-eslint/type-utils@npm:6.13.1": + version: 6.13.1 + resolution: "@typescript-eslint/type-utils@npm:6.13.1" dependencies: - "@typescript-eslint/types": 6.11.0 - "@typescript-eslint/visitor-keys": 6.11.0 - checksum: d219a96fd80fb14176cdcc47b070e870c73ccc0dfb32a8657f6ceaefb613dc0ea240a77250dcfc437d9c9360ca165c2765d4cf8fe689dae7e9eee2c0d6a98a50 - languageName: node - linkType: hard - -"@typescript-eslint/type-utils@npm:6.10.0": - version: 6.10.0 - resolution: "@typescript-eslint/type-utils@npm:6.10.0" - dependencies: - "@typescript-eslint/typescript-estree": 6.10.0 - "@typescript-eslint/utils": 6.10.0 + "@typescript-eslint/typescript-estree": 6.13.1 + "@typescript-eslint/utils": 6.13.1 debug: ^4.3.4 ts-api-utils: ^1.0.1 peerDependencies: @@ -19998,7 +19565,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: cfe9520cf0c0f50b115d2591acb2abf99ffe5789b3536268ca65b624c8498812d91f187e80c41bea7cf2cebad9c38f69ef27440f872a20fb53c59856d8f5df38 + checksum: e39d28dd2f3b47a26b4f6aa2c7a301bdd769ce9148d734be93441a813c3d1111eba1d655677355bba5519f3d4dbe93e4ff4e46830216b0302df0070bf7a80057 languageName: node linkType: hard @@ -20009,17 +19576,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:6.10.0": - version: 6.10.0 - resolution: "@typescript-eslint/types@npm:6.10.0" - checksum: e63a9e05eb3d736d02a09131627d5cb89394bf0d9d6b46fb4b620be902d89d73554720be65acbc194787bff9ffcd518c9a6cf88fd63e418232b4181e8d8438df - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:6.11.0": - version: 6.11.0 - resolution: "@typescript-eslint/types@npm:6.11.0" - checksum: ca8a11320286c9b0759a70ec83b9fd99937c9686fafdd41d8ea09ed7b2fa12e6b342bf65547efe5495926cd04cfc6488315920e3caffd27f12d42cb9a8cf88c8 +"@typescript-eslint/types@npm:6.13.1": + version: 6.13.1 + resolution: "@typescript-eslint/types@npm:6.13.1" + checksum: bb1d52f1646bab9acd3ec874567ffbaaaf7fe4a5f79845bdacbfea46d15698e58d45797da05b08c23f9496a17229b7f2c1363d000fd89ce4e79874fd57ba1d4a languageName: node linkType: hard @@ -20041,12 +19601,12 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.10.0": - version: 6.10.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.10.0" +"@typescript-eslint/typescript-estree@npm:6.13.1": + version: 6.13.1 + resolution: "@typescript-eslint/typescript-estree@npm:6.13.1" dependencies: - "@typescript-eslint/types": 6.10.0 - "@typescript-eslint/visitor-keys": 6.10.0 + "@typescript-eslint/types": 6.13.1 + "@typescript-eslint/visitor-keys": 6.13.1 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -20055,42 +19615,24 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 15bd8d9239a557071d6b03e7aa854b769fcc2dbdff587ed94be7ee8060dabdb05bcae4251df22432f625f82087e7f6986e9aab04f7eea35af694d4edd76a21af + checksum: 09aa0f5cbd60e84df4f58f3d479be352549600b24dbefe75c686ea89252526c52c1c06ce1ae56c0405dd7337002e741c2ba02b71fb1caa3b94a740a70fcc8699 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.11.0": - version: 6.11.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.11.0" - dependencies: - "@typescript-eslint/types": 6.11.0 - "@typescript-eslint/visitor-keys": 6.11.0 - debug: ^4.3.4 - globby: ^11.1.0 - is-glob: ^4.0.3 - semver: ^7.5.4 - ts-api-utils: ^1.0.1 - peerDependenciesMeta: - typescript: - optional: true - checksum: e137ba7c4cad08853a44d9c40072496ca5f2d440828be9fd2d207a59db56b05a6dcb4756f3ba341ee2ae714de45df80114477946d30801c5a46eed67314fd9c6 - languageName: node - linkType: hard - -"@typescript-eslint/utils@npm:6.10.0": - version: 6.10.0 - resolution: "@typescript-eslint/utils@npm:6.10.0" +"@typescript-eslint/utils@npm:6.13.1": + version: 6.13.1 + resolution: "@typescript-eslint/utils@npm:6.13.1" dependencies: "@eslint-community/eslint-utils": ^4.4.0 "@types/json-schema": ^7.0.12 "@types/semver": ^7.5.0 - "@typescript-eslint/scope-manager": 6.10.0 - "@typescript-eslint/types": 6.10.0 - "@typescript-eslint/typescript-estree": 6.10.0 + "@typescript-eslint/scope-manager": 6.13.1 + "@typescript-eslint/types": 6.13.1 + "@typescript-eslint/typescript-estree": 6.13.1 semver: ^7.5.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: b6bd4d68623fb8d616ae63a88f2954258411a0cc113029fba801d1e74b4c0319fdfbcac0070527afe5cc38c012c8718e4faecd1603000924d7b89e8fefc3f24d + checksum: 14f64840869c8755af4d287cfc74abc424dc139559e87ca1a8b0e850f4fa56311d99dfb61a43dd4433eae5914be12b4b3390e55de1f236dce6701830d17e31c9 languageName: node linkType: hard @@ -20122,29 +19664,19 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.10.0": - version: 6.10.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.10.0" +"@typescript-eslint/visitor-keys@npm:6.13.1": + version: 6.13.1 + resolution: "@typescript-eslint/visitor-keys@npm:6.13.1" dependencies: - "@typescript-eslint/types": 6.10.0 + "@typescript-eslint/types": 6.13.1 eslint-visitor-keys: ^3.4.1 - checksum: 9640bfae41e6109ffba31e68b1720382de0538d021261e2fc9e514c83c703084393c0818ca77ed26b950273e45e593371120281e8d4bbd09cb8c2d46c9fe4f03 + checksum: d15d362203a2fe995ea62a59d5b44c15c8fb1fb30ff59dd1542a980f75b3b62035303dfb781d83709921613f6ac8cc5bf57b70f6e20d820aec8b7911f07152e9 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.11.0": - version: 6.11.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.11.0" - dependencies: - "@typescript-eslint/types": 6.11.0 - eslint-visitor-keys: ^3.4.1 - checksum: 6aae9dd79963bbefbf2e310015b909627da541a13ab4d8359eea3c86c34fdbb91e583f65b5a99dee1959f7c5d67b21b45e5a05c63ddb4b82dacd60c890ce8b25 - languageName: node - linkType: hard - -"@uiw/codemirror-extensions-basic-setup@npm:4.21.20": - version: 4.21.20 - resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.21.20" +"@uiw/codemirror-extensions-basic-setup@npm:4.21.21": + version: 4.21.21 + resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.21.21" dependencies: "@codemirror/autocomplete": ^6.0.0 "@codemirror/commands": ^6.0.0 @@ -20161,19 +19693,19 @@ __metadata: "@codemirror/search": ">=6.0.0" "@codemirror/state": ">=6.0.0" "@codemirror/view": ">=6.0.0" - checksum: 76a6caf05bbcf06c515c680ab952e79b8470ca10c9d8c3166fdb05310232239782b170da276b1dbf33900ca894332fc2aba3bd6955665b2c2580548c7e17cbc0 + checksum: 5d96ec930be286b5e324ee8dd57128171c72a8e333b4b991a5c4f33a05420a638def3776bd1a77c5b88184f7d3cbc6828b5c9a42b3b490f51908bedf69eaa0f0 languageName: node linkType: hard "@uiw/react-codemirror@npm:^4.9.3": - version: 4.21.20 - resolution: "@uiw/react-codemirror@npm:4.21.20" + version: 4.21.21 + resolution: "@uiw/react-codemirror@npm:4.21.21" dependencies: "@babel/runtime": ^7.18.6 "@codemirror/commands": ^6.1.0 "@codemirror/state": ^6.1.1 "@codemirror/theme-one-dark": ^6.0.0 - "@uiw/codemirror-extensions-basic-setup": 4.21.20 + "@uiw/codemirror-extensions-basic-setup": 4.21.21 codemirror: ^6.0.0 peerDependencies: "@babel/runtime": ">=7.11.0" @@ -20183,7 +19715,7 @@ __metadata: codemirror: ">=6.0.0" react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: 63ea348a922c535ff91c8bff1c1dac40ced0227d1c17139142dbc28017bb254cc32428a15686660ec4f4cd6935c574d627b6a4872910357af51da8e90faaf4da + checksum: 6a8500290bf0a739fd345221465b10112e0f758914bc8aa28ce0b9904b76489ae018d390f6a2d7dd7752b21f0ed87ba3fedb45b4185d04e4985abf0eb22e6d75 languageName: node linkType: hard @@ -20366,17 +19898,17 @@ __metadata: linkType: hard "@vitejs/plugin-react@npm:^4.0.4": - version: 4.1.1 - resolution: "@vitejs/plugin-react@npm:4.1.1" + version: 4.2.0 + resolution: "@vitejs/plugin-react@npm:4.2.0" dependencies: - "@babel/core": ^7.23.2 - "@babel/plugin-transform-react-jsx-self": ^7.22.5 - "@babel/plugin-transform-react-jsx-source": ^7.22.5 - "@types/babel__core": ^7.20.3 + "@babel/core": ^7.23.3 + "@babel/plugin-transform-react-jsx-self": ^7.23.3 + "@babel/plugin-transform-react-jsx-source": ^7.23.3 + "@types/babel__core": ^7.20.4 react-refresh: ^0.14.0 peerDependencies: - vite: ^4.2.0 - checksum: 275132ab1e4c227326396aeee93084f20bbe5f0fbe92d45813f3eacd0766eb6e8cd83ee222f90411aefad1ce60fbd31766a8e4725e7bb36914f2bba37afbdebf + vite: ^4.2.0 || ^5.0.0 + checksum: 515dc270dc433d9d80806501221d152f627aabc342916e9dc0d1d840fec76bc00daf3e41738f9aad286de89ee9325fd423372298bd04a3bfd618601ae62d515d languageName: node linkType: hard @@ -20531,98 +20063,33 @@ __metadata: languageName: node linkType: hard -"@whatwg-node/events@npm:^0.0.2": - version: 0.0.2 - resolution: "@whatwg-node/events@npm:0.0.2" - checksum: 6d491801d36967d5d62443cca6ef39d41cf882d575839d2e9d1a5f394722cd24ef84fe9e897bb72c01bd198871fda9ff0e8b1ac5aa6f3f814f87d92b7f28fdcc +"@whatwg-node/events@npm:^0.1.0": + version: 0.1.1 + resolution: "@whatwg-node/events@npm:0.1.1" + checksum: 3a356ca23522190201e27446cfd7ebf1cf96815ddb9d1ba5da0a00bbe6c1d28b4094862104411101fbedd47c758b25fe3683033f6a3e80933029efd664c33567 languageName: node linkType: hard -"@whatwg-node/fetch@npm:0.5.3, @whatwg-node/fetch@npm:^0.5.0": - version: 0.5.3 - resolution: "@whatwg-node/fetch@npm:0.5.3" +"@whatwg-node/fetch@npm:^0.9.0": + version: 0.9.14 + resolution: "@whatwg-node/fetch@npm:0.9.14" dependencies: - "@peculiar/webcrypto": ^1.4.0 - abort-controller: ^3.0.0 - busboy: ^1.6.0 - form-data-encoder: ^1.7.1 - formdata-node: ^4.3.1 - node-fetch: ^2.6.7 - undici: ^5.12.0 - web-streams-polyfill: ^3.2.0 - checksum: 73087779b3b0e70d0abf8b2a5d82919c29c26f8062e16db0cad413fe45c7b58c3c12cc2bcd5942aebdfdc4feee97b01cf1ff6c5d92d9507a140afdcafa410b12 + "@whatwg-node/node-fetch": ^0.5.0 + urlpattern-polyfill: ^9.0.0 + checksum: 9dc7c49742df03f8072e8caa1c2f602f9487ee5fd42c8daa23da24efe73c538f452f15852a6ce4aa12a933b70ce4c8b1fbd036a065b7e18ffbffa9b29f403746 languageName: node linkType: hard -"@whatwg-node/fetch@npm:^0.2.4": - version: 0.2.6 - resolution: "@whatwg-node/fetch@npm:0.2.6" +"@whatwg-node/node-fetch@npm:^0.5.0": + version: 0.5.0 + resolution: "@whatwg-node/node-fetch@npm:0.5.0" dependencies: - "@peculiar/webcrypto": ^1.4.0 - abort-controller: ^3.0.0 - busboy: ^1.6.0 - event-target-polyfill: ^0.0.3 - form-data-encoder: ^1.7.1 - formdata-node: ^4.3.1 - node-fetch: ^2.6.7 - undici: ^5.8.0 - web-streams-polyfill: ^3.2.0 - checksum: 12ee718be802860fbde2647ec0139dba598a278b0248326c0a314591b7096c84c34b16f5317273b0b11f3bbc6ff0d5d1df08983b4e9f5c3f0d779fde727f21af - languageName: node - linkType: hard - -"@whatwg-node/fetch@npm:^0.8.0": - version: 0.8.1 - resolution: "@whatwg-node/fetch@npm:0.8.1" - dependencies: - "@peculiar/webcrypto": ^1.4.0 - "@whatwg-node/node-fetch": ^0.3.0 - busboy: ^1.6.0 - urlpattern-polyfill: ^6.0.2 - web-streams-polyfill: ^3.2.1 - checksum: b827ac2299676705d98d31be4b68e70741200618b38daaae0d70e587f61fae573854170e2ca219d64bbd910b96960e26b64aa9869e9194a4d162e2a751d6f7a7 - languageName: node - linkType: hard - -"@whatwg-node/node-fetch@npm:^0.3.0": - version: 0.3.0 - resolution: "@whatwg-node/node-fetch@npm:0.3.0" - dependencies: - "@whatwg-node/events": ^0.0.2 + "@whatwg-node/events": ^0.1.0 busboy: ^1.6.0 fast-querystring: ^1.1.1 fast-url-parser: ^1.1.3 tslib: ^2.3.1 - peerDependencies: - "@types/node": ^18.0.6 - checksum: 141deb3f44d1978218c64ca285120b3e2427159773056774f2251f9d5d418c8e1d6f27f4b593d031ff4124f9cd00cb4bd9fd681e4528c9f498c72356a520b69f - languageName: node - linkType: hard - -"@wry/context@npm:^0.7.0, @wry/context@npm:^0.7.3": - version: 0.7.3 - resolution: "@wry/context@npm:0.7.3" - dependencies: - tslib: ^2.3.0 - checksum: 91c1e9eee9046c48ff857d60dcbb59f22246ce0f9bb2d9b190e0555227e7ba3f86024032cc057f3f5141d3bee93fc6b2a15ce2c79fa512569d3432eb8e1af02b - languageName: node - linkType: hard - -"@wry/equality@npm:^0.5.6": - version: 0.5.6 - resolution: "@wry/equality@npm:0.5.6" - dependencies: - tslib: ^2.3.0 - checksum: 9addf8891bdff5e23eecff03641846e7a56c1de3c9362c25e69c0b2ee3303e74b22e9a0376920283cd9d3bdd1bada12df54be5eaa29c2d801d33d94992672e14 - languageName: node - linkType: hard - -"@wry/trie@npm:^0.4.3": - version: 0.4.3 - resolution: "@wry/trie@npm:0.4.3" - dependencies: - tslib: ^2.3.0 - checksum: 106e021125cfafd22250a6631a0438a6a3debae7bd73f6db87fe42aa0757fe67693db0dfbe200ae1f60ba608c3e09ddb8a4e2b3527d56ed0a7e02aa0ee4c94e1 + checksum: 74350f16415be5f1b33460bd50a2c05b721cfb1e90eafddccf81c64267ac3ea3265c8792da815fef0f6132e882a6eacdc71bab926a5a9023570ddfece32e0b29 languageName: node linkType: hard @@ -20874,7 +20341,7 @@ __metadata: languageName: node linkType: hard -"ajv-errors@npm:~3.0.0": +"ajv-errors@npm:^3.0.0, ajv-errors@npm:~3.0.0": version: 3.0.0 resolution: "ajv-errors@npm:3.0.0" peerDependencies: @@ -20931,7 +20398,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^6.10.1, ajv@npm:^6.12.2, ajv@npm:^6.12.4, ajv@npm:^6.12.5, ajv@npm:^6.5.5, ajv@npm:~6.12.6": +"ajv@npm:^6.12.2, ajv@npm:^6.12.4, ajv@npm:^6.12.5, ajv@npm:^6.5.5, ajv@npm:~6.12.6": version: 6.12.6 resolution: "ajv@npm:6.12.6" dependencies: @@ -20943,7 +20410,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^8.0.0, ajv@npm:^8.10.0, ajv@npm:^8.11.2, ajv@npm:^8.12.0, ajv@npm:^8.6.0, ajv@npm:^8.6.3, ajv@npm:^8.8.0, ajv@npm:^8.8.2": +"ajv@npm:^8.0.0, ajv@npm:^8.10.0, ajv@npm:^8.11.0, ajv@npm:^8.11.2, ajv@npm:^8.12.0, ajv@npm:^8.6.0, ajv@npm:^8.6.3, ajv@npm:^8.8.0, ajv@npm:^8.8.2": version: 8.12.0 resolution: "ajv@npm:8.12.0" dependencies: @@ -21010,7 +20477,7 @@ __metadata: languageName: node linkType: hard -"ansi-escapes@npm:^4.2.1, ansi-escapes@npm:^4.3.0": +"ansi-escapes@npm:^4.2.1": version: 4.3.2 resolution: "ansi-escapes@npm:4.3.2" dependencies: @@ -21156,7 +20623,21 @@ __metadata: languageName: node linkType: hard -"archiver@npm:^5.0.2, archiver@npm:^5.3.1": +"archiver-utils@npm:^4.0.1": + version: 4.0.1 + resolution: "archiver-utils@npm:4.0.1" + dependencies: + glob: ^8.0.0 + graceful-fs: ^4.2.0 + lazystream: ^1.0.0 + lodash: ^4.17.15 + normalize-path: ^3.0.0 + readable-stream: ^3.6.0 + checksum: 2917cdf63a912c74002a4a1e6de3076a4691030b4e722efdd6d862447b61cd64c8b7688d331b1d35f8d4fc661d6e34f91bc1ffc79478fca2e48ad060acece18c + languageName: node + linkType: hard + +"archiver@npm:^5.3.1": version: 5.3.2 resolution: "archiver@npm:5.3.2" dependencies: @@ -21171,6 +20652,21 @@ __metadata: languageName: node linkType: hard +"archiver@npm:^6.0.0": + version: 6.0.1 + resolution: "archiver@npm:6.0.1" + dependencies: + archiver-utils: ^4.0.1 + async: ^3.2.4 + buffer-crc32: ^0.2.1 + readable-stream: ^3.6.0 + readdir-glob: ^1.1.2 + tar-stream: ^3.0.0 + zip-stream: ^5.0.1 + checksum: 20549eef7366173440a86873387412226568744a410626f826998b0dda85fe84e739c542d9db9aca3923b772436eb795eafdff29c2983e683355fdd9faaa0fdb + languageName: node + linkType: hard + "are-we-there-yet@npm:^2.0.0": version: 2.0.0 resolution: "are-we-there-yet@npm:2.0.0" @@ -21284,13 +20780,6 @@ __metadata: languageName: node linkType: hard -"array-ify@npm:^1.0.0": - version: 1.0.0 - resolution: "array-ify@npm:1.0.0" - checksum: c0502015b319c93dd4484f18036bcc4b654eb76a4aa1f04afbcef11ac918859bb1f5d71ba1f0f1141770db9eef1a4f40f1761753650873068010bbf7bcdae4a4 - languageName: node - linkType: hard - "array-includes@npm:^3.1.6, array-includes@npm:^3.1.7": version: 3.1.7 resolution: "array-includes@npm:3.1.7" @@ -21418,17 +20907,6 @@ __metadata: languageName: node linkType: hard -"asn1js@npm:^3.0.1, asn1js@npm:^3.0.5": - version: 3.0.5 - resolution: "asn1js@npm:3.0.5" - dependencies: - pvtsutils: ^1.3.2 - pvutils: ^1.1.3 - tslib: ^2.4.0 - checksum: 3b6af1bbadd5762ef8ead5daf2f6bda1bc9e23bc825c4dcc996aa1f9521ad7390a64028565d95d98090d69c8431f004c71cccb866004759169d7c203cf9075eb - languageName: node - linkType: hard - "assert-plus@npm:1.0.0, assert-plus@npm:^1.0.0": version: 1.0.0 resolution: "assert-plus@npm:1.0.0" @@ -21522,7 +21000,7 @@ __metadata: languageName: node linkType: hard -"async-retry@npm:^1.2.1, async-retry@npm:^1.3.3": +"async-retry@npm:^1.3.3": version: 1.3.3 resolution: "async-retry@npm:1.3.3" dependencies: @@ -21594,13 +21072,6 @@ __metadata: languageName: node linkType: hard -"auto-bind@npm:~4.0.0": - version: 4.0.0 - resolution: "auto-bind@npm:4.0.0" - checksum: 00cad71cce5742faccb7dd65c1b55ebc4f45add4b0c9a1547b10b05bab22813230133b0c892c67ba3eb969a4524710c5e43cc45c72898ec84e56f3a596e7a04f - languageName: node - linkType: hard - "autolinker@npm:^3.11.0": version: 3.16.2 resolution: "autolinker@npm:3.16.2" @@ -21617,7 +21088,7 @@ __metadata: languageName: node linkType: hard -"avsc@npm:^5.7.3": +"avsc@npm:^5.7.5, avsc@npm:^5.7.6": version: 5.7.7 resolution: "avsc@npm:5.7.7" checksum: e3361aa88a61397b3345876263f79c8c8bfe013d849142202758205459a37e24cdbf02edc49ae019d6e82d93bbc7bc73e9e7fefca049aae91626bae28de4d1a9 @@ -21747,6 +21218,13 @@ __metadata: languageName: node linkType: hard +"b4a@npm:^1.6.4": + version: 1.6.4 + resolution: "b4a@npm:1.6.4" + checksum: 81b086f9af1f8845fbef4476307236bda3d660c158c201db976f19cdce05f41f93110ab6b12fd7a2696602a490cc43d5410ee36a56d6eef93afb0d6ca69ac3b2 + languageName: node + linkType: hard + "babel-core@npm:^7.0.0-bridge.0": version: 7.0.0-bridge.0 resolution: "babel-core@npm:7.0.0-bridge.0" @@ -21867,13 +21345,6 @@ __metadata: languageName: node linkType: hard -"babel-plugin-syntax-trailing-function-commas@npm:^7.0.0-beta.0": - version: 7.0.0-beta.0 - resolution: "babel-plugin-syntax-trailing-function-commas@npm:7.0.0-beta.0" - checksum: e37509156ca945dd9e4b82c66dd74f2d842ad917bd280cb5aa67960942300cd065eeac476d2514bdcdedec071277a358f6d517c31d9f9244d9bbc3619a8ecf8a - languageName: node - linkType: hard - "babel-polyfill@npm:^6.26.0": version: 6.26.0 resolution: "babel-polyfill@npm:6.26.0" @@ -21907,43 +21378,6 @@ __metadata: languageName: node linkType: hard -"babel-preset-fbjs@npm:^3.4.0": - version: 3.4.0 - resolution: "babel-preset-fbjs@npm:3.4.0" - dependencies: - "@babel/plugin-proposal-class-properties": ^7.0.0 - "@babel/plugin-proposal-object-rest-spread": ^7.0.0 - "@babel/plugin-syntax-class-properties": ^7.0.0 - "@babel/plugin-syntax-flow": ^7.0.0 - "@babel/plugin-syntax-jsx": ^7.0.0 - "@babel/plugin-syntax-object-rest-spread": ^7.0.0 - "@babel/plugin-transform-arrow-functions": ^7.0.0 - "@babel/plugin-transform-block-scoped-functions": ^7.0.0 - "@babel/plugin-transform-block-scoping": ^7.0.0 - "@babel/plugin-transform-classes": ^7.0.0 - "@babel/plugin-transform-computed-properties": ^7.0.0 - "@babel/plugin-transform-destructuring": ^7.0.0 - "@babel/plugin-transform-flow-strip-types": ^7.0.0 - "@babel/plugin-transform-for-of": ^7.0.0 - "@babel/plugin-transform-function-name": ^7.0.0 - "@babel/plugin-transform-literals": ^7.0.0 - "@babel/plugin-transform-member-expression-literals": ^7.0.0 - "@babel/plugin-transform-modules-commonjs": ^7.0.0 - "@babel/plugin-transform-object-super": ^7.0.0 - "@babel/plugin-transform-parameters": ^7.0.0 - "@babel/plugin-transform-property-literals": ^7.0.0 - "@babel/plugin-transform-react-display-name": ^7.0.0 - "@babel/plugin-transform-react-jsx": ^7.0.0 - "@babel/plugin-transform-shorthand-properties": ^7.0.0 - "@babel/plugin-transform-spread": ^7.0.0 - "@babel/plugin-transform-template-literals": ^7.0.0 - babel-plugin-syntax-trailing-function-commas: ^7.0.0-beta.0 - peerDependencies: - "@babel/core": ^7.0.0 - checksum: b3352cf690729125997f254bc31b9c4db347f8646f1571958ced1c45f0da89439e183e1c88e35397eb0361b9e1fbb1dd8142d3f4647814deb427e53c54f44d5f - languageName: node - linkType: hard - "babel-preset-jest@npm:^29.6.3": version: 29.6.3 resolution: "babel-preset-jest@npm:29.6.3" @@ -22099,26 +21533,26 @@ __metadata: linkType: hard "better-sqlite3@npm:^9.0.0": - version: 9.1.1 - resolution: "better-sqlite3@npm:9.1.1" + version: 9.2.0 + resolution: "better-sqlite3@npm:9.2.0" dependencies: bindings: ^1.5.0 node-gyp: latest prebuild-install: ^7.1.1 - checksum: b016b225b1c23717acb596848729ca9118d2496c3059643fcf23e11e22e63bf35bd1e61dd5b30c5b649d56df821521aba9c0f2cbad8fc7cdca9f3a4484e7ebcb + checksum: b6e5d8a34b950fa060fc7bb2206ea178d57f1094a2c09e3c7162b03e1cca4b6cf70da4a194fead61233206730154684243211f345de5f1f9a5ad14faf722ee5c languageName: node linkType: hard -"bfj@npm:^7.0.2": - version: 7.1.0 - resolution: "bfj@npm:7.1.0" +"bfj@npm:^8.0.0": + version: 8.0.0 + resolution: "bfj@npm:8.0.0" dependencies: bluebird: ^3.7.2 check-types: ^11.2.3 hoopy: ^0.1.4 jsonpath: ^1.1.1 tryer: ^1.0.1 - checksum: 36da9ed36c60f377a3f43bb0433092af7dc40442914b8155a1330ae86b1905640baf57e9c195ab83b36d6518b27cf8ed880adff663aa444c193be149e027d722 + checksum: f22d49cd2661a92e7526015edac0e02858a881a36438fe4e67df320dddc08cba09e197a7e128f282abc2c26127f5abb3ca8e8b7eff0737df20e5b8c4ee6273e9 languageName: node linkType: hard @@ -22591,10 +22025,10 @@ __metadata: languageName: node linkType: hard -"builtin-modules@npm:^3.0.0": - version: 3.2.0 - resolution: "builtin-modules@npm:3.2.0" - checksum: 0265aa1ba78e1a16f4e18668d815cb43fb364e6a6b8aa9189c6f44c7b894a551a43b323c40206959d2d4b2568c1f2805607ad6c88adc306a776ce6904cca6715 +"builtin-modules@npm:^3.3.0": + version: 3.3.0 + resolution: "builtin-modules@npm:3.3.0" + checksum: db021755d7ed8be048f25668fe2117620861ef6703ea2c65ed2779c9e3636d5c3b82325bd912244293959ff3ae303afa3471f6a15bf5060c103e4cc3a839749d languageName: node linkType: hard @@ -22863,17 +22297,6 @@ __metadata: languageName: node linkType: hard -"capital-case@npm:^1.0.4": - version: 1.0.4 - resolution: "capital-case@npm:1.0.4" - dependencies: - no-case: ^3.0.4 - tslib: ^2.0.3 - upper-case-first: ^2.0.2 - checksum: 41fa8fa87f6d24d0835a2b4a9341a3eaecb64ac29cd7c5391f35d6175a0fa98ab044e7f2602e1ec3afc886231462ed71b5b80c590b8b41af903ec2c15e5c5931 - languageName: node - linkType: hard - "caseless@npm:~0.12.0": version: 0.12.0 resolution: "caseless@npm:0.12.0" @@ -22881,15 +22304,6 @@ __metadata: languageName: node linkType: hard -"catharsis@npm:^0.9.0": - version: 0.9.0 - resolution: "catharsis@npm:0.9.0" - dependencies: - lodash: ^4.17.15 - checksum: da867df1fd01823ea5a7283886ba382f6eb5b1fe5af356e00fd944a02d9b867f4ea2fc7f61416c53427f62760fdbd41614f6e8ae37686d2c3a4696871526df20 - languageName: node - linkType: hard - "ccount@npm:^2.0.0": version: 2.0.0 resolution: "ccount@npm:2.0.0" @@ -22935,44 +22349,6 @@ __metadata: languageName: node linkType: hard -"change-case-all@npm:1.0.15": - version: 1.0.15 - resolution: "change-case-all@npm:1.0.15" - dependencies: - change-case: ^4.1.2 - is-lower-case: ^2.0.2 - is-upper-case: ^2.0.2 - lower-case: ^2.0.2 - lower-case-first: ^2.0.2 - sponge-case: ^1.0.1 - swap-case: ^2.0.2 - title-case: ^3.0.3 - upper-case: ^2.0.2 - upper-case-first: ^2.0.2 - checksum: e1dabdcd8447a3690f3faf15f92979dfbc113109b50916976e1d5e518e6cfdebee4f05f54d0ca24fb79a4bf835185b59ae25e967bb3dc10bd236a775b19ecc52 - languageName: node - linkType: hard - -"change-case@npm:^4.1.2": - version: 4.1.2 - resolution: "change-case@npm:4.1.2" - dependencies: - camel-case: ^4.1.2 - capital-case: ^1.0.4 - constant-case: ^3.0.4 - dot-case: ^3.0.4 - header-case: ^2.0.4 - no-case: ^3.0.4 - param-case: ^3.0.4 - pascal-case: ^3.1.2 - path-case: ^3.0.4 - sentence-case: ^3.0.4 - snake-case: ^3.0.4 - tslib: ^2.0.3 - checksum: e4bc4a093a1f7cce8b33896665cf9e456e3bc3cc0def2ad7691b1994cfca99b3188d0a513b16855b01a6bd20692fcde12a7d4d87a5615c4c515bbbf0e651f116 - languageName: node - linkType: hard - "change-emitter@npm:^0.1.2": version: 0.1.6 resolution: "change-emitter@npm:0.1.6" @@ -23115,7 +22491,7 @@ __metadata: languageName: node linkType: hard -"ci-info@npm:^3.1.0, ci-info@npm:^3.2.0, ci-info@npm:^3.7.0": +"ci-info@npm:^3.2.0, ci-info@npm:^3.7.0": version: 3.8.0 resolution: "ci-info@npm:3.8.0" checksum: d0a4d3160497cae54294974a7246202244fff031b0a6ea20dd57b10ec510aa17399c41a1b0982142c105f3255aff2173e5c0dd7302ee1b2f28ba3debda375098 @@ -23253,16 +22629,6 @@ __metadata: languageName: node linkType: hard -"cli-truncate@npm:^2.1.0": - version: 2.1.0 - resolution: "cli-truncate@npm:2.1.0" - dependencies: - slice-ansi: ^3.0.0 - string-width: ^4.2.0 - checksum: bf1e4e6195392dc718bf9cd71f317b6300dc4a9191d052f31046b8773230ece4fa09458813bf0e3455a5e68c0690d2ea2c197d14a8b85a7b5e01c97f4b5feb5d - languageName: node - linkType: hard - "cli-truncate@npm:^3.1.0": version: 3.1.0 resolution: "cli-truncate@npm:3.1.0" @@ -23434,13 +22800,6 @@ __metadata: languageName: node linkType: hard -"code-error-fragment@npm:0.0.230": - version: 0.0.230 - resolution: "code-error-fragment@npm:0.0.230" - checksum: 6c5e800d6d70b30938cc85a2fc2c6069f028eadb58bceb65716b995ce6228c99906302f2c438ba50115fd81a1ee15dd95dc7d317b16a6c590e311ac7e50613f3 - languageName: node - linkType: hard - "codemirror-graphql@npm:^2.0.10": version: 2.0.10 resolution: "codemirror-graphql@npm:2.0.10" @@ -23726,7 +23085,7 @@ __metadata: languageName: node linkType: hard -"common-tags@npm:1.8.2, common-tags@npm:^1.8.0": +"common-tags@npm:^1.8.0": version: 1.8.2 resolution: "common-tags@npm:1.8.2" checksum: 767a6255a84bbc47df49a60ab583053bb29a7d9687066a18500a516188a062c4e4cd52de341f22de0b07062e699b1b8fe3cfa1cb55b241cb9301aeb4f45b4dff @@ -23754,16 +23113,6 @@ __metadata: languageName: node linkType: hard -"compare-func@npm:^2.0.0": - version: 2.0.0 - resolution: "compare-func@npm:2.0.0" - dependencies: - array-ify: ^1.0.0 - dot-prop: ^5.1.0 - checksum: fb71d70632baa1e93283cf9d80f30ac97f003aabee026e0b4426c9716678079ef5fea7519b84d012cbed938c476493866a38a79760564a9e21ae9433e40e6f0d - languageName: node - linkType: hard - "compare-versions@npm:4.1.4": version: 4.1.4 resolution: "compare-versions@npm:4.1.4" @@ -23797,6 +23146,18 @@ __metadata: languageName: node linkType: hard +"compress-commons@npm:^5.0.1": + version: 5.0.1 + resolution: "compress-commons@npm:5.0.1" + dependencies: + crc-32: ^1.2.0 + crc32-stream: ^5.0.0 + normalize-path: ^3.0.0 + readable-stream: ^3.6.0 + checksum: 65a68e56211a8d1dbe9dab0d35f1bd60a4df27aa01e6c3f0883080263e228c460758bab4f083637a380d4a96d2326722972a42ea1951360cc69728a3915f209f + languageName: node + linkType: hard + "compressible@npm:^2.0.12, compressible@npm:~2.0.16": version: 2.0.18 resolution: "compressible@npm:2.0.18" @@ -24020,17 +23381,6 @@ __metadata: languageName: node linkType: hard -"constant-case@npm:^3.0.4": - version: 3.0.4 - resolution: "constant-case@npm:3.0.4" - dependencies: - no-case: ^3.0.4 - tslib: ^2.0.3 - upper-case: ^2.0.2 - checksum: 6c3346d51afc28d9fae922e966c68eb77a19d94858dba230dd92d7b918b37d36db50f0311e9ecf6847e43e934b1c01406a0936973376ab17ec2c471fbcfb2cf3 - languageName: node - linkType: hard - "constants-browserify@npm:^1.0.0": version: 1.0.0 resolution: "constants-browserify@npm:1.0.0" @@ -24061,17 +23411,6 @@ __metadata: languageName: node linkType: hard -"conventional-changelog-conventionalcommits@npm:^5.0.0": - version: 5.0.0 - resolution: "conventional-changelog-conventionalcommits@npm:5.0.0" - dependencies: - compare-func: ^2.0.0 - lodash: ^4.17.15 - q: ^1.5.1 - checksum: b67d12e4e0fdde5baa32c3d77af472de38646a18657b26f5543eecce041a318103092fbfcef247e2319a16957c9ac78c6ea78acc11a5db6acf74be79a28c561f - languageName: node - linkType: hard - "convert-source-map@npm:^1.5.0, convert-source-map@npm:^1.6.0": version: 1.9.0 resolution: "convert-source-map@npm:1.9.0" @@ -24171,9 +23510,9 @@ __metadata: linkType: hard "core-js@npm:^3.26.0, core-js@npm:^3.6.5": - version: 3.33.2 - resolution: "core-js@npm:3.33.2" - checksum: 71de081acbd060ff985afdcdf2552de4a00ab3ac4695c77f3535b72ddf4526920dcd0cb73e72e57c2ae16e384838a6d55790e138f0a19d60afcf851f89d0064d + version: 3.33.3 + resolution: "core-js@npm:3.33.3" + checksum: 070b9c696f5a9b22bab0208daf9fcdffbc3b4f4c89ed2be512b7d99d4be363accfbb26fa6eec7261055d89e8ea0a5bcfccad5923fe43f1f2eafca9f568cc5596 languageName: node linkType: hard @@ -24201,18 +23540,6 @@ __metadata: languageName: node linkType: hard -"cosmiconfig@npm:8.0.0": - version: 8.0.0 - resolution: "cosmiconfig@npm:8.0.0" - dependencies: - import-fresh: ^3.2.1 - js-yaml: ^4.1.0 - parse-json: ^5.0.0 - path-type: ^4.0.0 - checksum: ff4cdf89ac1ae52e7520816622c21a9e04380d04b82d653f5139ec581aa4f7f29e096d46770bc76c4a63c225367e88a1dfa233ea791669a35101f5f9b972c7d1 - languageName: node - linkType: hard - "cosmiconfig@npm:^6.0.0": version: 6.0.0 resolution: "cosmiconfig@npm:6.0.0" @@ -24239,6 +23566,23 @@ __metadata: languageName: node linkType: hard +"cosmiconfig@npm:^8.1.0": + version: 8.3.6 + resolution: "cosmiconfig@npm:8.3.6" + dependencies: + import-fresh: ^3.3.0 + js-yaml: ^4.1.0 + parse-json: ^5.2.0 + path-type: ^4.0.0 + peerDependencies: + typescript: ">=4.9.5" + peerDependenciesMeta: + typescript: + optional: true + checksum: dc339ebea427898c9e03bf01b56ba7afbac07fc7d2a2d5a15d6e9c14de98275a9565da949375aee1809591c152c0a3877bb86dbeaf74d5bd5aaa79955ad9e7a0 + languageName: node + linkType: hard + "cpu-features@npm:0.0.2": version: 0.0.2 resolution: "cpu-features@npm:0.0.2" @@ -24271,6 +23615,16 @@ __metadata: languageName: node linkType: hard +"crc32-stream@npm:^5.0.0": + version: 5.0.0 + resolution: "crc32-stream@npm:5.0.0" + dependencies: + crc-32: ^1.2.0 + readable-stream: ^3.4.0 + checksum: 8e5dd04f22f3fbecc623492395107fbed2114f225bd606e39e8ed338f2fc1c454ac02a05741243620ab526473cb867fa86411a44a7ffcd88457cc1c2af82d0bc + languageName: node + linkType: hard + "create-ecdh@npm:^4.0.0": version: 4.0.3 resolution: "create-ecdh@npm:4.0.3" @@ -24350,11 +23704,11 @@ __metadata: linkType: hard "cronstrue@npm:^2.2.0, cronstrue@npm:^2.32.0": - version: 2.43.0 - resolution: "cronstrue@npm:2.43.0" + version: 2.47.0 + resolution: "cronstrue@npm:2.47.0" bin: cronstrue: bin/cli.js - checksum: 4926fe3036bba549b0ddee8c0027104c301d46390f83a235a31f95f31c09a3fc0e47a7fd46e434c3bb74960aa55fb75691197349750e9758b30b014b7cdcc4bb + checksum: a6752c8873fec30cabab4c5b92abde3a625cb5ef1797d9360f762b9e0bb9c0607a09744340faccdbf5b97eaeb5df0ebe9b5c424043fdba9b39799c82404076ec languageName: node linkType: hard @@ -24388,6 +23742,15 @@ __metadata: languageName: node linkType: hard +"cross-inspect@npm:1.0.0": + version: 1.0.0 + resolution: "cross-inspect@npm:1.0.0" + dependencies: + tslib: ^2.4.0 + checksum: 975c81799549627027254eb70f1c349cefb14435d580bea6f351f510c839dcb1a9288983407bac2ad317e6eff29cf1e99299606da21f404562bfa64cec502239 + languageName: node + linkType: hard + "cross-spawn@npm:^5.1.0": version: 5.1.0 resolution: "cross-spawn@npm:5.1.0" @@ -24503,13 +23866,12 @@ __metadata: languageName: node linkType: hard -"css-in-js-utils@npm:^2.0.0": - version: 2.0.1 - resolution: "css-in-js-utils@npm:2.0.1" +"css-in-js-utils@npm:^3.1.0": + version: 3.1.0 + resolution: "css-in-js-utils@npm:3.1.0" dependencies: - hyphenate-style-name: ^1.0.2 - isobject: ^3.0.1 - checksum: c9964c4708216954c468b69bbee2d971fd759ada4f40637b8ca4d3f79caba4818d0532a4f190ac560227c08742ad063ffec7a30afddc4d96b66a18c3a008f0d8 + hyphenate-style-name: ^1.0.3 + checksum: 066318e918c04a5e5bce46b38fe81052ea6ac051bcc6d3c369a1d59ceb1546cb2b6086901ab5d22be084122ee3732169996a3dfb04d3406eaee205af77aec61b languageName: node linkType: hard @@ -24735,7 +24097,7 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^3.0.2, csstype@npm:^3.0.6, csstype@npm:^3.1.2": +"csstype@npm:^3.0.2, csstype@npm:^3.1.2": version: 3.0.9 resolution: "csstype@npm:3.0.9" checksum: 199f9af7e673f9f188525c3102a329d637ff46c52f6385a4427ff5cb17adcb736189150170a7af7c5701d18d7704bdad130273f4aa7e44c6c4f9967e6115dc93 @@ -25010,13 +24372,6 @@ __metadata: languageName: node linkType: hard -"dataloader@npm:2.1.0": - version: 2.1.0 - resolution: "dataloader@npm:2.1.0" - checksum: bbd43496c41697766f8611f60ed3bae437b450985499140b9603a2447c10d45975d3a0661caaebaa9750bc1bc9fd154676a314423294916c8b8ca1a59a08d139 - languageName: node - linkType: hard - "dataloader@npm:^2.0.0, dataloader@npm:^2.2.2": version: 2.2.2 resolution: "dataloader@npm:2.2.2" @@ -25072,7 +24427,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:4.3.4, debug@npm:^4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -25376,7 +24731,7 @@ __metadata: languageName: node linkType: hard -"dependency-graph@npm:0.11.0, dependency-graph@npm:^0.11.0, dependency-graph@npm:~0.11.0": +"dependency-graph@npm:0.11.0, dependency-graph@npm:~0.11.0": version: 0.11.0 resolution: "dependency-graph@npm:0.11.0" checksum: 477204beaa9be69e642bc31ffe7a8c383d0cf48fa27acbc91c5df01431ab913e65c154213d2ef83d034c98d77280743ec85e5da018a97a18dd43d3c0b78b28cd @@ -25769,7 +25124,7 @@ __metadata: languageName: node linkType: hard -"dot-prop@npm:^5.1.0, dot-prop@npm:^5.2.0": +"dot-prop@npm:^5.2.0": version: 5.3.0 resolution: "dot-prop@npm:5.3.0" dependencies: @@ -25808,10 +25163,10 @@ __metadata: languageName: node linkType: hard -"dset@npm:3.1.2, dset@npm:^3.1.2": - version: 3.1.2 - resolution: "dset@npm:3.1.2" - checksum: 4f8066f517aa0a70af688c66e9a0a5590f0aada76f6edc7ba9ddb309e27d3a6d65c0a2e31ab2a84005d4c791e5327773cdde59b8ab169050330a0dc283663e87 +"dset@npm:^3.1.2": + version: 3.1.3 + resolution: "dset@npm:3.1.3" + checksum: 5db964a36c60c51aa3f7088bfe1dc5c0eedd9a6ef3b216935bb70ef4a7b8fc40fd2f9bb16b9a4692c9c9772cea60cfefb108d2d09fbd53c85ea8f6cd54502d6a languageName: node linkType: hard @@ -26526,31 +25881,31 @@ __metadata: linkType: hard "esbuild@npm:^0.19.0": - version: 0.19.5 - resolution: "esbuild@npm:0.19.5" + version: 0.19.8 + resolution: "esbuild@npm:0.19.8" dependencies: - "@esbuild/android-arm": 0.19.5 - "@esbuild/android-arm64": 0.19.5 - "@esbuild/android-x64": 0.19.5 - "@esbuild/darwin-arm64": 0.19.5 - "@esbuild/darwin-x64": 0.19.5 - "@esbuild/freebsd-arm64": 0.19.5 - "@esbuild/freebsd-x64": 0.19.5 - "@esbuild/linux-arm": 0.19.5 - "@esbuild/linux-arm64": 0.19.5 - "@esbuild/linux-ia32": 0.19.5 - "@esbuild/linux-loong64": 0.19.5 - "@esbuild/linux-mips64el": 0.19.5 - "@esbuild/linux-ppc64": 0.19.5 - "@esbuild/linux-riscv64": 0.19.5 - "@esbuild/linux-s390x": 0.19.5 - "@esbuild/linux-x64": 0.19.5 - "@esbuild/netbsd-x64": 0.19.5 - "@esbuild/openbsd-x64": 0.19.5 - "@esbuild/sunos-x64": 0.19.5 - "@esbuild/win32-arm64": 0.19.5 - "@esbuild/win32-ia32": 0.19.5 - "@esbuild/win32-x64": 0.19.5 + "@esbuild/android-arm": 0.19.8 + "@esbuild/android-arm64": 0.19.8 + "@esbuild/android-x64": 0.19.8 + "@esbuild/darwin-arm64": 0.19.8 + "@esbuild/darwin-x64": 0.19.8 + "@esbuild/freebsd-arm64": 0.19.8 + "@esbuild/freebsd-x64": 0.19.8 + "@esbuild/linux-arm": 0.19.8 + "@esbuild/linux-arm64": 0.19.8 + "@esbuild/linux-ia32": 0.19.8 + "@esbuild/linux-loong64": 0.19.8 + "@esbuild/linux-mips64el": 0.19.8 + "@esbuild/linux-ppc64": 0.19.8 + "@esbuild/linux-riscv64": 0.19.8 + "@esbuild/linux-s390x": 0.19.8 + "@esbuild/linux-x64": 0.19.8 + "@esbuild/netbsd-x64": 0.19.8 + "@esbuild/openbsd-x64": 0.19.8 + "@esbuild/sunos-x64": 0.19.8 + "@esbuild/win32-arm64": 0.19.8 + "@esbuild/win32-ia32": 0.19.8 + "@esbuild/win32-x64": 0.19.8 dependenciesMeta: "@esbuild/android-arm": optional: true @@ -26598,7 +25953,7 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 5a0227cf6ffffa3076714d88230af1dfdd2fc363d91bd712a81fb91230c315a395e2c9b7588eee62986aeebf4999804b9b1b59eeab8e2457184eb0056bfe20c8 + checksum: 1dff99482ecbfcc642ec66c71e4dc5c73ce6aef68e8158a4937890b570e86a95959ac47e0f14785ba70df5a673ae4289df88a162e9759b02367ed28074cee8ba languageName: node linkType: hard @@ -26651,7 +26006,7 @@ __metadata: languageName: node linkType: hard -"escodegen@npm:^1.13.0, escodegen@npm:^1.8.1": +"escodegen@npm:^1.8.1": version: 1.14.3 resolution: "escodegen@npm:1.14.3" dependencies: @@ -26869,13 +26224,35 @@ __metadata: linkType: hard "eslint-plugin-testing-library@npm:^6.0.0": - version: 6.1.2 - resolution: "eslint-plugin-testing-library@npm:6.1.2" + version: 6.2.0 + resolution: "eslint-plugin-testing-library@npm:6.2.0" dependencies: "@typescript-eslint/utils": ^5.58.0 peerDependencies: eslint: ^7.5.0 || ^8.0.0 - checksum: 74e6b1bdff52e9a3937be1ae0e3ddb6cfedcd97044ac5275be6e7472c77cf8ae0f6e29fd7d3b90aac1318e22850086e73ee8dde7de8d9034be59cdfed9ba7bd7 + checksum: 7af7e0a1eee44c6ba65ce2ae99f8e46ce709a319f4cce778bb0af2dda5828d78f3a81e8989c7b691a8b9b9fef102b56136209aac700038b9e64794600b0d12db + languageName: node + linkType: hard + +"eslint-plugin-unused-imports@npm:^3.0.0": + version: 3.0.0 + resolution: "eslint-plugin-unused-imports@npm:3.0.0" + dependencies: + eslint-rule-composer: ^0.3.0 + peerDependencies: + "@typescript-eslint/eslint-plugin": ^6.0.0 + eslint: ^8.0.0 + peerDependenciesMeta: + "@typescript-eslint/eslint-plugin": + optional: true + checksum: 51666f62cc8dccba2895ced83f3c1e0b78b68c357e17360e156c4db548bfdeda34cbd8725192fb4903f22d5069400fb22ded6039631df01ee82fd618dc307247 + languageName: node + linkType: hard + +"eslint-rule-composer@npm:^0.3.0": + version: 0.3.0 + resolution: "eslint-rule-composer@npm:0.3.0" + checksum: c2f57cded8d1c8f82483e0ce28861214347e24fd79fd4144667974cd334d718f4ba05080aaef2399e3bbe36f7d6632865110227e6b176ed6daa2d676df9281b1 languageName: node linkType: hard @@ -26923,13 +26300,13 @@ __metadata: linkType: hard "eslint@npm:^8.33.0, eslint@npm:^8.6.0": - version: 8.53.0 - resolution: "eslint@npm:8.53.0" + version: 8.55.0 + resolution: "eslint@npm:8.55.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.6.1 - "@eslint/eslintrc": ^2.1.3 - "@eslint/js": 8.53.0 + "@eslint/eslintrc": ^2.1.4 + "@eslint/js": 8.55.0 "@humanwhocodes/config-array": ^0.11.13 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 @@ -26966,7 +26343,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 2da808655c7aa4b33f8970ba30d96b453c3071cc4d6cd60d367163430677e32ff186b65270816b662d29139283138bff81f28dddeb2e73265495245a316ed02c + checksum: 83f82a604559dc1faae79d28fdf3dfc9e592ca221052e2ea516e1b379b37e77e4597705a16880e2f5ece4f79087c1dd13fd7f6e9746f794a401175519db18b41 languageName: node linkType: hard @@ -26977,7 +26354,7 @@ __metadata: languageName: node linkType: hard -"espree@npm:^9.0.0, espree@npm:^9.6.0, espree@npm:^9.6.1": +"espree@npm:^9.6.0, espree@npm:^9.6.1": version: 9.6.1 resolution: "espree@npm:9.6.1" dependencies: @@ -27047,13 +26424,6 @@ __metadata: languageName: node linkType: hard -"estree-walker@npm:^1.0.1": - version: 1.0.1 - resolution: "estree-walker@npm:1.0.1" - checksum: 7e70da539691f6db03a08e7ce94f394ce2eef4180e136d251af299d41f92fb2d28ebcd9a6e393e3728d7970aeb5358705ddf7209d52fbcb2dd4693f95dcf925f - languageName: node - linkType: hard - "estree-walker@npm:^2.0.1, estree-walker@npm:^2.0.2": version: 2.0.2 resolution: "estree-walker@npm:2.0.2" @@ -27099,13 +26469,6 @@ __metadata: languageName: node linkType: hard -"event-target-polyfill@npm:^0.0.3": - version: 0.0.3 - resolution: "event-target-polyfill@npm:0.0.3" - checksum: 42efefcc46aa4170547b35399337762a579fa27c9fe8b3e791aec470df3126e0bb4cb49b9f17901956eb65a137ef0e35c3a32c9f047b32c64cf56fa9ecc76d06 - languageName: node - linkType: hard - "event-target-shim@npm:^5.0.0": version: 5.0.1 resolution: "event-target-shim@npm:5.0.1" @@ -27187,7 +26550,6 @@ __metadata: "@backstage/plugin-catalog-import": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" "@backstage/plugin-catalog-unprocessed-entities": "workspace:^" - "@backstage/plugin-circleci": "workspace:^" "@backstage/plugin-cloudbuild": "workspace:^" "@backstage/plugin-code-coverage": "workspace:^" "@backstage/plugin-cost-insights": "workspace:^" @@ -27234,6 +26596,7 @@ __metadata: "@backstage/plugin-user-settings": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" + "@circleci/backstage-plugin": ^0.1.1 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 @@ -27296,7 +26659,6 @@ __metadata: "@backstage/plugin-catalog-import": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" "@backstage/plugin-catalog-unprocessed-entities": "workspace:^" - "@backstage/plugin-circleci": "workspace:^" "@backstage/plugin-cloudbuild": "workspace:^" "@backstage/plugin-code-coverage": "workspace:^" "@backstage/plugin-cost-insights": "workspace:^" @@ -27346,6 +26708,7 @@ __metadata: "@backstage/plugin-user-settings": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" + "@circleci/backstage-plugin": ^0.1.1 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 @@ -27374,7 +26737,7 @@ __metadata: react-use: ^17.2.4 vite: ^4.4.9 vite-plugin-html: ^3.2.0 - vite-plugin-node-polyfills: ^0.16.0 + vite-plugin-node-polyfills: ^0.17.0 zen-observable: ^0.10.0 languageName: unknown linkType: soft @@ -27450,7 +26813,6 @@ __metadata: "@backstage/plugin-events-backend": "workspace:^" "@backstage/plugin-events-node": "workspace:^" "@backstage/plugin-explore-backend": "workspace:^" - "@backstage/plugin-graphql-backend": "workspace:^" "@backstage/plugin-jenkins-backend": "workspace:^" "@backstage/plugin-kafka-backend": "workspace:^" "@backstage/plugin-kubernetes-backend": "workspace:^" @@ -27624,8 +26986,8 @@ __metadata: linkType: hard "express-openapi-validator@npm:^5.0.4": - version: 5.1.0 - resolution: "express-openapi-validator@npm:5.1.0" + version: 5.1.1 + resolution: "express-openapi-validator@npm:5.1.1" dependencies: "@apidevtools/json-schema-ref-parser": ^9.1.2 "@types/multer": ^1.4.7 @@ -27642,7 +27004,7 @@ __metadata: multer: ^1.4.5-lts.1 ono: ^7.1.3 path-to-regexp: ^6.2.0 - checksum: 8014636cf7122af318aaa6f91e19ac78e125c691b49a85483264c93ad820790f2d32016a118ac743ae8710a985ef4ca4931f4eab47705f4231564aec487fc271 + checksum: 33392d9f08c477f582675c3a747792380c6b87270cabd26ceea62cb683299cbb6ec4493e8a88ab1a91ba68657876006dc165697b733b8fcba0555c52841d3a39 languageName: node linkType: hard @@ -27771,13 +27133,6 @@ __metadata: languageName: node linkType: hard -"extract-files@npm:^9.0.0": - version: 9.0.0 - resolution: "extract-files@npm:9.0.0" - checksum: c31781d090f8d8f62cc541f1023b39ea863f24bd6fb3d4011922d71cbded70cef8191f2b70b43ec6cb5c5907cdad1dc5e9f29f78228936c10adc239091d8ab64 - languageName: node - linkType: hard - "extsprintf@npm:1.3.0": version: 1.3.0 resolution: "extsprintf@npm:1.3.0" @@ -27813,6 +27168,13 @@ __metadata: languageName: node linkType: hard +"fast-fifo@npm:^1.1.0, fast-fifo@npm:^1.2.0": + version: 1.3.2 + resolution: "fast-fifo@npm:1.3.2" + checksum: 6bfcba3e4df5af7be3332703b69a7898a8ed7020837ec4395bb341bd96cc3a6d86c3f6071dd98da289618cf2234c70d84b2a6f09a33dd6f988b1ff60d8e54275 + languageName: node + linkType: hard + "fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.9": version: 3.2.12 resolution: "fast-glob@npm:3.2.12" @@ -27854,6 +27216,13 @@ __metadata: languageName: node linkType: hard +"fast-loops@npm:^1.1.3": + version: 1.1.3 + resolution: "fast-loops@npm:1.1.3" + checksum: b674378ba2ed8364ca1a00768636e88b22201c8d010fa62a8588a4cace04f90bac46714c13cf638be82b03438d2fe813600da32291fb47297a1bd7fa6cef0cee + languageName: node + linkType: hard + "fast-memoize@npm:^2.5.2": version: 2.5.2 resolution: "fast-memoize@npm:2.5.2" @@ -27862,11 +27231,11 @@ __metadata: linkType: hard "fast-querystring@npm:^1.1.1": - version: 1.1.1 - resolution: "fast-querystring@npm:1.1.1" + version: 1.1.2 + resolution: "fast-querystring@npm:1.1.2" dependencies: fast-decode-uri-component: ^1.0.1 - checksum: 86d2b75b9b299a552353532fb1a542f09730ee2a61e657d68710971d9a2afc9a3c5c7b7e106b6534f4cc506d2ff1c08ab0fda4ae614b4e7720798c9ac2a88e02 + checksum: 7149f82ee9ac39a9c08c7ffe435b9f6deade76ae5e3675fe1835720513e8c4bc541e666b4b7b1c0c07e08f369dcf4828d00f2bee39889a90a168e1439cf27b0b languageName: node linkType: hard @@ -27891,7 +27260,7 @@ __metadata: languageName: node linkType: hard -"fast-text-encoding@npm:^1.0.0, fast-text-encoding@npm:^1.0.3": +"fast-text-encoding@npm:^1.0.0": version: 1.0.3 resolution: "fast-text-encoding@npm:1.0.3" checksum: 3e51365896f06d0dcab128092d095a0037d274deec419fecbd2388bc236d7b387610e0c72f920c6126e00c885ab096fbfaa3645712f5b98f721bef6b064916a8 @@ -27918,14 +27287,14 @@ __metadata: languageName: node linkType: hard -"fast-xml-parser@npm:^4.2.2": - version: 4.2.7 - resolution: "fast-xml-parser@npm:4.2.7" +"fast-xml-parser@npm:^4.3.0": + version: 4.3.2 + resolution: "fast-xml-parser@npm:4.3.2" dependencies: strnum: ^1.0.5 bin: fxparser: src/cli/cli.js - checksum: d8b0c9e04756f6c43fa0399428f30149acadae21350e42e26e8fe98e24e6afa6b9b00aa554453795036b00e9fee974a1b556fe2ba18be391d51a9bf1ab790e7c + checksum: d507ce2efa5fd13d0a5ba28bd76dd68f2fc30ad8748357c37b70f360d19417866d79e35a688af067d5bceaaa796033fa985206aef9692f7a421e1326b6e73309 languageName: node linkType: hard @@ -28404,13 +27773,6 @@ __metadata: languageName: node linkType: hard -"form-data-encoder@npm:^1.7.1": - version: 1.7.1 - resolution: "form-data-encoder@npm:1.7.1" - checksum: a2a360d5588a70d323c12a140c3db23a503a38f0a5d141af1efad579dde9f9fff2e49e5f31f378cb4631518c1ab4a826452c92f0d2869e954b6b2d77b05613e1 - languageName: node - linkType: hard - "form-data@npm:^2.3.2, form-data@npm:^2.5.0": version: 2.5.1 resolution: "form-data@npm:2.5.1" @@ -28462,16 +27824,6 @@ __metadata: languageName: node linkType: hard -"formdata-node@npm:^4.3.1": - version: 4.3.2 - resolution: "formdata-node@npm:4.3.2" - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 4.0.0-beta.1 - checksum: e1d7aae7d579775b813ddc8ea4511fee613552715e81b36afb188d3a65b3d4df2ef69017106079ba52d9ab1e3367fea0206862d8ae64c02008ababdb341d2c3d - languageName: node - linkType: hard - "formidable@npm:^2.1.2": version: 2.1.2 resolution: "formidable@npm:2.1.2" @@ -28766,6 +28118,18 @@ __metadata: languageName: node linkType: hard +"gaxios@npm:^6.0.0, gaxios@npm:^6.0.2": + version: 6.1.1 + resolution: "gaxios@npm:6.1.1" + dependencies: + extend: ^3.0.2 + https-proxy-agent: ^7.0.1 + is-stream: ^2.0.0 + node-fetch: ^2.6.9 + checksum: bb4a4e6c81847b690ee29e01294d2093eb9bb4f9e60bbf81fcc6cd3b274f3c551c50a9bc134e7e7019a9b116eac9d9df6af9f2519c695da7ddd785f36564da72 + languageName: node + linkType: hard + "gcp-metadata@npm:^5.3.0": version: 5.3.0 resolution: "gcp-metadata@npm:5.3.0" @@ -28776,6 +28140,16 @@ __metadata: languageName: node linkType: hard +"gcp-metadata@npm:^6.0.0": + version: 6.1.0 + resolution: "gcp-metadata@npm:6.1.0" + dependencies: + gaxios: ^6.0.0 + json-bigint: ^1.0.0 + checksum: 55de8ae4a6b7664379a093abf7e758ae06e82f244d41bd58d881a470bf34db94c4067ce9e1b425d9455b7705636d5f8baad844e49bb73879c338753ba7785b2b + languageName: node + linkType: hard + "gendocu-public-apis@npm:^1.0.0": version: 1.0.0 resolution: "gendocu-public-apis@npm:1.0.0" @@ -29017,7 +28391,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.0.0, glob@npm:^7.1.1, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.1.7, glob@npm:^7.2.0": +"glob@npm:^7.0.0, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.1.7, glob@npm:^7.2.0": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -29148,7 +28522,7 @@ __metadata: languageName: node linkType: hard -"google-auth-library@npm:^8.0.0, google-auth-library@npm:^8.0.1, google-auth-library@npm:^8.0.2": +"google-auth-library@npm:^8.0.0": version: 8.9.0 resolution: "google-auth-library@npm:8.9.0" dependencies: @@ -29165,29 +28539,36 @@ __metadata: languageName: node linkType: hard -"google-gax@npm:^3.5.7, google-gax@npm:^3.5.8": - version: 3.6.1 - resolution: "google-gax@npm:3.6.1" +"google-auth-library@npm:^9.0.0": + version: 9.2.0 + resolution: "google-auth-library@npm:9.2.0" dependencies: - "@grpc/grpc-js": ~1.8.0 + base64-js: ^1.3.0 + ecdsa-sig-formatter: ^1.0.11 + gaxios: ^6.0.0 + gcp-metadata: ^6.0.0 + gtoken: ^7.0.0 + jws: ^4.0.0 + checksum: 0da686964a769c79b5a1f7e518cb885f7c433edd50c8adf5cc310bfce607235184ebe6f9bc5290618d760c25e4ce1e273d444c9914c815353faa9d9dea37d1b3 + languageName: node + linkType: hard + +"google-gax@npm:^4.0.3, google-gax@npm:^4.0.4": + version: 4.0.5 + resolution: "google-gax@npm:4.0.5" + dependencies: + "@grpc/grpc-js": ~1.9.6 "@grpc/proto-loader": ^0.7.0 "@types/long": ^4.0.0 - "@types/rimraf": ^3.0.2 abort-controller: ^3.0.0 duplexify: ^4.0.0 - fast-text-encoding: ^1.0.3 - google-auth-library: ^8.0.2 - is-stream-ended: ^0.1.4 + google-auth-library: ^9.0.0 node-fetch: ^2.6.1 object-hash: ^3.0.0 - proto3-json-serializer: ^1.0.0 - protobufjs: 7.2.4 - protobufjs-cli: 1.1.1 - retry-request: ^5.0.0 - bin: - compileProtos: build/tools/compileProtos.js - minifyProtoJson: build/tools/minify.js - checksum: 16e5fb211d75c6a4cb4d2e62adba7bbf41d160feba74fe39435a70fc31ef8ebc740af4527a2897abab39a1806d131792b2a761da432ae1b916198c9c43aab36e + proto3-json-serializer: ^2.0.0 + protobufjs: 7.2.5 + retry-request: ^7.0.0 + checksum: d4b5f2fc4a902b29d23552ab0fa498785ce88516ff07f7e7f08cac0f6572a78113a7f468f47b17e98d235d4049eeda8d77cfcad6291f6d14bda39b9eb19f935d languageName: node linkType: hard @@ -29256,7 +28637,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.1.9, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.10, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.10, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.10 resolution: "graceful-fs@npm:4.2.10" checksum: 3f109d70ae123951905d85032ebeae3c2a5a7a997430df00ea30df0e3a6c60cf6689b109654d6fdacd28810a053348c4d14642da1d075049e6be1ba5216218da @@ -29277,9 +28658,9 @@ __metadata: languageName: node linkType: hard -"graphiql@npm:3.0.9, graphiql@npm:^3.0.6": - version: 3.0.9 - resolution: "graphiql@npm:3.0.9" +"graphiql@npm:3.0.10, graphiql@npm:^3.0.6": + version: 3.0.10 + resolution: "graphiql@npm:3.0.10" dependencies: "@graphiql/react": ^0.20.2 "@graphiql/toolkit": ^0.9.1 @@ -29289,7 +28670,7 @@ __metadata: graphql: ^15.5.0 || ^16.0.0 react: ^16.8.0 || ^17 || ^18 react-dom: ^16.8.0 || ^17 || ^18 - checksum: 4431842ddcee548bb0aacbe6c8d2eaf3a8cd34fcdb584d98e0983dec21bdeeeaee4550c80a34debd290aebbd8535dae488d2d0beb85e1cb59b89ba4ed08ef32c + checksum: f85b5e82cd2280325dedb28d42580119df46b6724a913a571b7a8183c2bf23d4832edf45570d6c8a0af18ba576f50c9b39219a8537277cba626f0411e6ed55bb languageName: node linkType: hard @@ -29302,20 +28683,20 @@ __metadata: languageName: node linkType: hard -"graphql-config@npm:^4.5.0": - version: 4.5.0 - resolution: "graphql-config@npm:4.5.0" +"graphql-config@npm:^5.0.2": + version: 5.0.3 + resolution: "graphql-config@npm:5.0.3" dependencies: - "@graphql-tools/graphql-file-loader": ^7.3.7 - "@graphql-tools/json-file-loader": ^7.3.7 - "@graphql-tools/load": ^7.5.5 - "@graphql-tools/merge": ^8.2.6 - "@graphql-tools/url-loader": ^7.9.7 - "@graphql-tools/utils": ^9.0.0 - cosmiconfig: 8.0.0 - jiti: 1.17.1 - minimatch: 4.2.3 - string-env-interpolation: 1.0.1 + "@graphql-tools/graphql-file-loader": ^8.0.0 + "@graphql-tools/json-file-loader": ^8.0.0 + "@graphql-tools/load": ^8.0.0 + "@graphql-tools/merge": ^9.0.0 + "@graphql-tools/url-loader": ^8.0.0 + "@graphql-tools/utils": ^10.0.0 + cosmiconfig: ^8.1.0 + jiti: ^1.18.2 + minimatch: ^4.2.3 + string-env-interpolation: ^1.0.1 tslib: ^2.4.0 peerDependencies: cosmiconfig-toml-loader: ^1.0.0 @@ -29323,7 +28704,7 @@ __metadata: peerDependenciesMeta: cosmiconfig-toml-loader: optional: true - checksum: 8ab1a3ce3534598ddac2df213b6af2eecd9ebcca2268d39cc3e87a6e55749483389a6df222e9e0acd638dd2479378a5c8e8d90f980e6a54e700c4c4ae3522123 + checksum: 3d079d48ccc624d16bee58d15802267d65e856f4d1ba278ededb3ac66a565d4f205cd60ac1f19ed8159bfa2d944c453ae58512c6513a8004754bea9964924485 languageName: node linkType: hard @@ -29350,34 +28731,6 @@ __metadata: languageName: node linkType: hard -"graphql-modules@npm:^2.0.0": - version: 2.3.0 - resolution: "graphql-modules@npm:2.3.0" - dependencies: - "@graphql-tools/schema": ^10.0.0 - "@graphql-tools/wrap": ^10.0.0 - "@graphql-typed-document-node/core": ^3.1.0 - ramda: ^0.29.0 - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 - checksum: aea97b00535914d472c544a9e104091b7208f56634f622471bd8389e7702483cdff4f38fd0877f1c9ebb93d3fabed443b10e49d88f0624642271a5d1479d971e - languageName: node - linkType: hard - -"graphql-request@npm:^5.0.0": - version: 5.1.0 - resolution: "graphql-request@npm:5.1.0" - dependencies: - "@graphql-typed-document-node/core": ^3.1.1 - cross-fetch: ^3.1.5 - extract-files: ^9.0.0 - form-data: ^3.0.0 - peerDependencies: - graphql: 14 - 16 - checksum: 8b65d5c1b0cad8996a843b52305b2712ffbf842c700487d4cee1ed719f22baacaacfddafb65572bcddd67d57fd1d2d389dee2430ffba4b34c3ab542d079446c7 - languageName: node - linkType: hard - "graphql-subscriptions@npm:^1.1.0": version: 1.2.1 resolution: "graphql-subscriptions@npm:1.2.1" @@ -29389,7 +28742,7 @@ __metadata: languageName: node linkType: hard -"graphql-tag@npm:^2.10.3, graphql-tag@npm:^2.11.0, graphql-tag@npm:^2.12.6": +"graphql-tag@npm:^2.10.3, graphql-tag@npm:^2.12.6": version: 2.12.6 resolution: "graphql-tag@npm:2.12.6" dependencies: @@ -29400,15 +28753,6 @@ __metadata: languageName: node linkType: hard -"graphql-type-json@npm:^0.3.2": - version: 0.3.2 - resolution: "graphql-type-json@npm:0.3.2" - peerDependencies: - graphql: ">=0.8.0" - checksum: 41620699637a5294937bd61d6e2696edea5a1279ef3d8f4b33716a910635595435381ccd1b74c6fae62c2bc81064c62ae27d3559c8380c0f99bdfdc8ecb249b0 - languageName: node - linkType: hard - "graphql-voyager@npm:^1.0.0-rc.31": version: 1.0.0-rc.31 resolution: "graphql-voyager@npm:1.0.0-rc.31" @@ -29430,16 +28774,7 @@ __metadata: languageName: node linkType: hard -"graphql-ws@npm:5.11.2": - version: 5.11.2 - resolution: "graphql-ws@npm:5.11.2" - peerDependencies: - graphql: ">=0.11 <=16" - checksum: 2c94b06c1919217dc15a0556474673de7aabcc7179a2982a87ded51856c105e4f4ee6d54a6c135a0a7f55d85a5997a6a15cff514959258885814adec6a61ff00 - languageName: node - linkType: hard - -"graphql-ws@npm:^5.4.1, graphql-ws@npm:^5.9.0": +"graphql-ws@npm:^5.14.0, graphql-ws@npm:^5.4.1, graphql-ws@npm:^5.9.0": version: 5.14.2 resolution: "graphql-ws@npm:5.14.2" peerDependencies: @@ -29504,6 +28839,16 @@ __metadata: languageName: node linkType: hard +"gtoken@npm:^7.0.0": + version: 7.0.1 + resolution: "gtoken@npm:7.0.1" + dependencies: + gaxios: ^6.0.0 + jws: ^4.0.0 + checksum: de1f65ebe77deb90931c29c76408e6bd097ac6f8d0b520164ac13449b39012ea8d710596d5a63ae508b2c9e49ef9f92cd7817d6fc97140668ba2e1ff30e2d418 + languageName: node + linkType: hard + "gzip-size@npm:^6.0.0": version: 6.0.0 resolution: "gzip-size@npm:6.0.0" @@ -29717,16 +29062,6 @@ __metadata: languageName: node linkType: hard -"header-case@npm:^2.0.4": - version: 2.0.4 - resolution: "header-case@npm:2.0.4" - dependencies: - capital-case: ^1.0.4 - tslib: ^2.0.3 - checksum: 571c83eeb25e8130d172218712f807c0b96d62b020981400bccc1503a7cf14b09b8b10498a962d2739eccf231d950e3848ba7d420b58a6acd2f9283439546cd9 - languageName: node - linkType: hard - "headers-polyfill@npm:3.2.5": version: 3.2.5 resolution: "headers-polyfill@npm:3.2.5" @@ -29734,6 +29069,13 @@ __metadata: languageName: node linkType: hard +"headers-polyfill@npm:^4.0.1": + version: 4.0.2 + resolution: "headers-polyfill@npm:4.0.2" + checksum: a95280ed58df429fc86c4f49b21596be3ea3f5f3d790e7d75238668df9b90b292f15a968c7c19ae1db88c0ae036dd1bf363a71b8e771199d82848e2d8b3c6c2e + languageName: node + linkType: hard + "helmet@npm:^6.0.0": version: 6.0.1 resolution: "helmet@npm:6.0.1" @@ -30290,13 +29632,6 @@ __metadata: languageName: node linkType: hard -"immutable@npm:~3.7.6": - version: 3.7.6 - resolution: "immutable@npm:3.7.6" - checksum: 8cccfb22d3ecf14fe0c474612e96d6bb5d117493e7639fe6642fb81e78c9ac4b698dd8a322c105001a709ad873ffc90e30bad7db5d9a3ef0b54a6e1db0258e8e - languageName: node - linkType: hard - "import-cwd@npm:^3.0.0": version: 3.0.0 resolution: "import-cwd@npm:3.0.0" @@ -30306,7 +29641,7 @@ __metadata: languageName: node linkType: hard -"import-fresh@npm:^3.1.0, import-fresh@npm:^3.2.1": +"import-fresh@npm:^3.1.0, import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0": version: 3.3.0 resolution: "import-fresh@npm:3.3.0" dependencies: @@ -30316,13 +29651,6 @@ __metadata: languageName: node linkType: hard -"import-from@npm:4.0.0": - version: 4.0.0 - resolution: "import-from@npm:4.0.0" - checksum: 1fa29c05b048da18914e91d9a529e5d9b91774bebbfab10e53f59bcc1667917672b971cf102fee857f142e5e433ce69fa1f0a596e1c7d82f9947a5ec352694b9 - languageName: node - linkType: hard - "import-from@npm:^3.0.0": version: 3.0.0 resolution: "import-from@npm:3.0.0" @@ -30447,12 +29775,13 @@ __metadata: languageName: node linkType: hard -"inline-style-prefixer@npm:^6.0.0": - version: 6.0.0 - resolution: "inline-style-prefixer@npm:6.0.0" +"inline-style-prefixer@npm:^7.0.0": + version: 7.0.0 + resolution: "inline-style-prefixer@npm:7.0.0" dependencies: - css-in-js-utils: ^2.0.0 - checksum: 1331a6184bed03d145e3b9a98363fc7a245590ea1a495df7376a99386737893d4318f8ecf873e2be8431cff1de91512b7a4b9e36326933d5647db0088b63ef4f + css-in-js-utils: ^3.1.0 + fast-loops: ^1.1.3 + checksum: 89fd73eb06e7392e24032ea33b8b33ae7f9a24298f2d9ebbf7b31a3a3934247270047f4f49a454a363aace14e25c3a20fd97465405b0399cc888e5a2bc04ec05 languageName: node linkType: hard @@ -30605,16 +29934,6 @@ __metadata: languageName: node linkType: hard -"is-absolute@npm:^1.0.0": - version: 1.0.0 - resolution: "is-absolute@npm:1.0.0" - dependencies: - is-relative: ^1.0.0 - is-windows: ^1.0.1 - checksum: 9d16b2605eda3f3ce755410f1d423e327ad3a898bcb86c9354cf63970ed3f91ba85e9828aa56f5d6a952b9fae43d0477770f78d37409ae8ecc31e59ebc279b27 - languageName: node - linkType: hard - "is-admin@npm:^3.0.0": version: 3.0.0 resolution: "is-admin@npm:3.0.0" @@ -30744,12 +30063,12 @@ __metadata: languageName: node linkType: hard -"is-builtin-module@npm:^3.1.0": - version: 3.1.0 - resolution: "is-builtin-module@npm:3.1.0" +"is-builtin-module@npm:^3.2.1": + version: 3.2.1 + resolution: "is-builtin-module@npm:3.2.1" dependencies: - builtin-modules: ^3.0.0 - checksum: f1e5dd2cd5f252d4d799b20a0c8c4f7e9c399c4d141749af76ca0121058d4062c3015d026f1b1409dd3d2a4ddfb9b15cf6eb9c370fed53fea8652ce35b5e95cb + builtin-modules: ^3.3.0 + checksum: e8f0ffc19a98240bda9c7ada84d846486365af88d14616e737d280d378695c8c448a621dcafc8332dbf0fcd0a17b0763b845400709963fa9151ddffece90ae88 languageName: node linkType: hard @@ -30771,17 +30090,6 @@ __metadata: languageName: node linkType: hard -"is-ci@npm:^3.0.1": - version: 3.0.1 - resolution: "is-ci@npm:3.0.1" - dependencies: - ci-info: ^3.2.0 - bin: - is-ci: bin.js - checksum: 192c66dc7826d58f803ecae624860dccf1899fc1f3ac5505284c0a5cf5f889046ffeb958fa651e5725d5705c5bcb14f055b79150ea5fcad7456a9569de60260e - languageName: node - linkType: hard - "is-core-module@npm:^2.1.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1, is-core-module@npm:^2.9.0": version: 2.13.1 resolution: "is-core-module@npm:2.13.1" @@ -30879,7 +30187,7 @@ __metadata: languageName: node linkType: hard -"is-glob@npm:4.0.3, is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": +"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": version: 4.0.3 resolution: "is-glob@npm:4.0.3" dependencies: @@ -30933,15 +30241,6 @@ __metadata: languageName: node linkType: hard -"is-lower-case@npm:^2.0.2": - version: 2.0.2 - resolution: "is-lower-case@npm:2.0.2" - dependencies: - tslib: ^2.0.3 - checksum: ba57dd1201e15fd9b590654736afccf1b3b68e919f40c23ef13b00ebcc639b1d9c2f81fe86415bff3e8eccffec459786c9ac9dc8f3a19cfa4484206c411c1d7d - languageName: node - linkType: hard - "is-map@npm:^2.0.1, is-map@npm:^2.0.2": version: 2.0.2 resolution: "is-map@npm:2.0.2" @@ -31122,15 +30421,6 @@ __metadata: languageName: node linkType: hard -"is-relative@npm:^1.0.0": - version: 1.0.0 - resolution: "is-relative@npm:1.0.0" - dependencies: - is-unc-path: ^1.0.0 - checksum: 3271a0df109302ef5e14a29dcd5d23d9788e15ade91a40b942b035827ffbb59f7ce9ff82d036ea798541a52913cbf9d2d0b66456340887b51f3542d57b5a4c05 - languageName: node - linkType: hard - "is-resolvable@npm:^1.1.0": version: 1.1.0 resolution: "is-resolvable@npm:1.1.0" @@ -31186,13 +30476,6 @@ __metadata: languageName: node linkType: hard -"is-stream-ended@npm:^0.1.4": - version: 0.1.4 - resolution: "is-stream-ended@npm:0.1.4" - checksum: 56cbc9cfa0a77877777a3df9e186abb5b0ca73dcbcaf0fd87ed573fb8f8e61283abec0fc072c9e3412336edc04449439b8a128d2bcc6c2797158de5465cfaf85 - languageName: node - linkType: hard - "is-stream@npm:^1.0.1, is-stream@npm:^1.1.0": version: 1.1.0 resolution: "is-stream@npm:1.1.0" @@ -31257,15 +30540,6 @@ __metadata: languageName: node linkType: hard -"is-unc-path@npm:^1.0.0": - version: 1.0.0 - resolution: "is-unc-path@npm:1.0.0" - dependencies: - unc-path-regex: ^0.1.2 - checksum: e8abfde203f7409f5b03a5f1f8636e3a41e78b983702ef49d9343eb608cdfe691429398e8815157519b987b739bcfbc73ae7cf4c8582b0ab66add5171088eab6 - languageName: node - linkType: hard - "is-unicode-supported@npm:^0.1.0": version: 0.1.0 resolution: "is-unicode-supported@npm:0.1.0" @@ -31273,15 +30547,6 @@ __metadata: languageName: node linkType: hard -"is-upper-case@npm:^2.0.2": - version: 2.0.2 - resolution: "is-upper-case@npm:2.0.2" - dependencies: - tslib: ^2.0.3 - checksum: cf4fd43c00c2e72cd5cff911923070b89f0933b464941bd782e2315385f80b5a5acd772db3b796542e5e3cfed735f4dffd88c54d62db1ebfc5c3daa7b1af2bc6 - languageName: node - linkType: hard - "is-url@npm:^1.2.4": version: 1.2.4 resolution: "is-url@npm:1.2.4" @@ -31322,7 +30587,7 @@ __metadata: languageName: node linkType: hard -"is-windows@npm:^1.0.0, is-windows@npm:^1.0.1": +"is-windows@npm:^1.0.0": version: 1.0.2 resolution: "is-windows@npm:1.0.2" checksum: 438b7e52656fe3b9b293b180defb4e448088e7023a523ec21a91a80b9ff8cdb3377ddb5b6e60f7c7de4fa8b63ab56e121b6705fe081b3cf1b828b0a380009ad7 @@ -31432,16 +30697,6 @@ __metadata: languageName: node linkType: hard -"isomorphic-fetch@npm:^3.0.0": - version: 3.0.0 - resolution: "isomorphic-fetch@npm:3.0.0" - dependencies: - node-fetch: ^2.6.1 - whatwg-fetch: ^3.4.1 - checksum: e5ab79a56ce5af6ddd21265f59312ad9a4bc5a72cebc98b54797b42cb30441d5c5f8d17c5cd84a99e18101c8af6f90c081ecb8d12fd79e332be1778d58486d75 - languageName: node - linkType: hard - "isomorphic-form-data@npm:^2.0.0": version: 2.0.0 resolution: "isomorphic-form-data@npm:2.0.0" @@ -32227,21 +31482,12 @@ __metadata: languageName: node linkType: hard -"jiti@npm:1.17.1": - version: 1.17.1 - resolution: "jiti@npm:1.17.1" +"jiti@npm:^1.18.2": + version: 1.21.0 + resolution: "jiti@npm:1.21.0" bin: jiti: bin/jiti.js - checksum: 56c6d8488e7e9cc6ee66a0f0d5e18db6669cb12b2e93364f393442289a9bc75a8e8c796249f59015e01c3ebdf9478e2ca8b76c30e29072c678ee00d39de757c7 - languageName: node - linkType: hard - -"jiti@npm:^1.17.1": - version: 1.17.2 - resolution: "jiti@npm:1.17.2" - bin: - jiti: bin/jiti.js - checksum: 51941fea3622d1ff80d914ec6ec95ae463ede598a4a2317f1e8ff018823212eba6b9ea1c638c97c18f681870b1c2b9f49fbb13021b7c2415c46c8a3b1910f1e3 + checksum: a7bd5d63921c170eaec91eecd686388181c7828e1fa0657ab374b9372bfc1f383cf4b039e6b272383d5cb25607509880af814a39abdff967322459cca41f2961 languageName: node linkType: hard @@ -32350,15 +31596,6 @@ __metadata: languageName: node linkType: hard -"js2xmlparser@npm:^4.0.2": - version: 4.0.2 - resolution: "js2xmlparser@npm:4.0.2" - dependencies: - xmlcreate: ^2.0.4 - checksum: 55e3af71dc0104941dfc3e85452230db42ff3870a5777d1ea26bc0c68743f49113a517a7b305421a932b29f10058a012a7da8f5ba07860a05a1dce9fe5b62962 - languageName: node - linkType: hard - "jsbn@npm:~0.1.0": version: 0.1.1 resolution: "jsbn@npm:0.1.1" @@ -32422,31 +31659,6 @@ __metadata: languageName: node linkType: hard -"jsdoc@npm:^4.0.0": - version: 4.0.2 - resolution: "jsdoc@npm:4.0.2" - dependencies: - "@babel/parser": ^7.20.15 - "@jsdoc/salty": ^0.2.1 - "@types/markdown-it": ^12.2.3 - bluebird: ^3.7.2 - catharsis: ^0.9.0 - escape-string-regexp: ^2.0.0 - js2xmlparser: ^4.0.2 - klaw: ^3.0.0 - markdown-it: ^12.3.2 - markdown-it-anchor: ^8.4.1 - marked: ^4.0.10 - mkdirp: ^1.0.4 - requizzle: ^0.2.3 - strip-json-comments: ^3.1.0 - underscore: ~1.13.2 - bin: - jsdoc: jsdoc.js - checksum: 04bf5ab005349b7581bd0e72ed99933eb71a41dcb47235b486b7d9146fbdf212a53e0cc044abe48ccf46012bd812dc1dfc007c6d679660ebdd053cd000242515 - languageName: node - linkType: hard - "jsdom@npm:^16.5.2": version: 16.7.0 resolution: "jsdom@npm:16.7.0" @@ -32706,26 +31918,6 @@ __metadata: languageName: node linkType: hard -"json-to-ast@npm:^2.1.0": - version: 2.1.0 - resolution: "json-to-ast@npm:2.1.0" - dependencies: - code-error-fragment: 0.0.230 - grapheme-splitter: ^1.0.4 - checksum: 1e9b051505b218573b39f3fec9054d75772413aefc2fee3e763d9033276664faa7eec26b945a71f70b9ce29685b2f13259df7dd3243e15eacf4672c62d5ba7ce - languageName: node - linkType: hard - -"json-to-pretty-yaml@npm:^1.2.2": - version: 1.2.2 - resolution: "json-to-pretty-yaml@npm:1.2.2" - dependencies: - remedial: ^1.0.7 - remove-trailing-spaces: ^1.0.6 - checksum: 4b78480f426e176e5fdac073e05877683bb026f1175deb52d0941b992f9c91a58a812c020f00aa67ba1fc7cadb220539a264146f222e48a48c8bb2a0931cac9b - languageName: node - linkType: hard - "json2xml@npm:^0.1.3": version: 0.1.3 resolution: "json2xml@npm:0.1.3" @@ -32916,77 +32108,77 @@ __metadata: languageName: node linkType: hard -"jss-plugin-camel-case@npm:^10.5.1": - version: 10.9.2 - resolution: "jss-plugin-camel-case@npm:10.9.2" +"jss-plugin-camel-case@npm:^10.10.0, jss-plugin-camel-case@npm:^10.5.1": + version: 10.10.0 + resolution: "jss-plugin-camel-case@npm:10.10.0" dependencies: "@babel/runtime": ^7.3.1 hyphenate-style-name: ^1.0.3 - jss: 10.9.2 - checksum: 5fa617b23ce9718244691c59ace6a0d1271dbcb4430ce3e13b851ee1879c1db8ecab7e941c33802bea763a0f0e2b609d004b8a975b2063f213cdd639cdd384d2 + jss: 10.10.0 + checksum: 693485b86f7a0e0bd0c16b8ddd057ca02a993fc088558c96501f9131e7e6261cc9f4b08047879a68441c688c40dceeb5219b1f15ade9043935aade4f37f5ca85 languageName: node linkType: hard -"jss-plugin-default-unit@npm:^10.5.1": - version: 10.9.2 - resolution: "jss-plugin-default-unit@npm:10.9.2" +"jss-plugin-default-unit@npm:^10.10.0, jss-plugin-default-unit@npm:^10.5.1": + version: 10.10.0 + resolution: "jss-plugin-default-unit@npm:10.10.0" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.9.2 - checksum: 48d8d836d36dd15513d98de11fba6be373ac29e6fd5702eb2edd143c815fb9e2f9969b2af6b1b964e9b8a052828690887042f6bcb34836836d5c359e52702d0f + jss: 10.10.0 + checksum: 6e56213830753ad80bca3824973a667106defaef698d5996d45d03a0e2a3e035b33cd257aa8015040c41bd6669e7598dce72c36099d7ae69db758a7b2ca453fa languageName: node linkType: hard -"jss-plugin-global@npm:^10.5.1": - version: 10.9.2 - resolution: "jss-plugin-global@npm:10.9.2" +"jss-plugin-global@npm:^10.10.0, jss-plugin-global@npm:^10.5.1": + version: 10.10.0 + resolution: "jss-plugin-global@npm:10.10.0" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.9.2 - checksum: 9b29b0c1f169d5a1033890875df072d76364a902d0f6470f448544669a388612a9a4d51844fb2bcb6d25a1c43d67c1637f11a162c2cdd9f4b6b0a8f9c94f6090 + jss: 10.10.0 + checksum: f3af4f40358e96cf89e0c7c84b6e441dc9b4d543cd6109fdf9314a9818fd780d252035f46cc526c3d3fb4393bc29effc6993cc22e04f4e67ec3c889ab760d580 languageName: node linkType: hard -"jss-plugin-nested@npm:^10.5.1": - version: 10.9.2 - resolution: "jss-plugin-nested@npm:10.9.2" +"jss-plugin-nested@npm:^10.10.0, jss-plugin-nested@npm:^10.5.1": + version: 10.10.0 + resolution: "jss-plugin-nested@npm:10.10.0" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.9.2 + jss: 10.10.0 tiny-warning: ^1.0.2 - checksum: ee08df07f3d553931b48037674842a8314bbc7857cc954a52f962a516bfc4b2d4e9871578b06b8fa3981edf5a927cea00021fd368d4ce315870065b7647f7b57 + checksum: 190094375972b68eb8f683387c74e97dc8347e7cc4f2fbfd40b3baf077dfde83d70e57be56744690d22537c0390e0a398714d86736df820c64e498df95f937de languageName: node linkType: hard -"jss-plugin-props-sort@npm:^10.5.1": - version: 10.9.2 - resolution: "jss-plugin-props-sort@npm:10.9.2" +"jss-plugin-props-sort@npm:^10.10.0, jss-plugin-props-sort@npm:^10.5.1": + version: 10.10.0 + resolution: "jss-plugin-props-sort@npm:10.10.0" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.9.2 - checksum: 70bd181a458a6078f19ad4d7350570c78d26b9aabc25a1fbde673839edcc19825af7b636861b208a38aa17e551e68d0ea38599480716b4aec08e353bbe737222 + jss: 10.10.0 + checksum: 274483444b6733bd58d229ebdcdb32b3c24172bc83cb2f6f8364926de19acd872758bcf06c7b3af11cf75504a67a7d67abba62b25081d144585a56b4df9512ba languageName: node linkType: hard -"jss-plugin-rule-value-function@npm:^10.5.1": - version: 10.9.2 - resolution: "jss-plugin-rule-value-function@npm:10.9.2" +"jss-plugin-rule-value-function@npm:^10.10.0, jss-plugin-rule-value-function@npm:^10.5.1": + version: 10.10.0 + resolution: "jss-plugin-rule-value-function@npm:10.10.0" dependencies: "@babel/runtime": ^7.3.1 - jss: 10.9.2 + jss: 10.10.0 tiny-warning: ^1.0.2 - checksum: b1a03209d0249f13ea6de766d3ee14c1769cd1f67d8c543c7d1ce6178c32cf15507c021ecb3e3b7585a8a7a2425dddbe0bdae02f4135c4598725a4152bebfc99 + checksum: 009c9593b9be8b9f1030b797e58e3c233d90e034e5c68b0cabd25bffc7da965c69dc1ccb1bb6a542d72bb824df89036b2264fe564e8538320ef99febaf2882ee languageName: node linkType: hard -"jss-plugin-vendor-prefixer@npm:^10.5.1": - version: 10.9.2 - resolution: "jss-plugin-vendor-prefixer@npm:10.9.2" +"jss-plugin-vendor-prefixer@npm:^10.10.0, jss-plugin-vendor-prefixer@npm:^10.5.1": + version: 10.10.0 + resolution: "jss-plugin-vendor-prefixer@npm:10.10.0" dependencies: "@babel/runtime": ^7.3.1 css-vendor: ^2.0.8 - jss: 10.9.2 - checksum: a5c352a500fea82e8a782a090cc9815f6331259f1a331158ed74ed77c750fb45750f5ae95f07d27922742830b45d4c3592cfaab194b3ba4a50591acbdeab04d8 + jss: 10.10.0 + checksum: 879b7233f9b0b571074dc2b88d97a05dbb949012ba2405f1481bbedd521167dc835133632adb3f2d8ffceddd337c8c13e3e8b1931590516c0664039598752dff languageName: node linkType: hard @@ -33010,19 +32202,7 @@ __metadata: languageName: node linkType: hard -"jss@npm:10.9.2": - version: 10.9.2 - resolution: "jss@npm:10.9.2" - dependencies: - "@babel/runtime": ^7.3.1 - csstype: ^3.0.2 - is-in-browser: ^1.1.3 - tiny-warning: ^1.0.2 - checksum: 7ae5cd2f8602bf197ec90251d774b9f10d55eb2db0854ac78dc7fb6983828c202e8eb0d5c8c59c73b2f64718ebd33d6063afa799d625a995986a22dc1cc27230 - languageName: node - linkType: hard - -"jss@npm:^10.5.1, jss@npm:~10.10.0": +"jss@npm:10.10.0, jss@npm:^10.10.0, jss@npm:^10.5.1, jss@npm:~10.10.0": version: 10.10.0 resolution: "jss@npm:10.10.0" dependencies: @@ -33180,15 +32360,6 @@ __metadata: languageName: node linkType: hard -"klaw@npm:^3.0.0": - version: 3.0.0 - resolution: "klaw@npm:3.0.0" - dependencies: - graceful-fs: ^4.1.9 - checksum: 1bf9de22392c80d28de8a2babd6f0de29fa52fcdc1654838fd35174b3641c168ec32b8b03022191e3c190efd535c31fce23f85e29cb260245571da7263ef418e - languageName: node - linkType: hard - "kleur@npm:^3.0.3": version: 3.0.3 resolution: "kleur@npm:3.0.3" @@ -33477,6 +32648,16 @@ __metadata: languageName: node linkType: hard +"linkify-react@npm:4.1.3": + version: 4.1.3 + resolution: "linkify-react@npm:4.1.3" + peerDependencies: + linkifyjs: ^4.0.0 + react: ">= 15.0.0" + checksum: 1c28ab02774d5427fad9f4a5ad1c7b852b83aece983fd143fdb4ec95dedf7edc77da59883aaf6fb1a2c2060e8b5e72fdfad4d704d544fabc2b173a1b1eb6473d + languageName: node + linkType: hard + "linkifyjs@npm:4.1.2": version: 4.1.2 resolution: "linkifyjs@npm:4.1.2" @@ -33484,6 +32665,13 @@ __metadata: languageName: node linkType: hard +"linkifyjs@npm:4.1.3": + version: 4.1.3 + resolution: "linkifyjs@npm:4.1.3" + checksum: 023d467499a717a49ebbfa256a80cb2811a3b038ff2593e5be0fb8a4715b0a63bf80c571838e19e120833d5b9874464f3a1448965c8eebbde8c19458b3a6c6e4 + languageName: node + linkType: hard + "lint-staged@npm:^15.0.0": version: 15.1.0 resolution: "lint-staged@npm:15.1.0" @@ -33525,27 +32713,6 @@ __metadata: languageName: node linkType: hard -"listr2@npm:^4.0.5": - version: 4.0.5 - resolution: "listr2@npm:4.0.5" - dependencies: - cli-truncate: ^2.1.0 - colorette: ^2.0.16 - log-update: ^4.0.0 - p-map: ^4.0.0 - rfdc: ^1.3.0 - rxjs: ^7.5.5 - through: ^2.3.8 - wrap-ansi: ^7.0.0 - peerDependencies: - enquirer: ">= 2.3.0 < 3" - peerDependenciesMeta: - enquirer: - optional: true - checksum: 7af31851abe25969ef0581c6db808117e36af15b131401795182427769d9824f451ba9e8aff6ccd25b6a4f6c8796f816292caf08e5f1f9b1775e8e9c313dc6c5 - languageName: node - linkType: hard - "load-yaml-file@npm:^0.2.0": version: 0.2.0 resolution: "load-yaml-file@npm:0.2.0" @@ -33860,7 +33027,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:4.17.21, lodash@npm:^4.15.0, lodash@npm:^4.16.4, lodash@npm:^4.17.10, lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:^4.7.0, lodash@npm:~4.17.0, lodash@npm:~4.17.15, lodash@npm:~4.17.21": +"lodash@npm:4.17.21, lodash@npm:^4.15.0, lodash@npm:^4.16.4, lodash@npm:^4.17.10, lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:^4.7.0, lodash@npm:~4.17.15, lodash@npm:~4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7 @@ -33895,18 +33062,6 @@ __metadata: languageName: node linkType: hard -"log-update@npm:^4.0.0": - version: 4.0.0 - resolution: "log-update@npm:4.0.0" - dependencies: - ansi-escapes: ^4.3.0 - cli-cursor: ^3.1.0 - slice-ansi: ^4.0.0 - wrap-ansi: ^6.2.0 - checksum: ae2f85bbabc1906034154fb7d4c4477c79b3e703d22d78adee8b3862fa913942772e7fa11713e3d96fb46de4e3cabefbf5d0a544344f03b58d3c4bff52aa9eb2 - languageName: node - linkType: hard - "log-update@npm:^5.0.1": version: 5.0.1 resolution: "log-update@npm:5.0.1" @@ -33949,7 +33104,7 @@ __metadata: languageName: node linkType: hard -"loglevel@npm:^1.6.8, loglevel@npm:^1.8.0": +"loglevel@npm:^1.8.0": version: 1.8.1 resolution: "loglevel@npm:1.8.1" checksum: a1a62db40291aaeaef2f612334c49e531bff71cc1d01a2acab689ab80d59e092f852ab164a5aedc1a752fdc46b7b162cb097d8a9eb2cf0b299511106c29af61d @@ -33988,15 +33143,6 @@ __metadata: languageName: node linkType: hard -"lower-case-first@npm:^2.0.2": - version: 2.0.2 - resolution: "lower-case-first@npm:2.0.2" - dependencies: - tslib: ^2.0.3 - checksum: 33e3da1098ddda219ce125d4ab7a78a944972c0ee8872e95b6ccc35df8ad405284ab233b0ba4d72315ad1a06fe2f0d418ee4cba9ec1ef1c386dea78899fc8958 - languageName: node - linkType: hard - "lower-case@npm:^2.0.2": version: 2.0.2 resolution: "lower-case@npm:2.0.2" @@ -34065,7 +33211,7 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^7.10.1, lru-cache@npm:^7.14.0, lru-cache@npm:^7.14.1, lru-cache@npm:^7.7.1": +"lru-cache@npm:^7.14.0, lru-cache@npm:^7.7.1": version: 7.18.3 resolution: "lru-cache@npm:7.18.3" checksum: e550d772384709deea3f141af34b6d4fa392e2e418c1498c078de0ee63670f1f46f5eee746e8ef7e69e1c895af0d4224e62ee33e66a543a14763b0f2e74c1356 @@ -34150,15 +33296,6 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.27.0": - version: 0.27.0 - resolution: "magic-string@npm:0.27.0" - dependencies: - "@jridgewell/sourcemap-codec": ^1.4.13 - checksum: 273faaa50baadb7a2df6e442eac34ad611304fc08fe16e24fe2e472fd944bfcb73ffb50d2dc972dc04e92784222002af46868cb9698b1be181c81830fd95a13e - languageName: node - linkType: hard - "magic-string@npm:^0.30.3": version: 0.30.5 resolution: "magic-string@npm:0.30.5" @@ -34279,13 +33416,6 @@ __metadata: languageName: node linkType: hard -"map-cache@npm:^0.2.0": - version: 0.2.2 - resolution: "map-cache@npm:0.2.2" - checksum: 3067cea54285c43848bb4539f978a15dedc63c03022abeec6ef05c8cb6829f920f13b94bcaf04142fc6a088318e564c4785704072910d120d55dbc2e0c421969 - languageName: node - linkType: hard - "map-obj@npm:^1.0.0": version: 1.0.1 resolution: "map-obj@npm:1.0.1" @@ -34300,17 +33430,7 @@ __metadata: languageName: node linkType: hard -"markdown-it-anchor@npm:^8.4.1": - version: 8.6.4 - resolution: "markdown-it-anchor@npm:8.6.4" - peerDependencies: - "@types/markdown-it": "*" - markdown-it: "*" - checksum: bde310d0202450a228662921df9d9c2e95b3c5762512e8eed1d472fcc812fb20e6b4e98480cda88c8b56b0baf34ac70d6bf8404309c5a2321ebe62da43cd6fe6 - languageName: node - linkType: hard - -"markdown-it@npm:^12.2.0, markdown-it@npm:^12.3.2": +"markdown-it@npm:^12.2.0": version: 12.3.2 resolution: "markdown-it@npm:12.3.2" dependencies: @@ -34341,7 +33461,7 @@ __metadata: languageName: node linkType: hard -"marked@npm:^4.0.10, marked@npm:^4.0.14": +"marked@npm:^4.0.14": version: 4.3.0 resolution: "marked@npm:4.3.0" bin: @@ -34700,15 +33820,15 @@ __metadata: languageName: node linkType: hard -"meros@npm:1.2.1, meros@npm:^1.1.4": - version: 1.2.1 - resolution: "meros@npm:1.2.1" +"meros@npm:^1.1.4, meros@npm:^1.2.1": + version: 1.3.0 + resolution: "meros@npm:1.3.0" peerDependencies: "@types/node": ">=13" peerDependenciesMeta: "@types/node": optional: true - checksum: 2201c3f7c58ad2a5b5f7d6b1c644d79bde513e25cb64b51a8c41381ec74bc02cd3423425e34f60c96bf3991f1ec51d65dc8b8e3354cbb060cc9f8226b4666a5a + checksum: ea86c83fe9357d3eb2f5bad20909e12642c7bc8c10340d9bd0968b48f69ec453de14f7e5032d138ad04cb10d79b8c9fb3c9601bb515e8fbdf9bec4eed62994ad languageName: node linkType: hard @@ -35229,15 +34349,6 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:4.2.3": - version: 4.2.3 - resolution: "minimatch@npm:4.2.3" - dependencies: - brace-expansion: ^1.1.7 - checksum: 3392388e3ef7de7ae9a3a48d48a27a323934452f4af81b925dfbe85ce2dc07da855e3dbcc69229888be4e5118f6c0b79847d30f3e7c0e0017b25e423c11c0409 - languageName: node - linkType: hard - "minimatch@npm:9.0.3, minimatch@npm:^9.0.1": version: 9.0.3 resolution: "minimatch@npm:9.0.3" @@ -35247,6 +34358,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^4.2.3": + version: 4.2.3 + resolution: "minimatch@npm:4.2.3" + dependencies: + brace-expansion: ^1.1.7 + checksum: 3392388e3ef7de7ae9a3a48d48a27a323934452f4af81b925dfbe85ce2dc07da855e3dbcc69229888be4e5118f6c0b79847d30f3e7c0e0017b25e423c11c0409 + languageName: node + linkType: hard + "minimatch@npm:^5.0.0, minimatch@npm:^5.0.1, minimatch@npm:^5.1.0, minimatch@npm:^5.1.1, minimatch@npm:^5.1.2": version: 5.1.6 resolution: "minimatch@npm:5.1.6" @@ -35652,6 +34772,42 @@ __metadata: languageName: node linkType: hard +"msw@npm:^2.0.0, msw@npm:^2.0.8": + version: 2.0.9 + resolution: "msw@npm:2.0.9" + dependencies: + "@bundled-es-modules/cookie": ^2.0.0 + "@bundled-es-modules/js-levenshtein": ^2.0.1 + "@bundled-es-modules/statuses": ^1.0.1 + "@mswjs/cookies": ^1.1.0 + "@mswjs/interceptors": ^0.25.11 + "@open-draft/until": ^2.1.0 + "@types/cookie": ^0.4.1 + "@types/js-levenshtein": ^1.1.1 + "@types/statuses": ^2.0.1 + chalk: ^4.1.2 + chokidar: ^3.4.2 + graphql: ^16.8.1 + headers-polyfill: ^4.0.1 + inquirer: ^8.2.0 + is-node-process: ^1.2.0 + js-levenshtein: ^1.1.6 + outvariant: ^1.4.0 + path-to-regexp: ^6.2.0 + strict-event-emitter: ^0.5.0 + type-fest: ^2.19.0 + yargs: ^17.3.1 + peerDependencies: + typescript: ">= 4.7.x <= 5.2.x" + peerDependenciesMeta: + typescript: + optional: true + bin: + msw: cli/index.js + checksum: 77bdb10a019f1d382bfc66b3005752e722f2891e9f8a4f9d3d17f5641ca4d8afb02bc67c9325dfd25708702443e0f9b8e48fbc580faa37c21e090425df93089e + languageName: node + linkType: hard + "multer@npm:^1.4.5-lts.1": version: 1.4.5-lts.1 resolution: "multer@npm:1.4.5-lts.1" @@ -35744,22 +34900,22 @@ __metadata: languageName: node linkType: hard -"nano-css@npm:^5.3.1": - version: 5.3.1 - resolution: "nano-css@npm:5.3.1" +"nano-css@npm:^5.6.1": + version: 5.6.1 + resolution: "nano-css@npm:5.6.1" dependencies: + "@jridgewell/sourcemap-codec": ^1.4.15 css-tree: ^1.1.2 - csstype: ^3.0.6 + csstype: ^3.1.2 fastest-stable-stringify: ^2.0.2 - inline-style-prefixer: ^6.0.0 - rtl-css-js: ^1.14.0 - sourcemap-codec: ^1.4.8 + inline-style-prefixer: ^7.0.0 + rtl-css-js: ^1.16.1 stacktrace-js: ^2.0.2 - stylis: ^4.0.6 + stylis: ^4.3.0 peerDependencies: react: "*" react-dom: "*" - checksum: 45517871e8c15a00769bfc9eb5e466d9c193b0a7423050eb77eb21003a1ccfd13863f01bf68490be830de019f4a0ae945d5b91eb23c5898d341ac8968ba3f18b + checksum: 735f02c030a9416bb6060503d24f18f2b2c9f43e4893c2d8714508d00f9d114b8a134df3623e94e376b0b1d794b0cacac6a48f8e5fb2b7fa8996071bcad590b8 languageName: node linkType: hard @@ -35770,12 +34926,12 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.6": - version: 3.3.6 - resolution: "nanoid@npm:3.3.6" +"nanoid@npm:^3.3.6, nanoid@npm:^3.3.7": + version: 3.3.7 + resolution: "nanoid@npm:3.3.7" bin: nanoid: bin/nanoid.cjs - checksum: 7d0eda657002738aa5206107bd0580aead6c95c460ef1bdd0b1a87a9c7ae6277ac2e9b945306aaa5b32c6dcb7feaf462d0f552e7f8b5718abfc6ead5c94a71b3 + checksum: d36c427e530713e4ac6567d488b489a36582ef89da1d6d4e3b87eded11eb10d7042a877958c6f104929809b2ab0bafa17652b076cdf84324aa75b30b722204f2 languageName: node linkType: hard @@ -35925,15 +35081,6 @@ __metadata: languageName: node linkType: hard -"node-addon-api@npm:^3.2.1": - version: 3.2.1 - resolution: "node-addon-api@npm:3.2.1" - dependencies: - node-gyp: latest - checksum: 2369986bb0881ccd9ef6bacdf39550e07e089a9c8ede1cbc5fc7712d8e2faa4d50da0e487e333d4125f8c7a616c730131d1091676c9d499af1d74560756b4a18 - languageName: node - linkType: hard - "node-cache@npm:^5.1.2": version: 5.1.2 resolution: "node-cache@npm:5.1.2" @@ -35952,7 +35099,7 @@ __metadata: languageName: node linkType: hard -"node-domexception@npm:1.0.0, node-domexception@npm:^1.0.0": +"node-domexception@npm:^1.0.0": version: 1.0.0 resolution: "node-domexception@npm:1.0.0" checksum: ee1d37dd2a4eb26a8a92cd6b64dfc29caec72bff5e1ed9aba80c294f57a31ba4895a60fd48347cf17dd6e766da0ae87d75657dfd1f384ebfa60462c2283f5c7f @@ -35969,6 +35116,20 @@ __metadata: languageName: node linkType: hard +"node-fetch@npm:2.6.7": + version: 2.6.7 + resolution: "node-fetch@npm:2.6.7" + dependencies: + whatwg-url: ^5.0.0 + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: 8d816ffd1ee22cab8301c7756ef04f3437f18dace86a1dae22cf81db8ef29c0bf6655f3215cb0cdb22b420b6fe141e64b26905e7f33f9377a7fa59135ea3e10b + languageName: node + linkType: hard + "node-fetch@npm:^1.0.1": version: 1.7.3 resolution: "node-fetch@npm:1.7.3" @@ -35979,7 +35140,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.12, node-fetch@npm:^2.6.5, node-fetch@npm:^2.6.7": +"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.12, node-fetch@npm:^2.6.5, node-fetch@npm:^2.6.7, node-fetch@npm:^2.6.9": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" dependencies: @@ -36000,17 +35161,6 @@ __metadata: languageName: node linkType: hard -"node-gyp-build@npm:^4.3.0": - version: 4.6.0 - resolution: "node-gyp-build@npm:4.6.0" - bin: - node-gyp-build: bin.js - node-gyp-build-optional: optional.js - node-gyp-build-test: build-test.js - checksum: 25d78c5ef1f8c24291f4a370c47ba52fcea14f39272041a90a7894cd50d766f7c8cb8fb06c0f42bf6f69b204b49d9be3c8fc344aac09714d5bdb95965499eb15 - languageName: node - linkType: hard - "node-gyp@npm:^10.0.0, node-gyp@npm:latest": version: 10.0.1 resolution: "node-gyp@npm:10.0.1" @@ -36178,11 +35328,11 @@ __metadata: linkType: hard "nodemon@npm:^3.0.1": - version: 3.0.1 - resolution: "nodemon@npm:3.0.1" + version: 3.0.2 + resolution: "nodemon@npm:3.0.2" dependencies: chokidar: ^3.5.2 - debug: ^3.2.7 + debug: ^4 ignore-by-default: ^1.0.1 minimatch: ^3.1.2 pstree.remy: ^1.1.8 @@ -36193,7 +35343,7 @@ __metadata: undefsafe: ^2.0.5 bin: nodemon: bin/nodemon.js - checksum: 6a5d81855760d6617049eccce10ccf02bddb482dab13ceea5280ae595ec7004eee13e7b934368e3f46c37fe4d970342a8c38c99cae7e93e4d7a3ed1c1ecb6acf + checksum: 61f3dd207ad444f4a7a2f1aa44adc886605c96c7bc6286291c2360e5e2cd26c3828c90a1418a60783a9da2463593383149135a5a4c099918c54d34a611745499 languageName: node linkType: hard @@ -36445,7 +35595,7 @@ __metadata: languageName: node linkType: hard -"nullthrows@npm:^1.0.0, nullthrows@npm:^1.1.1": +"nullthrows@npm:^1.0.0": version: 1.1.1 resolution: "nullthrows@npm:1.1.1" checksum: 10806b92121253eb1b08ecf707d92480f5331ba8ae5b23fa3eb0548ad24196eb797ed47606153006568a5733ea9e528a3579f21421f7828e09e7756f4bdd386f @@ -36792,17 +35942,6 @@ __metadata: languageName: node linkType: hard -"optimism@npm:^0.17.5": - version: 0.17.5 - resolution: "optimism@npm:0.17.5" - dependencies: - "@wry/context": ^0.7.0 - "@wry/trie": ^0.4.3 - tslib: ^2.3.0 - checksum: 5990217d989e9857dc523a64cb6e5a9205eae68c7acac78f7dde8fbe50045d0f11ca8068cdbb51b1eae15510d96ad593a99cf98c6f86c41d1b6f90e54956ff11 - languageName: node - linkType: hard - "optionator@npm:^0.8.1": version: 0.8.3 resolution: "optionator@npm:0.8.3" @@ -37205,17 +36344,6 @@ __metadata: languageName: node linkType: hard -"parse-filepath@npm:^1.0.2": - version: 1.0.2 - resolution: "parse-filepath@npm:1.0.2" - dependencies: - is-absolute: ^1.0.0 - map-cache: ^0.2.0 - path-root: ^0.1.1 - checksum: 6794c3f38d3921f0f7cc63fb1fb0c4d04cd463356ad389c8ce6726d3c50793b9005971f4138975a6d7025526058d5e65e9bfe634d0765e84c4e2571152665a69 - languageName: node - linkType: hard - "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" @@ -37295,6 +36423,15 @@ __metadata: languageName: node linkType: hard +"passport-atlassian-oauth2@npm:^2.1.0": + version: 2.1.0 + resolution: "passport-atlassian-oauth2@npm:2.1.0" + dependencies: + passport-oauth2: ^1.4.0 + checksum: fc1d46951018d03a792a469a0c856d16f4c21df13d743aa5a0111f60253588c042881c560c737c77d85f4751e42b9ad3a485db7a5d5ea39e0f76160bc4010182 + languageName: node + linkType: hard + "passport-auth0@npm:^1.4.3": version: 1.4.4 resolution: "passport-auth0@npm:1.4.4" @@ -37433,14 +36570,14 @@ __metadata: languageName: node linkType: hard -"passport@npm:^0.6.0": - version: 0.6.0 - resolution: "passport@npm:0.6.0" +"passport@npm:^0.7.0": + version: 0.7.0 + resolution: "passport@npm:0.7.0" dependencies: passport-strategy: 1.x.x pause: 0.0.1 utils-merge: ^1.0.1 - checksum: ef932ad671d50de34765c7a53cd1e058d8331a82a6df09265a9c6c1168911aee4a7b5215803d0101110ab7f317e096b4954ca7e18fb2c33b9929f0bd17dbe159 + checksum: 5080b46df2df7a84f7ba4a8a20437ce71a1346fd27ab47b62df3251a666af9f3430d6c8a1beda3174f6a9d91edc823b57b88050d423a6cff9831848a2d97725c languageName: node linkType: hard @@ -37483,16 +36620,6 @@ __metadata: languageName: node linkType: hard -"path-case@npm:^3.0.4": - version: 3.0.4 - resolution: "path-case@npm:3.0.4" - dependencies: - dot-case: ^3.0.4 - tslib: ^2.0.3 - checksum: 61de0526222629f65038a66f63330dd22d5b54014ded6636283e1d15364da38b3cf29e4433aa3f9d8b0dba407ae2b059c23b0104a34ee789944b1bc1c5c7e06d - languageName: node - linkType: hard - "path-equal@npm:^1.2.5": version: 1.2.5 resolution: "path-equal@npm:1.2.5" @@ -37556,22 +36683,6 @@ __metadata: languageName: node linkType: hard -"path-root-regex@npm:^0.1.0": - version: 0.1.2 - resolution: "path-root-regex@npm:0.1.2" - checksum: dcd75d1f8e93faabe35a58e875b0f636839b3658ff2ad8c289463c40bc1a844debe0dab73c3398ef9dc8f6ec6c319720aff390cf4633763ddcf3cf4b1bbf7e8b - languageName: node - linkType: hard - -"path-root@npm:^0.1.1": - version: 0.1.1 - resolution: "path-root@npm:0.1.1" - dependencies: - path-root-regex: ^0.1.0 - checksum: ff88aebfc1c59ace510cc06703d67692a11530989920427625e52b66a303ca9b3d4059b0b7d0b2a73248d1ad29bcb342b8b786ec00592f3101d38a45fd3b2e08 - languageName: node - linkType: hard - "path-scurry@npm:^1.10.1": version: 1.10.1 resolution: "path-scurry@npm:1.10.1" @@ -37653,6 +36764,13 @@ __metadata: languageName: node linkType: hard +"pct-encode@npm:~1.0.0": + version: 1.0.2 + resolution: "pct-encode@npm:1.0.2" + checksum: 11edce15c8a9012cf5fdee006a05f10e3668a755a15aa25b6afbb8cc20d67f600702eb83e5eaca7a98ee78f9b362fb7d9ada9745428dceb6cdc44e0143851509 + languageName: node + linkType: hard + "peek-readable@npm:^4.0.1": version: 4.0.1 resolution: "peek-readable@npm:4.0.1" @@ -37957,27 +37075,27 @@ __metadata: languageName: node linkType: hard -"playwright-core@npm:1.39.0": - version: 1.39.0 - resolution: "playwright-core@npm:1.39.0" +"playwright-core@npm:1.40.1": + version: 1.40.1 + resolution: "playwright-core@npm:1.40.1" bin: playwright-core: cli.js - checksum: 556e78dee4f9890facf2af8249972e0d6e01a5ae98737b0f6b0166c660a95ffee4cb79350335b1ef96430a0ef01d3669daae9099fa46c8d403d11c623988238b + checksum: 84d92fb9b86e3c225b16b6886bf858eb5059b4e60fa1205ff23336e56a06dcb2eac62650992dede72f406c8e70a7b6a5303e511f9b4bc0b85022ede356a01ee0 languageName: node linkType: hard -"playwright@npm:1.39.0": - version: 1.39.0 - resolution: "playwright@npm:1.39.0" +"playwright@npm:1.40.1": + version: 1.40.1 + resolution: "playwright@npm:1.40.1" dependencies: fsevents: 2.3.2 - playwright-core: 1.39.0 + playwright-core: 1.40.1 dependenciesMeta: fsevents: optional: true bin: playwright: cli.js - checksum: 96d8ca5aa25465c1c5d554d0d6071981d55e22477800ff8f5d47a53ca75193d60ece2df538a01b7165b3277dd5493c67603a5acda713029df7fbd95ce2417bc9 + checksum: 9e36791c1b4a649c104aa365fdd9d049924eeb518c5967c0e921aa38b9b00994aa6ee54784d6c2af194b3b494b6f69772673081ef53c6c4a4b2065af9955c4ba languageName: node linkType: hard @@ -38445,13 +37563,13 @@ __metadata: linkType: hard "postcss@npm:^8.1.0, postcss@npm:^8.4.21, postcss@npm:^8.4.27": - version: 8.4.31 - resolution: "postcss@npm:8.4.31" + version: 8.4.32 + resolution: "postcss@npm:8.4.32" dependencies: - nanoid: ^3.3.6 + nanoid: ^3.3.7 picocolors: ^1.0.0 source-map-js: ^1.0.2 - checksum: 1d8611341b073143ad90486fcdfeab49edd243377b1f51834dc4f6d028e82ce5190e4f11bb2633276864503654fb7cab28e67abdc0fbf9d1f88cad4a0ff0beea + checksum: 220d9d0bf5d65be7ed31006c523bfb11619461d296245c1231831f90150aeb4a31eab9983ac9c5c89759a3ca8b60b3e0d098574964e1691673c3ce5c494305ae languageName: node linkType: hard @@ -38825,59 +37943,16 @@ __metadata: languageName: node linkType: hard -"proto3-json-serializer@npm:^1.0.0": - version: 1.1.1 - resolution: "proto3-json-serializer@npm:1.1.1" +"proto3-json-serializer@npm:^2.0.0": + version: 2.0.0 + resolution: "proto3-json-serializer@npm:2.0.0" dependencies: protobufjs: ^7.0.0 - checksum: 0cd94cb635a9b9b3a2d047700175be4a6c7b7a43e2698826edad17604793764bcdfc270585ea58cb94aa690211b6cdaae5bf7a22522bea68ca67a2844773b4b7 + checksum: aea3433d5e0204625b97bda53001f71fc060eb83709d58d001c5bf75728f14b5ebfca39b54d81e7c90e4de363f68aecf1d203a410f33ebda9590a812f8f30b13 languageName: node linkType: hard -"protobufjs-cli@npm:1.1.1": - version: 1.1.1 - resolution: "protobufjs-cli@npm:1.1.1" - dependencies: - chalk: ^4.0.0 - escodegen: ^1.13.0 - espree: ^9.0.0 - estraverse: ^5.1.0 - glob: ^8.0.0 - jsdoc: ^4.0.0 - minimist: ^1.2.0 - semver: ^7.1.2 - tmp: ^0.2.1 - uglify-js: ^3.7.7 - peerDependencies: - protobufjs: ^7.0.0 - bin: - pbjs: bin/pbjs - pbts: bin/pbts - checksum: 124a2cb10d6fccdd6e8f2984b0f7d9a351d9c1efd17f237acd4a9e7c4b82d63265364b1c86bfa5c6a6fa17d7119182c4c323a8972c0078e1ac5c5f653d096f9b - languageName: node - linkType: hard - -"protobufjs@npm:7.2.4": - version: 7.2.4 - resolution: "protobufjs@npm:7.2.4" - dependencies: - "@protobufjs/aspromise": ^1.1.2 - "@protobufjs/base64": ^1.1.2 - "@protobufjs/codegen": ^2.0.4 - "@protobufjs/eventemitter": ^1.1.0 - "@protobufjs/fetch": ^1.1.0 - "@protobufjs/float": ^1.0.2 - "@protobufjs/inquire": ^1.1.0 - "@protobufjs/path": ^1.1.2 - "@protobufjs/pool": ^1.1.0 - "@protobufjs/utf8": ^1.1.0 - "@types/node": ">=13.7.0" - long: ^5.0.0 - checksum: a952cdf2a5e5250c16ae651b570849b6f5b20a5475c3eef63ffb290ad239aa2916adfc1cc676f7fc93c69f48113df268761c0c246f7f023118c85bdd1a170044 - languageName: node - linkType: hard - -"protobufjs@npm:^7.0.0, protobufjs@npm:^7.2.5": +"protobufjs@npm:7.2.5, protobufjs@npm:^7.0.0, protobufjs@npm:^7.2.4, protobufjs@npm:^7.2.5": version: 7.2.5 resolution: "protobufjs@npm:7.2.5" dependencies: @@ -39017,29 +38092,6 @@ __metadata: languageName: node linkType: hard -"pvtsutils@npm:^1.3.2": - version: 1.3.2 - resolution: "pvtsutils@npm:1.3.2" - dependencies: - tslib: ^2.4.0 - checksum: 9b8155611363e2f40276879f2454e60204b45be0cd0482f9373f369308a2e9c76d5d74cdf661a3f5aae8022d75ea159eb0ba38ee78fc782ee3051e4722db98d0 - languageName: node - linkType: hard - -"pvutils@npm:^1.1.3": - version: 1.1.3 - resolution: "pvutils@npm:1.1.3" - checksum: 2ee26a9e5176c348977d6ec00d8ee80bff62f51743b1c5fe8abeeb4c5d29d9959cdfe0ce146707a9e6801bce88190fed3002d720b072dc87d031c692820b44c9 - languageName: node - linkType: hard - -"q@npm:^1.5.1": - version: 1.5.1 - resolution: "q@npm:1.5.1" - checksum: 147baa93c805bc1200ed698bdf9c72e9e42c05f96d007e33a558b5fdfd63e5ea130e99313f28efc1783e90e6bdb4e48b67a36fcc026b7b09202437ae88a1fb12 - languageName: node - linkType: hard - "qs@npm:6.11.0": version: 6.11.0 resolution: "qs@npm:6.11.0" @@ -39098,6 +38150,13 @@ __metadata: languageName: node linkType: hard +"queue-tick@npm:^1.0.1": + version: 1.0.1 + resolution: "queue-tick@npm:1.0.1" + checksum: 57c3292814b297f87f792fbeb99ce982813e4e54d7a8bdff65cf53d5c084113913289d4a48ec8bbc964927a74b847554f9f4579df43c969a6c8e0f026457ad01 + languageName: node + linkType: hard + "quick-format-unescaped@npm:^3.0.3": version: 3.0.3 resolution: "quick-format-unescaped@npm:3.0.3" @@ -39142,7 +38201,7 @@ __metadata: languageName: node linkType: hard -"ramda@npm:^0.29.0, ramda@npm:~0.29.0": +"ramda@npm:~0.29.0": version: 0.29.0 resolution: "ramda@npm:0.29.0" checksum: 9ab26c06eb7545cbb7eebcf75526d6ee2fcaae19e338f165b2bf32772121e7b28192d6664d1ba222ff76188ba26ab307342d66e805dbb02c860560adc4d5dd57 @@ -39734,18 +38793,6 @@ __metadata: languageName: node linkType: hard -"react-resize-detector@npm:^8.0.4": - version: 8.0.4 - resolution: "react-resize-detector@npm:8.0.4" - dependencies: - lodash: ^4.17.21 - peerDependencies: - react: ^16.0.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 - checksum: f53a99cc5413844a6fc2a713b0b1094d23947897c14ab64481938632f4e77fadded52d91a6619055abf6240c7cacd6cc7dd492ea866639b302f81df680709d45 - languageName: node - linkType: hard - "react-router-beta@npm:react-router@6.0.0-beta.0, react-router@npm:6.0.0-beta.0": version: 6.0.0-beta.0 resolution: "react-router@npm:6.0.0-beta.0" @@ -39786,15 +38833,15 @@ __metadata: linkType: hard "react-router-dom@npm:^6.3.0": - version: 6.18.0 - resolution: "react-router-dom@npm:6.18.0" + version: 6.20.1 + resolution: "react-router-dom@npm:6.20.1" dependencies: - "@remix-run/router": 1.11.0 - react-router: 6.18.0 + "@remix-run/router": 1.13.1 + react-router: 6.20.1 peerDependencies: react: ">=16.8" react-dom: ">=16.8" - checksum: ca5c9a9f748f4ff9677d25762970fc59cb216568aad0ebc668b22398222a940f767680bc9a3e65a92e940d3fe05731eda8a4b352ccbf1054904b3b785a9f5e6f + checksum: 137b12fd3c3fd2a9469367946353c8ccd4e31473c6ec650eeb2d9e9f256f64b031fafaecb2ae4dc47bbab817c8d089b1f07a0db74699df7d874850e511cd5380 languageName: node linkType: hard @@ -39809,14 +38856,14 @@ __metadata: languageName: node linkType: hard -"react-router@npm:6.18.0, react-router@npm:^6.3.0": - version: 6.18.0 - resolution: "react-router@npm:6.18.0" +"react-router@npm:6.20.1, react-router@npm:^6.3.0": + version: 6.20.1 + resolution: "react-router@npm:6.20.1" dependencies: - "@remix-run/router": 1.11.0 + "@remix-run/router": 1.13.1 peerDependencies: react: ">=16.8" - checksum: 03e9a23c5b75d8813720745e2952bb9e62ec310d238cde4f19e0ce73582701fa5e04cf609ff9ced978e9e6c531b5e333b9aee35371e6c4743afc2829e32e926a + checksum: 046efa4b101c64de823f0c838948a50ad53f3ccdd7887604d93c1ccf19c4e797935cab602aa001d793544445412ebeb95c2c7f880e3e86ca447772db574789d7 languageName: node linkType: hard @@ -39829,7 +38876,7 @@ __metadata: languageName: node linkType: hard -"react-smooth@npm:^2.0.4": +"react-smooth@npm:^2.0.5": version: 2.0.5 resolution: "react-smooth@npm:2.0.5" dependencies: @@ -39967,8 +39014,8 @@ __metadata: linkType: hard "react-use@npm:^17.2.4, react-use@npm:^17.3.1, react-use@npm:^17.3.2, react-use@npm:^17.4.0": - version: 17.4.0 - resolution: "react-use@npm:17.4.0" + version: 17.4.2 + resolution: "react-use@npm:17.4.2" dependencies: "@types/js-cookie": ^2.2.6 "@xobotyi/scrollbar-width": ^1.9.5 @@ -39976,7 +39023,7 @@ __metadata: fast-deep-equal: ^3.1.3 fast-shallow-equal: ^1.0.0 js-cookie: ^2.2.1 - nano-css: ^5.3.1 + nano-css: ^5.6.1 react-universal-interface: ^0.6.2 resize-observer-polyfill: ^1.5.1 screenfull: ^5.1.0 @@ -39985,9 +39032,9 @@ __metadata: ts-easing: ^0.2.0 tslib: ^2.1.0 peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 0889da919b49a186de375ec15d2778b954ae981c523acd17dd496e4a4da7b6190efe7993491e1b85fdd6de3e745d08a4eaba4caa35408d570b5f1de550f35d11 + react: "*" + react-dom: "*" + checksum: 1b15add951a80eee637045e5e769dd565edde47838da3d8d0e9a4a2cfd547eb59626b5c5b020ba3c067c01356d2042c5948c534a90729114a7fc7d1e18763d0c languageName: node linkType: hard @@ -40002,15 +39049,15 @@ __metadata: linkType: hard "react-window@npm:^1.8.6": - version: 1.8.9 - resolution: "react-window@npm:1.8.9" + version: 1.8.10 + resolution: "react-window@npm:1.8.10" dependencies: "@babel/runtime": ^7.0.0 memoize-one: ">=3.1.1 <6" peerDependencies: react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 - checksum: cefa232f4f37269d292529ef15780fb108123d6bb5beee19eeac657e75cf8d4664be66f2da04baf0cb1bc64c5ab3d83a88199c3358f023b78940acd37b0673b2 + checksum: e8830f32e3ad4bf91af9cdc5cead84148c7694ce6abd9fdb447fb609da6cd4bbd0bbc75ff985f78828f4bbbd3ba4cbc98235cc9c056b5e5787578518f7fafbb9 languageName: node linkType: hard @@ -40197,15 +39244,14 @@ __metadata: linkType: hard "recharts@npm:^2.5.0": - version: 2.9.3 - resolution: "recharts@npm:2.9.3" + version: 2.10.3 + resolution: "recharts@npm:2.10.3" dependencies: - classnames: ^2.2.5 + clsx: ^2.0.0 eventemitter3: ^4.0.1 lodash: ^4.17.19 react-is: ^16.10.2 - react-resize-detector: ^8.0.4 - react-smooth: ^2.0.4 + react-smooth: ^2.0.5 recharts-scale: ^0.4.4 tiny-invariant: ^1.3.1 victory-vendor: ^36.6.8 @@ -40213,7 +39259,7 @@ __metadata: prop-types: ^15.6.0 react: ^16.0.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 - checksum: e08bcc76a1ec2ea0cbcfcf8f57013acd11fb5ac44f40f43bb208880a8c410a9bc8d0eb421e8d1a5943eb0899729ae136a579a8008c720cb2e18367771edd86d7 + checksum: 503c9fefa8648e0e8834a11ccc09fdcc310d391807438f4c0567b1888d7cd5f7a1f65f020afb981ec54ad6f96d31ebe757ab9025e93782edabc5c741f1aa946a languageName: node linkType: hard @@ -40304,7 +39350,7 @@ __metadata: languageName: node linkType: hard -"reflect-metadata@npm:0.1.13, reflect-metadata@npm:^0.1.13": +"reflect-metadata@npm:0.1.13": version: 0.1.13 resolution: "reflect-metadata@npm:0.1.13" checksum: 798d379a7b6f6455501145419505c97dd11cbc23857a386add2b9ef15963ccf15a48d9d15507afe01d4cd74116df8a213247200bac00320bd7c11ddeaa5e8fb4 @@ -40450,17 +39496,6 @@ __metadata: languageName: node linkType: hard -"relay-runtime@npm:12.0.0": - version: 12.0.0 - resolution: "relay-runtime@npm:12.0.0" - dependencies: - "@babel/runtime": ^7.0.0 - fbjs: ^3.0.0 - invariant: ^2.2.4 - checksum: 51cdc8a5e04188982452ae4e7c6ac7d6375ee769130d24ce8e8f9cdd45aa7e11ecd68670f56e30dcee1b4974585e88ecce19e69a9868b80cda0db7678c3b8f0a - languageName: node - linkType: hard - "remark-gfm@npm:^3.0.1": version: 3.0.1 resolution: "remark-gfm@npm:3.0.1" @@ -40508,13 +39543,6 @@ __metadata: languageName: node linkType: hard -"remedial@npm:^1.0.7": - version: 1.0.8 - resolution: "remedial@npm:1.0.8" - checksum: 12df7c55eb92501d7f33cfe5f5ad12be13bb6ac0c53f494aaa9963d5a5155bb8be2143e8d5e17afa1a500ef5dc71d13642920d35350f2a31b65a9778afab6869 - languageName: node - linkType: hard - "remove-trailing-separator@npm:^1.0.1": version: 1.1.0 resolution: "remove-trailing-separator@npm:1.1.0" @@ -40529,13 +39557,6 @@ __metadata: languageName: node linkType: hard -"remove-trailing-spaces@npm:^1.0.6": - version: 1.0.8 - resolution: "remove-trailing-spaces@npm:1.0.8" - checksum: 81f615c5cd8dd6a5e3017dcc9af598965575d176d42ef99cfd7b894529991f464e629fd68aba089f5c6bebf5bb8070a5eee56f3b621aba55e8ef524d6a4d4f69 - languageName: node - linkType: hard - "renderkid@npm:^3.0.0": version: 3.0.0 resolution: "renderkid@npm:3.0.0" @@ -40632,15 +39653,6 @@ __metadata: languageName: node linkType: hard -"requizzle@npm:^0.2.3": - version: 0.2.3 - resolution: "requizzle@npm:0.2.3" - dependencies: - lodash: ^4.17.14 - checksum: b1b27c6ad16a2621d4cdb57cd44f01d302974df60f84f94b4d9d313dfe1d375e5b1a12f46010929fe508e83c40696a2105d38c1d1906c228500ac72b23a0d0c6 - languageName: node - linkType: hard - "reselect@npm:^4.1.8": version: 4.1.8 resolution: "reselect@npm:4.1.8" @@ -40699,7 +39711,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.4, resolve@npm:~1.22.1": +"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.14.2, resolve@npm:^1.17.0, resolve@npm:^1.19.0, resolve@npm:^1.20.0, resolve@npm:^1.22.1, resolve@npm:^1.22.4, resolve@npm:~1.22.1": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -40735,7 +39747,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.17.0#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.4#~builtin, resolve@patch:resolve@~1.22.1#~builtin": +"resolve@patch:resolve@^1.1.6#~builtin, resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.17.0#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.20.0#~builtin, resolve@patch:resolve@^1.22.1#~builtin, resolve@patch:resolve@^1.22.4#~builtin, resolve@patch:resolve@~1.22.1#~builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#~builtin::version=1.22.8&hash=07638b" dependencies: @@ -40771,13 +39783,6 @@ __metadata: languageName: node linkType: hard -"response-iterator@npm:^0.2.6": - version: 0.2.6 - resolution: "response-iterator@npm:0.2.6" - checksum: b0db3c0665a0d698d65512951de9623c086b9c84ce015a76076d4bd0bf733779601d0b41f0931d16ae38132fba29e1ce291c1f8e6550fc32daaa2dc3ab4f338d - languageName: node - linkType: hard - "responselike@npm:^1.0.2": version: 1.0.2 resolution: "responselike@npm:1.0.2" @@ -40830,13 +39835,15 @@ __metadata: languageName: node linkType: hard -"retry-request@npm:^5.0.0": - version: 5.0.0 - resolution: "retry-request@npm:5.0.0" +"retry-request@npm:^7.0.0": + version: 7.0.1 + resolution: "retry-request@npm:7.0.1" dependencies: + "@types/request": ^2.48.8 debug: ^4.1.1 extend: ^3.0.2 - checksum: f1c6eba3a380e994f2693d1734320e1291de16c11d25b3c4ac2f636b60dff02d8b6a977388a60c5a7d269a3ce5f9a72eb65734e0a614ce91e927fba549ed390e + teeny-request: ^9.0.0 + checksum: 75a359afc8a748ae2ee2b5991cf3c7a198a61492e73b0fcdc6f03d35767c99a3eb0dc93194f1acf1575665475e4edfcf5cf74097376390e05fc6c004133bd79d languageName: node linkType: hard @@ -41111,7 +40118,7 @@ __metadata: semver: ^7.5.3 shx: ^0.3.2 ts-node: ^10.4.0 - typescript: ~5.0.0 + typescript: ~5.2.0 languageName: unknown linkType: soft @@ -41147,12 +40154,12 @@ __metadata: languageName: node linkType: hard -"rtl-css-js@npm:^1.14.0": - version: 1.14.0 - resolution: "rtl-css-js@npm:1.14.0" +"rtl-css-js@npm:^1.16.1": + version: 1.16.1 + resolution: "rtl-css-js@npm:1.16.1" dependencies: "@babel/runtime": ^7.1.2 - checksum: 46e7f52058d7ac2dc7a6271f6858ce2e05f64be4d6a3eae712b52bf29c4de97fda8e30490c425bed620db87cc0b8a3ab4a457489ab0dba0868724bac27e6f893 + checksum: 7d9ab942098eee565784ccf957f6b7dfa78ea1eec7c6bffedc6641575d274189e90752537c7bdba1f43ae6534648144f467fd6d581527455ba626a4300e62c7a languageName: node linkType: hard @@ -41390,13 +40397,6 @@ __metadata: languageName: node linkType: hard -"scuid@npm:^1.1.0": - version: 1.1.0 - resolution: "scuid@npm:1.1.0" - checksum: cd094ac3718b0070a222f9a499b280c698fdea10268cc163fa244421099544c1766dd893fdee0e2a8eba5d53ab9d0bcb11067bedff166665030fa6fda25a096b - languageName: node - linkType: hard - "secure-json-parse@npm:^2.4.0": version: 2.4.0 resolution: "secure-json-parse@npm:2.4.0" @@ -41460,7 +40460,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.5.4, semver@npm:^7.1.1, semver@npm:^7.1.2, semver@npm:^7.1.3, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:~7.5.4": +"semver@npm:7.5.4, semver@npm:^7.1.1, semver@npm:^7.1.3, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:~7.5.4": version: 7.5.4 resolution: "semver@npm:7.5.4" dependencies: @@ -41501,17 +40501,6 @@ __metadata: languageName: node linkType: hard -"sentence-case@npm:^3.0.4": - version: 3.0.4 - resolution: "sentence-case@npm:3.0.4" - dependencies: - no-case: ^3.0.4 - tslib: ^2.0.3 - upper-case-first: ^2.0.2 - checksum: 3cfe6c0143e649132365695706702d7f729f484fa7b25f43435876efe7af2478243eefb052bacbcce10babf9319fd6b5b6bc59b94c80a1c819bcbb40651465d5 - languageName: node - linkType: hard - "seq-queue@npm:^0.0.5": version: 0.0.5 resolution: "seq-queue@npm:0.0.5" @@ -41791,13 +40780,6 @@ __metadata: languageName: node linkType: hard -"signedsource@npm:^1.0.0": - version: 1.0.0 - resolution: "signedsource@npm:1.0.0" - checksum: 64b2c8d7a48de9009cfd3aff62bb7c88abf3b8e0421f17ebb1d7f5ca9cc9c3ad10f5a1e3ae6cd804e4e6121c87b668202ae9057065f058ddfbf34ea65f63945d - languageName: node - linkType: hard - "simple-concat@npm:^1.0.0": version: 1.0.1 resolution: "simple-concat@npm:1.0.1" @@ -41896,17 +40878,6 @@ __metadata: languageName: node linkType: hard -"slice-ansi@npm:^3.0.0": - version: 3.0.0 - resolution: "slice-ansi@npm:3.0.0" - dependencies: - ansi-styles: ^4.0.0 - astral-regex: ^2.0.0 - is-fullwidth-code-point: ^3.0.0 - checksum: 5ec6d022d12e016347e9e3e98a7eb2a592213a43a65f1b61b74d2c78288da0aded781f665807a9f3876b9daa9ad94f64f77d7633a0458876c3a4fdc4eb223f24 - languageName: node - linkType: hard - "slice-ansi@npm:^4.0.0": version: 4.0.0 resolution: "slice-ansi@npm:4.0.0" @@ -41967,16 +40938,6 @@ __metadata: languageName: node linkType: hard -"snake-case@npm:^3.0.4": - version: 3.0.4 - resolution: "snake-case@npm:3.0.4" - dependencies: - dot-case: ^3.0.4 - tslib: ^2.0.3 - checksum: 0a7a79900bbb36f8aaa922cf111702a3647ac6165736d5dc96d3ef367efc50465cac70c53cd172c382b022dac72ec91710608e5393de71f76d7142e6fd80e8a3 - languageName: node - linkType: hard - "sockjs@npm:^0.3.24": version: 0.3.24 resolution: "sockjs@npm:0.3.24" @@ -42065,7 +41026,7 @@ __metadata: languageName: node linkType: hard -"source-map-support@npm:^0.5.16, source-map-support@npm:^0.5.21, source-map-support@npm:~0.5.20": +"source-map-support@npm:^0.5.16, source-map-support@npm:~0.5.20": version: 0.5.21 resolution: "source-map-support@npm:0.5.21" dependencies: @@ -42234,15 +41195,6 @@ __metadata: languageName: node linkType: hard -"sponge-case@npm:^1.0.1": - version: 1.0.1 - resolution: "sponge-case@npm:1.0.1" - dependencies: - tslib: ^2.0.3 - checksum: 64f53d930f63c5a9e59d4cae487c1ffa87d25eab682833b01d572cc885e7e3fdbad4f03409a41f03ecb27f1f8959432253eb48332c7007c3388efddb24ba2792 - languageName: node - linkType: hard - "sprintf-js@npm:^1.1.2": version: 1.1.2 resolution: "sprintf-js@npm:1.1.2" @@ -42431,7 +41383,7 @@ __metadata: languageName: node linkType: hard -"statuses@npm:2.0.1": +"statuses@npm:2.0.1, statuses@npm:^2.0.1": version: 2.0.1 resolution: "statuses@npm:2.0.1" checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb @@ -42552,6 +41504,16 @@ __metadata: languageName: node linkType: hard +"streamx@npm:^2.15.0": + version: 2.15.5 + resolution: "streamx@npm:2.15.5" + dependencies: + fast-fifo: ^1.1.0 + queue-tick: ^1.0.1 + checksum: 52e0ec94026d67c9e2e2e1090f05e5b138c2f2822462d9a8ef4a4805625a31d103e55ea5267fcd9bfe041374926424e42aec2dda28a85cb9de42c2a16d416d94 + languageName: node + linkType: hard + "strict-event-emitter@npm:^0.2.4": version: 0.2.8 resolution: "strict-event-emitter@npm:0.2.8" @@ -42568,6 +41530,13 @@ __metadata: languageName: node linkType: hard +"strict-event-emitter@npm:^0.5.0, strict-event-emitter@npm:^0.5.1": + version: 0.5.1 + resolution: "strict-event-emitter@npm:0.5.1" + checksum: 350480431bc1c28fdb601ef4976c2f8155fc364b4740f9692dd03e5bdd48aafc99a5e021fe655fbd986d0b803e9f3fc5c4b018b35cb838c4690d60f2a26f1cf3 + languageName: node + linkType: hard + "strict-uri-encode@npm:^2.0.0": version: 2.0.0 resolution: "strict-uri-encode@npm:2.0.0" @@ -42582,7 +41551,7 @@ __metadata: languageName: node linkType: hard -"string-env-interpolation@npm:1.0.1, string-env-interpolation@npm:^1.0.1": +"string-env-interpolation@npm:^1.0.1": version: 1.0.1 resolution: "string-env-interpolation@npm:1.0.1" checksum: d126329587f635bee65300e4451e7352b9b67e03daeb62f006ca84244cac12a1f6e45176b018653ba0c3ec3b5d980f9ca59d2eeed99cf799501cdaa7f871dc6f @@ -42801,7 +41770,7 @@ __metadata: languageName: node linkType: hard -"strip-json-comments@npm:^3.1.0, strip-json-comments@npm:^3.1.1, strip-json-comments@npm:~3.1.1": +"strip-json-comments@npm:^3.1.1, strip-json-comments@npm:~3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" checksum: 492f73e27268f9b1c122733f28ecb0e7e8d8a531a6662efbd08e22cccb3f9475e90a1b82cab06a392f6afae6d2de636f977e231296400d0ec5304ba70f166443 @@ -42915,13 +41884,20 @@ __metadata: languageName: node linkType: hard -"stylis@npm:4.2.0, stylis@npm:^4.0.6": +"stylis@npm:4.2.0": version: 4.2.0 resolution: "stylis@npm:4.2.0" checksum: 0eb6cc1b866dc17a6037d0a82ac7fa877eba6a757443e79e7c4f35bacedbf6421fadcab4363b39667b43355cbaaa570a3cde850f776498e5450f32ed2f9b7584 languageName: node linkType: hard +"stylis@npm:^4.3.0": + version: 4.3.0 + resolution: "stylis@npm:4.3.0" + checksum: 6120de3f03eacf3b5adc8e7919c4cca991089156a6badc5248752a3088106afaaf74996211a6817a7760ebeadca09004048eea31875bd8d4df51386365c50025 + languageName: node + linkType: hard + "subscriptions-transport-ws@npm:^0.11.0": version: 0.11.0 resolution: "subscriptions-transport-ws@npm:0.11.0" @@ -43082,8 +42058,8 @@ __metadata: linkType: hard "swagger-ui-react@npm:^5.0.0": - version: 5.10.0 - resolution: "swagger-ui-react@npm:5.10.0" + version: 5.10.3 + resolution: "swagger-ui-react@npm:5.10.3" dependencies: "@babel/runtime-corejs3": ^7.23.2 "@braintree/sanitize-url": =6.0.4 @@ -43122,16 +42098,7 @@ __metadata: peerDependencies: react: ">=17.0.0" react-dom: ">=17.0.0" - checksum: 71aa42a8f3218eb264ea330122b483583830ca30db9dfb6eacee16210db0c4c529602dda607b3860315a3fe42e56e1142d49c4659c41bdfe675d6ae05e1bcdea - languageName: node - linkType: hard - -"swap-case@npm:^2.0.2": - version: 2.0.2 - resolution: "swap-case@npm:2.0.2" - dependencies: - tslib: ^2.0.3 - checksum: 6e21c9e1b3cd5735eb2af679a99ec3efc78a14e3d4d5e3fd594e254b91cfd37185b3d1c6e41b22f53a2cdf5d1b963ce30c0fe8b78337e3fd43d0137084670a5f + checksum: 505dfb7b6f09b75bd637ac89796a6c4c8f3833b3907463f6824c37732cb4d19d045408fd92070dd1d93416996063bd97749de4397b2fca978df8025f2243b60c languageName: node linkType: hard @@ -43164,13 +42131,6 @@ __metadata: languageName: node linkType: hard -"symbol-observable@npm:^4.0.0": - version: 4.0.0 - resolution: "symbol-observable@npm:4.0.0" - checksum: 212c7edce6186634d671336a88c0e0bbd626c2ab51ed57498dc90698cce541839a261b969c2a1e8dd43762133d47672e8b62e0b1ce9cf4157934ba45fd172ba8 - languageName: node - linkType: hard - "symbol-tree@npm:^3.2.4": version: 3.2.4 resolution: "symbol-tree@npm:3.2.4" @@ -43229,6 +42189,17 @@ __metadata: languageName: node linkType: hard +"tar-stream@npm:^3.0.0": + version: 3.1.6 + resolution: "tar-stream@npm:3.1.6" + dependencies: + b4a: ^1.6.4 + fast-fifo: ^1.2.0 + streamx: ^2.15.0 + checksum: f3627f918581976e954ff03cb8d370551053796b82564f8c7ca8fac84c48e4d042026d0854fc222171a34ff9c682b72fae91be9c9b0a112d4c54f9e4f443e9c5 + languageName: node + linkType: hard + "tar@npm:^6.0.2, tar@npm:^6.1.0, tar@npm:^6.1.11, tar@npm:^6.1.12, tar@npm:^6.1.2": version: 6.2.0 resolution: "tar@npm:6.2.0" @@ -43299,16 +42270,16 @@ __metadata: languageName: unknown linkType: soft -"teeny-request@npm:^8.0.0": - version: 8.0.0 - resolution: "teeny-request@npm:8.0.0" +"teeny-request@npm:^9.0.0": + version: 9.0.0 + resolution: "teeny-request@npm:9.0.0" dependencies: http-proxy-agent: ^5.0.0 https-proxy-agent: ^5.0.0 - node-fetch: ^2.6.1 + node-fetch: ^2.6.9 stream-events: ^1.0.5 - uuid: ^8.0.0 - checksum: a867fb58406308e3ee8415f6b6612471a78af136971575bb51eb3ecf4b76d2ea363936da5eb68bbc28ef3d3af59e24dcf0803f1e80c8eb658c73cc9a53881c52 + uuid: ^9.0.0 + checksum: 9cb0ad83f9ca6ce6515b3109cbb30ceb2533cdeab8e41c3a0de89f509bd92c5a9aabd27b3adf7f3e49516e106a358859b19fa4928a1937a4ab95809ccb7d52eb languageName: node linkType: hard @@ -43457,7 +42428,7 @@ __metadata: languageName: node linkType: hard -"through@npm:2, through@npm:^2.3.6, through@npm:^2.3.8": +"through@npm:2, through@npm:^2.3.6": version: 2.3.8 resolution: "through@npm:2.3.8" checksum: a38c3e059853c494af95d50c072b83f8b676a9ba2818dcc5b108ef252230735c54e0185437618596c790bbba8fcdaef5b290405981ffa09dce67b1f1bf190cbd @@ -43518,13 +42489,6 @@ __metadata: languageName: node linkType: hard -"tiny-merge-patch@npm:^0.1.2": - version: 0.1.2 - resolution: "tiny-merge-patch@npm:0.1.2" - checksum: 66b0cc5098adc8767459f2007f9d73f60b47a0e87fa1200076c73a7ebc41dfe4c3842fdc609716c5165d1b2ae0a4140a00d3c78256587f0b3a494e03774ac340 - languageName: node - linkType: hard - "tiny-warning@npm:^1.0.2": version: 1.0.3 resolution: "tiny-warning@npm:1.0.3" @@ -43532,15 +42496,6 @@ __metadata: languageName: node linkType: hard -"title-case@npm:^3.0.3": - version: 3.0.3 - resolution: "title-case@npm:3.0.3" - dependencies: - tslib: ^2.0.3 - checksum: e8b7ea006b53cf3208d278455d9f1e22c409459d7f9878da324fa3b18cc0aef8560924c19c744e870394a5d9cddfdbe029ebae9875909ee7f4fc562e7cbfc53e - languageName: node - linkType: hard - "tmp@npm:^0.0.33": version: 0.0.33 resolution: "tmp@npm:0.0.33" @@ -43550,15 +42505,6 @@ __metadata: languageName: node linkType: hard -"tmp@npm:^0.2.1": - version: 0.2.1 - resolution: "tmp@npm:0.2.1" - dependencies: - rimraf: ^3.0.0 - checksum: 8b1214654182575124498c87ca986ac53dc76ff36e8f0e0b67139a8d221eaecfdec108c0e6ec54d76f49f1f72ab9325500b246f562b926f85bcdfca8bf35df9e - languageName: node - linkType: hard - "tmpl@npm:1.0.5": version: 1.0.5 resolution: "tmpl@npm:1.0.5" @@ -43804,15 +42750,6 @@ __metadata: languageName: node linkType: hard -"ts-invariant@npm:^0.10.3": - version: 0.10.3 - resolution: "ts-invariant@npm:0.10.3" - dependencies: - tslib: ^2.1.0 - checksum: bb07d56fe4aae69d8860e0301dfdee2d375281159054bc24bf1e49e513fb0835bf7f70a11351344d213a79199c5e695f37ebbf5a447188a377ce0cd81d91ddb5 - languageName: node - linkType: hard - "ts-invariant@npm:^0.9.3, ts-invariant@npm:^0.9.4": version: 0.9.4 resolution: "ts-invariant@npm:0.9.4" @@ -43829,13 +42766,6 @@ __metadata: languageName: node linkType: hard -"ts-log@npm:^2.2.3": - version: 2.2.5 - resolution: "ts-log@npm:2.2.5" - checksum: 28f78ab15b8555d56c089dbc243327d8ce4331219956242a29fc4cb3bad6bb0cb8234dd17a292381a1b1dba99a7e4849a2181b2e1a303e8247e9f4ca4e284f2d - languageName: node - linkType: hard - "ts-morph@npm:^20.0.0": version: 20.0.0 resolution: "ts-morph@npm:20.0.0" @@ -43917,7 +42847,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:2.5.0, tslib@npm:~2.5.0": +"tslib@npm:2.5.0": version: 2.5.0 resolution: "tslib@npm:2.5.0" checksum: ae3ed5f9ce29932d049908ebfdf21b3a003a85653a9a140d614da6b767a93ef94f460e52c3d787f0e4f383546981713f165037dc2274df212ea9f8a4541004e1 @@ -43931,20 +42861,13 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.3.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.4.1, tslib@npm:^2.4.1 || ^1.9.3, tslib@npm:^2.5.0": +"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.3.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.4.1, tslib@npm:^2.4.1 || ^1.9.3, tslib@npm:^2.5.0, tslib@npm:^2.6.0, tslib@npm:^2.6.2": version: 2.6.2 resolution: "tslib@npm:2.6.2" checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad languageName: node linkType: hard -"tslib@npm:~2.4.0": - version: 2.4.1 - resolution: "tslib@npm:2.4.1" - checksum: 19480d6e0313292bd6505d4efe096a6b31c70e21cf08b5febf4da62e95c265c8f571f7b36fcc3d1a17e068032f59c269fab3459d6cd3ed6949eafecf64315fca - languageName: node - linkType: hard - "tsutils@npm:^3.21.0": version: 3.21.0 resolution: "tsutils@npm:3.21.0" @@ -43956,20 +42879,19 @@ __metadata: languageName: node linkType: hard -"tsx@npm:^3.14.0": - version: 3.14.0 - resolution: "tsx@npm:3.14.0" +"tsx@npm:^4.0.0": + version: 4.6.2 + resolution: "tsx@npm:4.6.2" dependencies: esbuild: ~0.18.20 fsevents: ~2.3.3 get-tsconfig: ^4.7.2 - source-map-support: ^0.5.21 dependenciesMeta: fsevents: optional: true bin: tsx: dist/cli.mjs - checksum: afcef5d9b90b5800cf1ffb749e943f63042d78a4c0d9eef6e13e43f4ecab465d45e2c9812a2c515cbdc2ee913ff1cd01bf5c606a48013dd3ce2214a631b45557 + checksum: a9f13bdb67bfb316bbfc92303d8464323ab1b673aa93ea97271c211a8ba7c59274d4b32eeec5ad8fbd0b04260a092a3ad2116abeb6913254ba456010ff685743 languageName: node linkType: hard @@ -44233,7 +43155,7 @@ __metadata: languageName: node linkType: hard -"typescript@npm:~5.0.0, typescript@npm:~5.0.4": +"typescript@npm:~5.0.4": version: 5.0.4 resolution: "typescript@npm:5.0.4" bin: @@ -44253,7 +43175,17 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@~5.0.0#~builtin, typescript@patch:typescript@~5.0.4#~builtin": +"typescript@npm:~5.2.0": + version: 5.2.2 + resolution: "typescript@npm:5.2.2" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 7912821dac4d962d315c36800fe387cdc0a6298dba7ec171b350b4a6e988b51d7b8f051317786db1094bd7431d526b648aba7da8236607febb26cf5b871d2d3c + languageName: node + linkType: hard + +"typescript@patch:typescript@~5.0.4#~builtin": version: 5.0.4 resolution: "typescript@patch:typescript@npm%3A5.0.4#~builtin::version=5.0.4&hash=a1c5e5" bin: @@ -44273,6 +43205,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@~5.2.0#~builtin": + version: 5.2.2 + resolution: "typescript@patch:typescript@npm%3A5.2.2#~builtin::version=5.2.2&hash=a1c5e5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 07106822b4305de3f22835cbba949a2b35451cad50888759b6818421290ff95d522b38ef7919e70fb381c5fe9c1c643d7dea22c8b31652a717ddbd57b7f4d554 + languageName: node + linkType: hard + "ua-parser-js@npm:^0.7.30": version: 0.7.33 resolution: "ua-parser-js@npm:0.7.33" @@ -44287,7 +43229,7 @@ __metadata: languageName: node linkType: hard -"uglify-js@npm:^3.1.4, uglify-js@npm:^3.7.7": +"uglify-js@npm:^3.1.4": version: 3.17.0 resolution: "uglify-js@npm:3.17.0" bin: @@ -44340,13 +43282,6 @@ __metadata: languageName: node linkType: hard -"unc-path-regex@npm:^0.1.2": - version: 0.1.2 - resolution: "unc-path-regex@npm:0.1.2" - checksum: a05fa2006bf4606051c10fc7968f08ce7b28fa646befafa282813aeb1ac1a56f65cb1b577ca7851af2726198d59475bb49b11776036257b843eaacee2860a4ec - languageName: node - linkType: hard - "undefsafe@npm:^2.0.5": version: 2.0.5 resolution: "undefsafe@npm:2.0.5" @@ -44361,7 +43296,7 @@ __metadata: languageName: node linkType: hard -"underscore@npm:^1.12.1, underscore@npm:~1.13.2": +"underscore@npm:^1.12.1": version: 1.13.6 resolution: "underscore@npm:1.13.6" checksum: d5cedd14a9d0d91dd38c1ce6169e4455bb931f0aaf354108e47bd46d3f2da7464d49b2171a5cf786d61963204a42d01ea1332a903b7342ad428deaafaf70ec36 @@ -44375,7 +43310,7 @@ __metadata: languageName: node linkType: hard -"undici@npm:^5.12.0, undici@npm:^5.24.0, undici@npm:^5.8.0": +"undici@npm:^5.24.0": version: 5.26.3 resolution: "undici@npm:5.26.3" dependencies: @@ -44676,24 +43611,6 @@ __metadata: languageName: node linkType: hard -"upper-case-first@npm:^2.0.2": - version: 2.0.2 - resolution: "upper-case-first@npm:2.0.2" - dependencies: - tslib: ^2.0.3 - checksum: 4487db4701effe3b54ced4b3e4aa4d9ab06c548f97244d04aafb642eedf96a76d5a03cf5f38f10f415531d5792d1ac6e1b50f2a76984dc6964ad530f12876409 - languageName: node - linkType: hard - -"upper-case@npm:^2.0.2": - version: 2.0.2 - resolution: "upper-case@npm:2.0.2" - dependencies: - tslib: ^2.0.3 - checksum: 508723a2b03ab90cf1d6b7e0397513980fab821cbe79c87341d0e96cedefadf0d85f9d71eac24ab23f526a041d585a575cfca120a9f920e44eb4f8a7cf89121c - languageName: node - linkType: hard - "uri-js@npm:^4.2.2, uri-js@npm:^4.4.1": version: 4.4.1 resolution: "uri-js@npm:4.4.1" @@ -44703,6 +43620,15 @@ __metadata: languageName: node linkType: hard +"uri-template@npm:^2.0.0": + version: 2.0.0 + resolution: "uri-template@npm:2.0.0" + dependencies: + pct-encode: ~1.0.0 + checksum: 6eb3254368ca11330502525c6c0ab42af3cb646bfc96a4021666d6ac6653ede1ac0df7fde84a2e35e7f03f42d91b41251963122cfb3de9b54b84bc0ef3583ffc + languageName: node + linkType: hard + "urijs@npm:^1.19.10, urijs@npm:^1.19.11": version: 1.19.11 resolution: "urijs@npm:1.19.11" @@ -44753,12 +43679,10 @@ __metadata: languageName: node linkType: hard -"urlpattern-polyfill@npm:^6.0.2": - version: 6.0.2 - resolution: "urlpattern-polyfill@npm:6.0.2" - dependencies: - braces: ^3.0.2 - checksum: 564fb223761b67ea76d015f11dfec145db98c71cc35641015d1c9ec164da494b1fab614e652a844e14a72cda31236b9c3a59b22fdcca71166c315ab059fab676 +"urlpattern-polyfill@npm:^9.0.0": + version: 9.0.0 + resolution: "urlpattern-polyfill@npm:9.0.0" + checksum: d3658b78a10eaee514c464f5a4336c408c70cf01e9b915cb1df5892b3c49003d1ed4042dc72d1b18493b8b847883e84fbf2bf358abb5dff84b2725d5e8463bcb languageName: node linkType: hard @@ -45078,7 +44002,7 @@ __metadata: languageName: node linkType: hard -"value-or-promise@npm:1.0.12, value-or-promise@npm:^1.0.11, value-or-promise@npm:^1.0.12": +"value-or-promise@npm:^1.0.11, value-or-promise@npm:^1.0.12": version: 1.0.12 resolution: "value-or-promise@npm:1.0.12" checksum: f53a66c75b7447c90bbaf946a757ca09c094629cb80ba742f59c980ec3a69be0a385a0e75505dedb4e757862f1a994ca4beaf083a831f24d3ffb3d4bb18cd1e1 @@ -45205,23 +44129,23 @@ __metadata: languageName: node linkType: hard -"vite-plugin-node-polyfills@npm:^0.16.0": - version: 0.16.0 - resolution: "vite-plugin-node-polyfills@npm:0.16.0" +"vite-plugin-node-polyfills@npm:^0.17.0": + version: 0.17.0 + resolution: "vite-plugin-node-polyfills@npm:0.17.0" dependencies: "@rollup/plugin-inject": ^5.0.5 buffer-polyfill: "npm:buffer@^6.0.3" node-stdlib-browser: ^1.2.0 process: ^0.11.10 peerDependencies: - vite: ^2.0.0 || ^3.0.0 || ^4.0.0 - checksum: c4b3767e29a7c95efccde7d8adeac7963fb9b30677d88e348eda1c1d407c0d821d58c9ea651cb5db0aa010c93fd1971d8b671fea2417edd15a707861be772861 + vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 + checksum: 760d29c25adfa72b5fc731c1bb0826f9c6cc495afc856d38f634ac811566b158a11b1ea968e5d9d536889072470666e9b933ca38ea0c533854375806503b1729 languageName: node linkType: hard "vite@npm:^4.4.9": - version: 4.5.0 - resolution: "vite@npm:4.5.0" + version: 4.5.1 + resolution: "vite@npm:4.5.1" dependencies: esbuild: ^0.18.10 fsevents: ~2.3.2 @@ -45255,7 +44179,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 06f1a4c858e4dc4c04a10466f4ccacea30c5a9f8574e5ba3deb9d03fa20e80ca6797f02dad97a988da7cdef96238dbc69c3b6a538156585c74722d996223619e + checksum: 72b3584b3d3b8d14e8a37f0248e47fb8b4d02ab35de5b5a8e5ca8ae55c3be2aab73760dc36edac4fa722de182f78cc492eb44888fcb4a9a0712c4605dad644f9 languageName: node linkType: hard @@ -45396,14 +44320,7 @@ __metadata: languageName: node linkType: hard -"web-streams-polyfill@npm:4.0.0-beta.1": - version: 4.0.0-beta.1 - resolution: "web-streams-polyfill@npm:4.0.0-beta.1" - checksum: 94c21d3aba1c26e5942bb210ffd60c6990cbc750d34bdf548ed93ed845f0a6eac89cdae1dd0195afaba15fbcf4aaca9e397ee40fa4d1f2c191d04d43717bd065 - languageName: node - linkType: hard - -"web-streams-polyfill@npm:^3.0.3, web-streams-polyfill@npm:^3.2.0, web-streams-polyfill@npm:^3.2.1": +"web-streams-polyfill@npm:^3.0.3": version: 3.2.1 resolution: "web-streams-polyfill@npm:3.2.1" checksum: b119c78574b6d65935e35098c2afdcd752b84268e18746606af149e3c424e15621b6f1ff0b42b2676dc012fc4f0d313f964b41a4b5031e525faa03997457da02 @@ -45424,19 +44341,6 @@ __metadata: languageName: node linkType: hard -"webcrypto-core@npm:^1.7.4": - version: 1.7.5 - resolution: "webcrypto-core@npm:1.7.5" - dependencies: - "@peculiar/asn1-schema": ^2.1.6 - "@peculiar/json-schema": ^1.1.12 - asn1js: ^3.0.1 - pvtsutils: ^1.3.2 - tslib: ^2.4.0 - checksum: f6e529ca5c1175b8ccead3547f60efa7a1f8e247aaeab3bd4f096eb9fda11cfc8e6b6fb574bbc5696f608958c491a27e9682c89204412f73fb430e5fcbe9ebac - languageName: node - linkType: hard - "webidl-conversions@npm:^3.0.0": version: 3.0.1 resolution: "webidl-conversions@npm:3.0.1" @@ -45624,10 +44528,10 @@ __metadata: languageName: node linkType: hard -"whatwg-fetch@npm:>=0.10.0, whatwg-fetch@npm:^3.4.1": - version: 3.6.2 - resolution: "whatwg-fetch@npm:3.6.2" - checksum: ee976b7249e7791edb0d0a62cd806b29006ad7ec3a3d89145921ad8c00a3a67e4be8f3fb3ec6bc7b58498724fd568d11aeeeea1f7827e7e1e5eae6c8a275afed +"whatwg-fetch@npm:>=0.10.0": + version: 3.6.19 + resolution: "whatwg-fetch@npm:3.6.19" + checksum: 2896bc9ca867ea514392c73e2a272f65d5c4916248fe0837a9df5b1b92f247047bc76cf7c29c28a01ac6c5fb4314021d2718958c8a08292a96d56f72b2f56806 languageName: node linkType: hard @@ -45919,7 +44823,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:*, ws@npm:^8.11.0, ws@npm:^8.13.0, ws@npm:^8.8.0": +"ws@npm:*, ws@npm:8.14.2, ws@npm:^8.11.0, ws@npm:^8.12.0, ws@npm:^8.13.0, ws@npm:^8.8.0": version: 8.14.2 resolution: "ws@npm:8.14.2" peerDependencies: @@ -45934,21 +44838,6 @@ __metadata: languageName: node linkType: hard -"ws@npm:8.11.0": - version: 8.11.0 - resolution: "ws@npm:8.11.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 316b33aba32f317cd217df66dbfc5b281a2f09ff36815de222bc859e3424d83766d9eb2bd4d667de658b6ab7be151f258318fb1da812416b30be13103e5b5c67 - languageName: node - linkType: hard - "ws@npm:^5.2.0 || ^6.0.0 || ^7.0.0, ws@npm:^7.4.6": version: 7.5.9 resolution: "ws@npm:7.5.9" @@ -46080,13 +44969,6 @@ __metadata: languageName: node linkType: hard -"xmlcreate@npm:^2.0.4": - version: 2.0.4 - resolution: "xmlcreate@npm:2.0.4" - checksum: b8dd52668b9aea77cd1408fa85538c14bb8dcc98b4e7bb51e76696c9c115d59eba7240298d0c4fd2caf8f1a8e283ab4e5c7b9a6bcfcf23a8b48f5068b677b748 - languageName: node - linkType: hard - "xpath@npm:0.0.32": version: 0.0.32 resolution: "xpath@npm:0.0.32" @@ -46161,7 +45043,7 @@ __metadata: languageName: node linkType: hard -"yaml-ast-parser@npm:0.0.43, yaml-ast-parser@npm:^0.0.43": +"yaml-ast-parser@npm:^0.0.43": version: 0.0.43 resolution: "yaml-ast-parser@npm:0.0.43" checksum: fb5df4c067b6ccbd00953a46faf6ff27f0e290d623c712dc41f330251118f110e22cfd184bbff498bd969cbcda3cd27e0f9d0adb9e6d90eb60ccafc0d8e28077 @@ -46183,7 +45065,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:2.3.4, yaml@npm:^2.0.0, yaml@npm:^2.0.0-10, yaml@npm:^2.1.1, yaml@npm:^2.2.1, yaml@npm:^2.2.2, yaml@npm:^2.3.2": +"yaml@npm:2.3.4, yaml@npm:^2.0.0, yaml@npm:^2.0.0-10, yaml@npm:^2.1.1, yaml@npm:^2.2.1, yaml@npm:^2.2.2, yaml@npm:^2.3.2, yaml@npm:^2.3.3": version: 2.3.4 resolution: "yaml@npm:2.3.4" checksum: e6d1dae1c6383bcc8ba11796eef3b8c02d5082911c6723efeeb5ba50fc8e881df18d645e64de68e421b577296000bea9c75d6d9097c2f6699da3ae0406c030d8 @@ -46221,7 +45103,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^15.1.0, yargs@npm:^15.3.1": +"yargs@npm:^15.1.0": version: 15.4.1 resolution: "yargs@npm:15.4.1" dependencies: @@ -46255,7 +45137,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^17.0.0, yargs@npm:^17.1.1, yargs@npm:^17.2.1, yargs@npm:^17.3.1, yargs@npm:^17.7.1, yargs@npm:^17.7.2": +"yargs@npm:^17.1.1, yargs@npm:^17.2.1, yargs@npm:^17.3.1, yargs@npm:^17.7.1, yargs@npm:^17.7.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: @@ -46404,7 +45286,7 @@ __metadata: languageName: node linkType: hard -"zen-observable-ts@npm:^1.1.0, zen-observable-ts@npm:^1.2.5": +"zen-observable-ts@npm:^1.1.0": version: 1.2.5 resolution: "zen-observable-ts@npm:1.2.5" dependencies: @@ -46445,12 +45327,23 @@ __metadata: languageName: node linkType: hard +"zip-stream@npm:^5.0.1": + version: 5.0.1 + resolution: "zip-stream@npm:5.0.1" + dependencies: + archiver-utils: ^4.0.1 + compress-commons: ^5.0.1 + readable-stream: ^3.6.0 + checksum: 116cee5a2c1ecce7aa440b665470653f58ef56670c6aafa1b5491c9f9335992352145502af5fa865ac82f46336905e37fb7cbc649c2be72e2152c6b91802995c + languageName: node + linkType: hard + "zod-to-json-schema@npm:^3.20.4, zod-to-json-schema@npm:^3.21.4": - version: 3.21.4 - resolution: "zod-to-json-schema@npm:3.21.4" + version: 3.22.1 + resolution: "zod-to-json-schema@npm:3.22.1" peerDependencies: - zod: ^3.21.4 - checksum: 899c1f461fb6547c0b08a265c82040c250be9b88d3f408f2f3ff77a418fdfad7549077e589d418fccb312c1f6d555c3c7217b199cc9072762e1fab20716dd2a6 + zod: ^3.22.4 + checksum: 7c0cdcf0acac81a9b69b26e44bc45e43aefacd5759e12f89856f0a4b957b66be27560671473ef7ab4a5883a871b6990a7f61fce3cee96ecad3823c5b7e524fa5 languageName: node linkType: hard