diff --git a/.changeset/angry-badgers-beg.md b/.changeset/angry-badgers-beg.md deleted file mode 100644 index 38952aef98..0000000000 --- a/.changeset/angry-badgers-beg.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Internal update for removal of experimental plugin configuration API. diff --git a/.changeset/angry-clocks-exercise.md b/.changeset/angry-clocks-exercise.md deleted file mode 100644 index e7eb6ae1d9..0000000000 --- a/.changeset/angry-clocks-exercise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-nomad-backend': patch ---- - -Added support for the [new backend system](https://backstage.io/docs/backend-system/) diff --git a/.changeset/big-spies-beam.md b/.changeset/big-spies-beam.md deleted file mode 100644 index e5f0ad3eff..0000000000 --- a/.changeset/big-spies-beam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Removed duplicate `apple-touch-icon` link from `packages/app/public/index.html` that linked to nonexistent icon. diff --git a/.changeset/breezy-dryers-thank.md b/.changeset/breezy-dryers-thank.md deleted file mode 100644 index 7a742db1bf..0000000000 --- a/.changeset/breezy-dryers-thank.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/backend-tasks': patch ---- - -Instrument `backend-tasks` with some counters and histograms for duration. - -`backend_tasks.task.runs.count`: Counter with the total number of times a task has been run. -`backend_tasks.task.runs.duration`: Histogram with the run durations for each task. - -Both these metrics have come with `result` `taskId` and `scope` labels for finer grained grouping. diff --git a/.changeset/calm-carpets-kiss.md b/.changeset/calm-carpets-kiss.md deleted file mode 100644 index b946e4d9c6..0000000000 --- a/.changeset/calm-carpets-kiss.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -The `HostDiscovery` export has been deprecated, import it from `@backstage/backend-app-api` instead. diff --git a/.changeset/calm-scissors-rescue.md b/.changeset/calm-scissors-rescue.md deleted file mode 100644 index 4a5318d240..0000000000 --- a/.changeset/calm-scissors-rescue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Create unique temp directory for each `create-app` execution. diff --git a/.changeset/chatty-papayas-care.md b/.changeset/chatty-papayas-care.md deleted file mode 100644 index 9f29e94a85..0000000000 --- a/.changeset/chatty-papayas-care.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-pagerduty': patch ---- - -Minor fix to avoid usage of deprecated prop diff --git a/.changeset/chilled-knives-rule.md b/.changeset/chilled-knives-rule.md new file mode 100644 index 0000000000..f246beabbd --- /dev/null +++ b/.changeset/chilled-knives-rule.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Create an experimental plugin that is compatible with the declarative integration system, it is exported from the `/alpha` subpath. diff --git a/.changeset/clean-forks-love.md b/.changeset/clean-forks-love.md deleted file mode 100644 index f81fe3066b..0000000000 --- a/.changeset/clean-forks-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-sonarqube-backend': patch ---- - -Added support for the [new backend system](https://backstage.io/docs/backend-system/) diff --git a/.changeset/cold-bees-jam.md b/.changeset/cold-bees-jam.md deleted file mode 100644 index 3c6e652d2b..0000000000 --- a/.changeset/cold-bees-jam.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-org': patch ---- - -Fixed the display of OwnershipCard with aggregated relations by loading relations when getting children of entity. -This allows the already existing recursive method to work properly when children of entity have children themselves. diff --git a/.changeset/cold-seas-repeat.md b/.changeset/cold-seas-repeat.md deleted file mode 100644 index 0072c4327d..0000000000 --- a/.changeset/cold-seas-repeat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-code-coverage': patch ---- - -Fixed the coverage history statistics to compare newest with oldest record diff --git a/.changeset/dull-bugs-build.md b/.changeset/dull-bugs-build.md deleted file mode 100644 index 7acfe2a8a2..0000000000 --- a/.changeset/dull-bugs-build.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@backstage/plugin-search-backend-module-elasticsearch': patch -'@backstage/integration': patch ---- - -Ensure that all relevant config fields are properly marked as secret diff --git a/.changeset/dull-dolls-explode.md b/.changeset/dull-dolls-explode.md deleted file mode 100644 index 10088e0818..0000000000 --- a/.changeset/dull-dolls-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-playlist-backend': patch ---- - -Added support to the playlist plugin for the new backend diff --git a/.changeset/dull-experts-kiss.md b/.changeset/dull-experts-kiss.md deleted file mode 100644 index eaea346e49..0000000000 --- a/.changeset/dull-experts-kiss.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-react': patch ---- - -Fixed an issue causing `EntityPage` to show an error for entities containing special characters diff --git a/.changeset/dull-laws-camp.md b/.changeset/dull-laws-camp.md deleted file mode 100644 index 9a9c7436c5..0000000000 --- a/.changeset/dull-laws-camp.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Change base node image from node:18-bullseye-slim to node:18-bookworm-slim due to Docker build error on bullseye. - -You can apply these change to your own `Dockerfile` by replacing `node:18-bullseye-slim` with `node:18-bookworm-slim` diff --git a/.changeset/early-toes-develop.md b/.changeset/early-toes-develop.md deleted file mode 100644 index 3262ff0b98..0000000000 --- a/.changeset/early-toes-develop.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/plugin-techdocs-backend': minor -'@backstage/plugin-techdocs-node': minor ---- - -Allow prepared directory clean up for custom preparers - -When using custom preparer for TechDocs, the `preparedDir` might -end up taking disk space. This requires all custom preparers to -implement a new method `shouldCleanPreparedDirectory` which indicates -whether the prepared directory should be cleaned after generation. diff --git a/.changeset/eight-melons-cough.md b/.changeset/eight-melons-cough.md deleted file mode 100644 index 23d7b901f1..0000000000 --- a/.changeset/eight-melons-cough.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Create an experimental `CatalogSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. diff --git a/.changeset/eighty-actors-type.md b/.changeset/eighty-actors-type.md deleted file mode 100644 index 5c55a7b0c6..0000000000 --- a/.changeset/eighty-actors-type.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/test-utils': patch ---- - -Removed the alpha `MockPluginProvider` export since the plugin configuration API has been removed. diff --git a/.changeset/eighty-chairs-camp.md b/.changeset/eighty-chairs-camp.md new file mode 100644 index 0000000000..6a240609d4 --- /dev/null +++ b/.changeset/eighty-chairs-camp.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': minor +--- + +Added `RouteRef`, `SubRouteRef`, `ExternalRouteRef`, and related types. All exports from this package that previously relied on the types with the same name from `@backstage/core-plugin-api` now use the new types instead. To convert and existing legacy route ref to be compatible with the APIs from this package, use the `convertLegacyRouteRef` utility from `@backstage/core-plugin-api/alpha`. diff --git a/.changeset/fair-frogs-enjoy.md b/.changeset/fair-frogs-enjoy.md deleted file mode 100644 index 12eb57489e..0000000000 --- a/.changeset/fair-frogs-enjoy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Create an experimental `TechDocsSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. diff --git a/.changeset/fair-parrots-lick.md b/.changeset/fair-parrots-lick.md new file mode 100644 index 0000000000..dffe6be1e2 --- /dev/null +++ b/.changeset/fair-parrots-lick.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-home': patch +--- + +Remove the duplicate versions of `@rjsf/*` as they're no longer needed diff --git a/.changeset/fifty-taxis-allow.md b/.changeset/fifty-taxis-allow.md new file mode 100644 index 0000000000..1b818f45e7 --- /dev/null +++ b/.changeset/fifty-taxis-allow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-common': patch +--- + +Add missing required property `type` in `Template.v1beta3.schema.json` schema diff --git a/.changeset/flat-pandas-tan.md b/.changeset/flat-pandas-tan.md deleted file mode 100644 index dfe7965bec..0000000000 --- a/.changeset/flat-pandas-tan.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Added `createMockDirectory()` to help out with file system mocking in tests. diff --git a/.changeset/four-jars-protect.md b/.changeset/four-jars-protect.md deleted file mode 100644 index 8469839856..0000000000 --- a/.changeset/four-jars-protect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-rollbar-backend': patch ---- - -ensure rollbar token is hidden diff --git a/.changeset/four-onions-clap.md b/.changeset/four-onions-clap.md deleted file mode 100644 index 44d0cf9ae7..0000000000 --- a/.changeset/four-onions-clap.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Fix for the new backend `start` command to make it work on Windows. diff --git a/.changeset/four-pans-sin.md b/.changeset/four-pans-sin.md deleted file mode 100644 index 46d31c242c..0000000000 --- a/.changeset/four-pans-sin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Marked the `LocationEntityProcessor` as deprecated, as it is no longer used internally since way back and can even be harmful at this point. diff --git a/.changeset/fresh-badgers-study.md b/.changeset/fresh-badgers-study.md deleted file mode 100644 index 4c9e7ee627..0000000000 --- a/.changeset/fresh-badgers-study.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': patch ---- - -Wrap entire app in ``, enabling support for using translations outside plugins. diff --git a/.changeset/fresh-kangaroos-tap.md b/.changeset/fresh-kangaroos-tap.md deleted file mode 100644 index 5ac4d184eb..0000000000 --- a/.changeset/fresh-kangaroos-tap.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-plugin-api': minor ---- - -Removed the exprimental plugin configuration API. The `__experimentalReconfigure()` from the plugin options as well as the `__experimentalConfigure()` method on plugin instances have both been removed. diff --git a/.changeset/fuzzy-pillows-remain.md b/.changeset/fuzzy-pillows-remain.md deleted file mode 100644 index 59e3dd7896..0000000000 --- a/.changeset/fuzzy-pillows-remain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Improved `DocsTable` to display pagination controls dynamically, appearing only when needed. diff --git a/.changeset/gentle-elephants-fold.md b/.changeset/gentle-elephants-fold.md deleted file mode 100644 index 480ee41e7a..0000000000 --- a/.changeset/gentle-elephants-fold.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -'@backstage/plugin-catalog': minor ---- - -The catalog plugin no longer implements the experimental reconfiguration API. The create button title can now instead be configured using the new experimental internationalization API, via the `catalogTranslationRef` exported at `/alpha`. For example: - -```ts -import { catalogTranslationRef } from '@backstage/plugin-catalog/alpha'; - -const app = createApp({ - __experimentalTranslations: { - resources: [ - createTranslationMessages({ - ref: catalogTranslationRef, - catalog_page_create_button_title: 'Create Software', - }), - ], - }, -}); -``` diff --git a/.changeset/gentle-spies-deny.md b/.changeset/gentle-spies-deny.md deleted file mode 100644 index f2d0ea7d79..0000000000 --- a/.changeset/gentle-spies-deny.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-bitbucket-server': patch -'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch -'@backstage/plugin-catalog-backend-module-puppetdb': patch -'@backstage/plugin-catalog-backend-module-msgraph': patch -'@backstage/plugin-catalog-backend-module-gerrit': patch -'@backstage/plugin-catalog-backend-module-github': patch -'@backstage/plugin-catalog-backend-module-gitlab': patch -'@backstage/plugin-catalog-backend-module-azure': patch -'@backstage/plugin-catalog-backend-module-ldap': patch -'@backstage/plugin-catalog-backend-module-aws': patch ---- - -Make sure to include the error message when ingestion fails diff --git a/.changeset/great-walls-brake.md b/.changeset/great-walls-brake.md deleted file mode 100644 index dd71c81a07..0000000000 --- a/.changeset/great-walls-brake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Properly close write stream when writing temporary archive for processing zip-based `.readTree()` responses. diff --git a/.changeset/happy-books-smoke.md b/.changeset/happy-books-smoke.md deleted file mode 100644 index 68ea19ea5e..0000000000 --- a/.changeset/happy-books-smoke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-home': patch ---- - -Adds Top/Recently Visited components to homepage diff --git a/.changeset/healthy-shirts-fold.md b/.changeset/healthy-shirts-fold.md new file mode 100644 index 0000000000..f2ac0a9e83 --- /dev/null +++ b/.changeset/healthy-shirts-fold.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-catalog': patch +'@backstage/plugin-techdocs': patch +--- + +The `spec.lifecycle' field in entities will now always be rendered as a string. diff --git a/.changeset/heavy-forks-tie.md b/.changeset/heavy-forks-tie.md deleted file mode 100644 index f5af5975b7..0000000000 --- a/.changeset/heavy-forks-tie.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-node': patch ---- - -Added docs to `processingResult` diff --git a/.changeset/heavy-ladybugs-leave.md b/.changeset/heavy-ladybugs-leave.md deleted file mode 100644 index 5af2324260..0000000000 --- a/.changeset/heavy-ladybugs-leave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-newrelic': patch ---- - -Fixed sorting and searching in the NewRelic table. diff --git a/.changeset/hungry-paws-dress.md b/.changeset/hungry-paws-dress.md new file mode 100644 index 0000000000..b227a77e72 --- /dev/null +++ b/.changeset/hungry-paws-dress.md @@ -0,0 +1,9 @@ +--- +'@backstage/plugin-user-settings': patch +'@backstage/plugin-techdocs': patch +'@backstage/plugin-tech-radar': patch +'@backstage/plugin-graphiql': patch +'@backstage/plugin-search': patch +--- + +Updated alpha exports according to routing changes in `@backstage/frontend-plugin-api`. diff --git a/.changeset/hungry-radios-play.md b/.changeset/hungry-radios-play.md new file mode 100644 index 0000000000..ce7f524f4a --- /dev/null +++ b/.changeset/hungry-radios-play.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-user-settings-backend': patch +--- + +Added dependency on `@backstage/config` diff --git a/.changeset/itchy-bobcats-fly.md b/.changeset/itchy-bobcats-fly.md deleted file mode 100644 index e91d944478..0000000000 --- a/.changeset/itchy-bobcats-fly.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Added the ability to fetch git tags through the `Git` class. This is useful for scaffolder actions that want to take action based on tag versions in a cloned repository diff --git a/.changeset/itchy-monkeys-reply.md b/.changeset/itchy-monkeys-reply.md deleted file mode 100644 index 3773fe3ff8..0000000000 --- a/.changeset/itchy-monkeys-reply.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-dev-utils': patch ---- - -Fix an issue where early IPC responses would be lost. diff --git a/.changeset/itchy-rabbits-exist.md b/.changeset/itchy-rabbits-exist.md deleted file mode 100644 index acac771a97..0000000000 --- a/.changeset/itchy-rabbits-exist.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/cli': minor ---- - -The new backend start command that used to be enabled by setting `EXPERIMENTAL_BACKEND_START` is now the default. To revert to the old behavior, set `LEGACY_BACKEND_START` instead. - -This new command is no longer based on Webpack, but instead uses Node.js loaders to transpile on the fly. Rather than hot reloading modules the entire backend is now restarted on change, but the SQLite database state is still maintained across restarts via a parent process. diff --git a/.changeset/large-comics-knock.md b/.changeset/large-comics-knock.md deleted file mode 100644 index 860172579e..0000000000 --- a/.changeset/large-comics-knock.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -fixed issue related template editor fails with multiple templates per file. diff --git a/.changeset/late-papayas-push.md b/.changeset/late-papayas-push.md deleted file mode 100644 index 07422e1b1b..0000000000 --- a/.changeset/late-papayas-push.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-plugin-api': patch ---- - -Add support for `SidebarGroup` on the sidebar item extension. diff --git a/.changeset/lazy-doors-wink.md b/.changeset/lazy-doors-wink.md deleted file mode 100644 index aafbb3500e..0000000000 --- a/.changeset/lazy-doors-wink.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend': minor ---- - -Display meaningful error to the output if Gitlab namespace not found inside `publish:gitlab`. diff --git a/.changeset/lazy-hotels-wait.md b/.changeset/lazy-hotels-wait.md new file mode 100644 index 0000000000..85879880f5 --- /dev/null +++ b/.changeset/lazy-hotels-wait.md @@ -0,0 +1,109 @@ +--- +'@backstage/plugin-analytics-module-newrelic-browser': patch +'@backstage/plugin-api-docs-module-protoc-gen-doc': patch +'@backstage/plugin-techdocs-module-addons-contrib': patch +'@backstage/plugin-cicd-statistics-module-gitlab': patch +'@backstage/plugin-catalog-unprocessed-entities': patch +'@backstage/plugin-github-pull-requests-board': patch +'@backstage/plugin-techdocs-addons-test-utils': patch +'@backstage/frontend-plugin-api': patch +'@backstage/plugin-analytics-module-ga4': patch +'@backstage/plugin-analytics-module-ga': patch +'@backstage/plugin-git-release-manager': patch +'@backstage/integration-react': patch +'@backstage/plugin-github-deployments': patch +'@backstage/plugin-kubernetes-cluster': patch +'@backstage/plugin-microsoft-calendar': patch +'@backstage/plugin-newrelic-dashboard': patch +'@backstage/frontend-app-api': patch +'@backstage/plugin-entity-validation': patch +'@backstage/core-components': patch +'@backstage/core-plugin-api': patch +'@backstage/plugin-kubernetes-react': patch +'@backstage/plugin-permission-react': patch +'@backstage/plugin-scaffolder-react': patch +'@backstage/version-bridge': patch +'@backstage/plugin-apollo-explorer': patch +'@backstage/plugin-catalog-graphql': patch +'@backstage/plugin-cicd-statistics': patch +'@backstage/plugin-entity-feedback': patch +'@backstage/plugin-gitops-profiles': patch +'@backstage/plugin-graphql-voyager': patch +'@backstage/plugin-sonarqube-react': patch +'@backstage/plugin-apache-airflow': patch +'@backstage/plugin-catalog-import': patch +'@backstage/plugin-github-actions': patch +'@backstage/plugin-octopus-deploy': patch +'@backstage/plugin-splunk-on-call': patch +'@backstage/plugin-stack-overflow': patch +'@backstage/plugin-techdocs-react': patch +'@backstage/app-defaults': patch +'@backstage/core-app-api': patch +'@backstage/plugin-catalog-graph': patch +'@backstage/plugin-catalog-react': patch +'@backstage/plugin-code-coverage': patch +'@backstage/plugin-config-schema': patch +'@backstage/plugin-cost-insights': patch +'@backstage/plugin-explore-react': patch +'@backstage/plugin-github-issues': patch +'@backstage/plugin-tech-insights': patch +'@backstage/plugin-user-settings': patch +'@backstage/plugin-azure-devops': patch +'@backstage/plugin-code-climate': patch +'@backstage/plugin-gcp-projects': patch +'@backstage/plugin-search-react': patch +'@backstage/create-app': patch +'@backstage/test-utils': patch +'@backstage/plugin-azure-sites': patch +'@backstage/plugin-firehydrant': patch +'@backstage/plugin-cloudbuild': patch +'@backstage/plugin-home-react': patch +'@backstage/plugin-kubernetes': patch +'@backstage/plugin-lighthouse': patch +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-stackstorm': patch +'@backstage/plugin-tech-radar': patch +'@backstage/plugin-codescene': patch +'@backstage/plugin-dynatrace': patch +'@backstage/plugin-gcalendar': patch +'@backstage/plugin-org-react': patch +'@backstage/plugin-pagerduty': patch +'@backstage/plugin-shortcuts': patch +'@backstage/plugin-sonarqube': patch +'@backstage/plugin-xcmetrics': patch +'@backstage/plugin-airbrake': patch +'@backstage/plugin-api-docs': patch +'@backstage/plugin-circleci': patch +'@backstage/plugin-devtools': patch +'@backstage/plugin-graphiql': patch +'@backstage/plugin-linguist': patch +'@backstage/plugin-newrelic': patch +'@backstage/plugin-opencost': patch +'@backstage/plugin-periskop': patch +'@backstage/plugin-playlist': patch +'@backstage/plugin-puppetdb': patch +'@backstage/plugin-techdocs': patch +'@backstage/plugin-bitrise': patch +'@backstage/plugin-catalog': patch +'@backstage/plugin-explore': patch +'@backstage/plugin-jenkins': patch +'@backstage/plugin-rollbar': patch +'@backstage/theme': patch +'@backstage/plugin-allure': patch +'@backstage/plugin-badges': patch +'@backstage/plugin-bazaar': patch +'@backstage/plugin-search': patch +'@backstage/plugin-sentry': patch +'@backstage/plugin-fossa': patch +'@backstage/plugin-ilert': patch +'@backstage/plugin-kafka': patch +'@backstage/plugin-nomad': patch +'@backstage/plugin-vault': patch +'@backstage/plugin-gocd': patch +'@backstage/plugin-home': patch +'@backstage/plugin-todo': patch +'@backstage/plugin-adr': patch +'@backstage/plugin-org': patch +--- + +Add official support for React 18. diff --git a/.changeset/lemon-cups-wait.md b/.changeset/lemon-cups-wait.md deleted file mode 100644 index 4dd08c21b0..0000000000 --- a/.changeset/lemon-cups-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': minor ---- - -include owner chip in catalog search result item diff --git a/.changeset/lemon-masks-greet.md b/.changeset/lemon-masks-greet.md deleted file mode 100644 index 79c7b7e92b..0000000000 --- a/.changeset/lemon-masks-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -The `TabbedLayout` component will now also navigate when clicking the active tab, which allows for navigation back from any sub routes. diff --git a/.changeset/lovely-coins-occur.md b/.changeset/lovely-coins-occur.md deleted file mode 100644 index 34a6774388..0000000000 --- a/.changeset/lovely-coins-occur.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Fixes a bug where eagerly deleted entities did not properly trigger re-stitching of entities that they had relations to. diff --git a/.changeset/lovely-fans-sniff.md b/.changeset/lovely-fans-sniff.md deleted file mode 100644 index af8aebb89b..0000000000 --- a/.changeset/lovely-fans-sniff.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-tech-radar': patch ---- - -Added experimental support for the declarative integration. diff --git a/.changeset/many-pianos-bow.md b/.changeset/many-pianos-bow.md deleted file mode 100644 index 6c4e3be47f..0000000000 --- a/.changeset/many-pianos-bow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-adr': patch ---- - -Fix icon alignment in `AdrSearchResultListItem` diff --git a/.changeset/many-swans-eat.md b/.changeset/many-swans-eat.md deleted file mode 100644 index 86580d7cfe..0000000000 --- a/.changeset/many-swans-eat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-badges-backend': patch ---- - -Make sure the default badge factory is used if nothing is defined diff --git a/.changeset/mean-dancers-burn.md b/.changeset/mean-dancers-burn.md deleted file mode 100644 index a51ca7b8de..0000000000 --- a/.changeset/mean-dancers-burn.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/core-app-api': patch -'@backstage/app-defaults': patch -'@backstage/test-utils': patch ---- - -Add missing resource and template app icons diff --git a/.changeset/metal-peas-beam.md b/.changeset/metal-peas-beam.md deleted file mode 100644 index a4ebdeb69a..0000000000 --- a/.changeset/metal-peas-beam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-scaffolder': patch ---- - -Display log visibility button on the template panel diff --git a/.changeset/modern-ducks-battle.md b/.changeset/modern-ducks-battle.md new file mode 100644 index 0000000000..e8359cf4ac --- /dev/null +++ b/.changeset/modern-ducks-battle.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': minor +--- + +Added the ability to configure bound routes through `app.routes.bindings`. The routing system used by `createApp` has been replaced by one that only supports route refs of the new format from `@backstage/frontend-plugin-api`. The requirement for route refs to have the same ID as their associated extension has been removed. diff --git a/.changeset/moody-lobsters-rescue.md b/.changeset/moody-lobsters-rescue.md deleted file mode 100644 index c739e995c5..0000000000 --- a/.changeset/moody-lobsters-rescue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Bump `cypress` to fix the end-to-end tests diff --git a/.changeset/nasty-needles-hear.md b/.changeset/nasty-needles-hear.md deleted file mode 100644 index 32a9d0dfb7..0000000000 --- a/.changeset/nasty-needles-hear.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Added `/testUtils` entry point, with a utility for mocking resolve package paths as returned by `resolvePackagePath`. diff --git a/.changeset/nervous-hounds-sleep.md b/.changeset/nervous-hounds-sleep.md deleted file mode 100644 index 530ff348f7..0000000000 --- a/.changeset/nervous-hounds-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Make themes configurable through extensions, and switched default themes to use extensions instead. diff --git a/.changeset/new-beers-drive.md b/.changeset/new-beers-drive.md new file mode 100644 index 0000000000..370734b7c5 --- /dev/null +++ b/.changeset/new-beers-drive.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Create declarative extensions for the `Catalog` plugin; this initial plugin preset contains sidebar item, index page and filter extensions, all distributed via `/alpha` subpath. + +The `EntityPage` will be migrated in a follow-up patch. diff --git a/.changeset/nice-clocks-smash.md b/.changeset/nice-clocks-smash.md deleted file mode 100644 index 8a289370e5..0000000000 --- a/.changeset/nice-clocks-smash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-tech-insights-backend': patch ---- - -Increase the maximum allowed length of an entity filter for tech insights fact schemas. diff --git a/.changeset/nice-dancers-explain.md b/.changeset/nice-dancers-explain.md deleted file mode 100644 index 5e54a66c05..0000000000 --- a/.changeset/nice-dancers-explain.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-backend-module-github-provider': patch ---- - -Fixed a bug where the GitHub authenticator did not properly persist granted OAuth scopes. diff --git a/.changeset/nine-garlics-attend.md b/.changeset/nine-garlics-attend.md deleted file mode 100644 index a9cdac4a32..0000000000 --- a/.changeset/nine-garlics-attend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-tasks': patch ---- - -Fix bug where backend tasks that are defined with HumanDuration are immediately triggered on application startup diff --git a/.changeset/ninety-numbers-study.md b/.changeset/ninety-numbers-study.md new file mode 100644 index 0000000000..e77131fab9 --- /dev/null +++ b/.changeset/ninety-numbers-study.md @@ -0,0 +1,7 @@ +--- +'@backstage/core-components': patch +--- + +Fixed compatibility with Safari <16.3 by eliminating RegEx lookbehind in `extractInitials`. + +This PR also changed how initials are generated resulting in _John Jonathan Doe_ => _JD_ instead of _JJ_. diff --git a/.changeset/olive-cars-rescue.md b/.changeset/olive-cars-rescue.md deleted file mode 100644 index fd6c8fe331..0000000000 --- a/.changeset/olive-cars-rescue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search': patch ---- - -Create an experimental search plugin that is compatible with the declarative integration system, it is exported from `/alpha` subpath. diff --git a/.changeset/perfect-pumas-protect.md b/.changeset/perfect-pumas-protect.md deleted file mode 100644 index 7d6bf8d6d7..0000000000 --- a/.changeset/perfect-pumas-protect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-code-coverage-backend': patch ---- - -Added option to set body size limit diff --git a/.changeset/plenty-llamas-double.md b/.changeset/plenty-llamas-double.md deleted file mode 100644 index b2691a2f17..0000000000 --- a/.changeset/plenty-llamas-double.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-node': patch ---- - -Fix for persisted scopes not being properly restored on sign-in. diff --git a/.changeset/polite-cooks-perform.md b/.changeset/polite-cooks-perform.md deleted file mode 100644 index 40766c84a3..0000000000 --- a/.changeset/polite-cooks-perform.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': minor ---- - -The `createApp` config option has been replaced by a new `configLoader` option. There is now also a `pluginLoader` option that can be used to dynamically load plugins into the app. diff --git a/.changeset/polite-donuts-fail.md b/.changeset/polite-donuts-fail.md deleted file mode 100644 index 9c03faaf44..0000000000 --- a/.changeset/polite-donuts-fail.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': patch ---- - -Internal refactors, laying the foundation for later introducing deferred stitching (see #18062). diff --git a/.changeset/polite-trainers-grin.md b/.changeset/polite-trainers-grin.md deleted file mode 100644 index 878596702d..0000000000 --- a/.changeset/polite-trainers-grin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-github': patch ---- - -Make `defaultUserTransformer` resolve to `UserEntity` instead of `Entity` diff --git a/.changeset/popular-bikes-do.md b/.changeset/popular-bikes-do.md new file mode 100644 index 0000000000..b1cc5c2cdd --- /dev/null +++ b/.changeset/popular-bikes-do.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-code-coverage': patch +--- + +The warning for missing code coverage will now render the entity as a reference. diff --git a/.changeset/popular-dots-design.md b/.changeset/popular-dots-design.md deleted file mode 100644 index c333ce0105..0000000000 --- a/.changeset/popular-dots-design.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Changed SupportButton menuitems to support text wrap diff --git a/.changeset/pre.json b/.changeset/pre.json index d767fe77f0..4a9428d0cd 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -2,330 +2,255 @@ "mode": "pre", "tag": "next", "initialVersions": { - "example-app": "0.2.87", - "@backstage/app-defaults": "1.4.3", - "example-app-next": "0.0.1", - "app-next-example-plugin": "0.0.1", - "example-backend": "0.2.87", - "@backstage/backend-app-api": "0.5.3", - "@backstage/backend-common": "0.19.5", - "@backstage/backend-defaults": "0.2.3", - "@backstage/backend-dev-utils": "0.1.1", - "example-backend-next": "0.0.15", - "@backstage/backend-openapi-utils": "0.0.4", - "@backstage/backend-plugin-api": "0.6.3", - "@backstage/backend-plugin-manager": "0.0.1", - "@backstage/backend-tasks": "0.5.8", - "@backstage/backend-test-utils": "0.2.3", - "@backstage/catalog-client": "1.4.4", - "@backstage/catalog-model": "1.4.2", - "@backstage/cli": "0.22.13", - "@backstage/cli-common": "0.1.12", - "@backstage/cli-node": "0.1.4", - "@backstage/codemods": "0.1.45", - "@backstage/config": "1.1.0", - "@backstage/config-loader": "1.5.0", - "@backstage/core-app-api": "1.10.0", - "@backstage/core-components": "0.13.5", - "@backstage/core-plugin-api": "1.6.0", - "@backstage/create-app": "0.5.5", - "@backstage/dev-utils": "1.0.21", - "e2e-test": "0.2.7", - "@backstage/errors": "1.2.2", + "example-app": "0.2.88", + "@backstage/app-defaults": "1.4.4", + "example-app-next": "0.0.2", + "app-next-example-plugin": "0.0.2", + "example-backend": "0.2.88", + "@backstage/backend-app-api": "0.5.6", + "@backstage/backend-common": "0.19.8", + "@backstage/backend-defaults": "0.2.6", + "@backstage/backend-dev-utils": "0.1.2", + "example-backend-next": "0.0.16", + "@backstage/backend-openapi-utils": "0.0.5", + "@backstage/backend-plugin-api": "0.6.6", + "@backstage/backend-plugin-manager": "0.0.2", + "@backstage/backend-tasks": "0.5.11", + "@backstage/backend-test-utils": "0.2.7", + "@backstage/catalog-client": "1.4.5", + "@backstage/catalog-model": "1.4.3", + "@backstage/cli": "0.23.0", + "@backstage/cli-common": "0.1.13", + "@backstage/cli-node": "0.1.5", + "@backstage/codemods": "0.1.46", + "@backstage/config": "1.1.1", + "@backstage/config-loader": "1.5.1", + "@backstage/core-app-api": "1.11.0", + "@backstage/core-components": "0.13.6", + "@backstage/core-plugin-api": "1.7.0", + "@backstage/create-app": "0.5.6", + "@backstage/dev-utils": "1.0.22", + "e2e-test": "0.2.8", + "@backstage/e2e-test-utils": "0.1.0", + "@backstage/errors": "1.2.3", "@backstage/eslint-plugin": "0.1.3", - "@backstage/frontend-app-api": "0.1.0", - "@backstage/frontend-plugin-api": "0.1.0", - "@backstage/integration": "1.7.0", - "@backstage/integration-aws-node": "0.1.6", - "@backstage/integration-react": "1.1.19", + "@backstage/frontend-app-api": "0.2.0", + "@backstage/frontend-plugin-api": "0.2.0", + "@backstage/integration": "1.7.1", + "@backstage/integration-aws-node": "0.1.7", + "@backstage/integration-react": "1.1.20", "@backstage/release-manifests": "0.0.10", - "@backstage/repo-tools": "0.3.4", - "@techdocs/cli": "1.5.0", - "techdocs-cli-embedded-app": "0.2.86", - "@backstage/test-utils": "1.4.3", - "@backstage/theme": "0.4.2", + "@backstage/repo-tools": "0.3.5", + "@techdocs/cli": "1.6.0", + "techdocs-cli-embedded-app": "0.2.87", + "@backstage/test-utils": "1.4.4", + "@backstage/theme": "0.4.3", "@backstage/types": "1.1.1", - "@backstage/version-bridge": "1.0.5", - "@backstage/plugin-adr": "0.6.7", - "@backstage/plugin-adr-backend": "0.4.0", - "@backstage/plugin-adr-common": "0.2.15", - "@backstage/plugin-airbrake": "0.3.24", - "@backstage/plugin-airbrake-backend": "0.3.0", - "@backstage/plugin-allure": "0.1.40", - "@backstage/plugin-analytics-module-ga": "0.1.33", - "@backstage/plugin-analytics-module-ga4": "0.1.4", - "@backstage/plugin-analytics-module-newrelic-browser": "0.0.2", - "@backstage/plugin-apache-airflow": "0.2.15", - "@backstage/plugin-api-docs": "0.9.11", - "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.3", - "@backstage/plugin-apollo-explorer": "0.1.15", - "@backstage/plugin-app-backend": "0.3.51", - "@backstage/plugin-app-node": "0.1.3", - "@backstage/plugin-auth-backend": "0.19.0", - "@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.1.0", - "@backstage/plugin-auth-backend-module-github-provider": "0.1.0", - "@backstage/plugin-auth-backend-module-gitlab-provider": "0.1.0", - "@backstage/plugin-auth-backend-module-google-provider": "0.1.0", - "@backstage/plugin-auth-backend-module-oauth2-provider": "0.1.0", - "@backstage/plugin-auth-node": "0.3.0", - "@backstage/plugin-azure-devops": "0.3.6", - "@backstage/plugin-azure-devops-backend": "0.4.0", + "@backstage/version-bridge": "1.0.6", + "@backstage/plugin-adr": "0.6.8", + "@backstage/plugin-adr-backend": "0.4.3", + "@backstage/plugin-adr-common": "0.2.16", + "@backstage/plugin-airbrake": "0.3.25", + "@backstage/plugin-airbrake-backend": "0.3.3", + "@backstage/plugin-allure": "0.1.41", + "@backstage/plugin-analytics-module-ga": "0.1.34", + "@backstage/plugin-analytics-module-ga4": "0.1.5", + "@backstage/plugin-analytics-module-newrelic-browser": "0.0.3", + "@backstage/plugin-apache-airflow": "0.2.16", + "@backstage/plugin-api-docs": "0.9.12", + "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.4", + "@backstage/plugin-apollo-explorer": "0.1.16", + "@backstage/plugin-app-backend": "0.3.54", + "@backstage/plugin-app-node": "0.1.6", + "@backstage/plugin-auth-backend": "0.19.3", + "@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.2.0", + "@backstage/plugin-auth-backend-module-github-provider": "0.1.3", + "@backstage/plugin-auth-backend-module-gitlab-provider": "0.1.3", + "@backstage/plugin-auth-backend-module-google-provider": "0.1.3", + "@backstage/plugin-auth-backend-module-microsoft-provider": "0.1.0", + "@backstage/plugin-auth-backend-module-oauth2-provider": "0.1.3", + "@backstage/plugin-auth-backend-module-pinniped-provider": "0.1.0", + "@backstage/plugin-auth-node": "0.4.0", + "@backstage/plugin-azure-devops": "0.3.7", + "@backstage/plugin-azure-devops-backend": "0.4.3", "@backstage/plugin-azure-devops-common": "0.3.1", - "@backstage/plugin-azure-sites": "0.1.13", - "@backstage/plugin-azure-sites-backend": "0.1.13", + "@backstage/plugin-azure-sites": "0.1.14", + "@backstage/plugin-azure-sites-backend": "0.1.16", "@backstage/plugin-azure-sites-common": "0.1.1", - "@backstage/plugin-badges": "0.2.48", - "@backstage/plugin-badges-backend": "0.3.0", - "@backstage/plugin-bazaar": "0.2.16", - "@backstage/plugin-bazaar-backend": "0.3.0", - "@backstage/plugin-bitbucket-cloud-common": "0.2.12", - "@backstage/plugin-bitrise": "0.1.51", - "@backstage/plugin-catalog": "1.13.0", - "@backstage/plugin-catalog-backend": "1.13.0", - "@backstage/plugin-catalog-backend-module-aws": "0.2.6", - "@backstage/plugin-catalog-backend-module-azure": "0.1.22", - "@backstage/plugin-catalog-backend-module-bitbucket": "0.2.18", - "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.1.18", - "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.1.16", - "@backstage/plugin-catalog-backend-module-gcp": "0.1.3", - "@backstage/plugin-catalog-backend-module-gerrit": "0.1.19", - "@backstage/plugin-catalog-backend-module-github": "0.4.0", - "@backstage/plugin-catalog-backend-module-gitlab": "0.3.0", - "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.4.6", - "@backstage/plugin-catalog-backend-module-ldap": "0.5.18", - "@backstage/plugin-catalog-backend-module-msgraph": "0.5.10", - "@backstage/plugin-catalog-backend-module-openapi": "0.1.19", - "@backstage/plugin-catalog-backend-module-puppetdb": "0.1.8", - "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.1.0", - "@backstage/plugin-catalog-backend-module-unprocessed": "0.3.0", - "@backstage/plugin-catalog-common": "1.0.16", - "@internal/plugin-catalog-customized": "0.0.14", - "@backstage/plugin-catalog-graph": "0.2.36", - "@backstage/plugin-catalog-graphql": "0.3.23", - "@backstage/plugin-catalog-import": "0.10.0", - "@backstage/plugin-catalog-node": "1.4.4", - "@backstage/plugin-catalog-react": "1.8.4", - "@backstage/plugin-catalog-unprocessed-entities": "0.1.3", - "@backstage/plugin-cicd-statistics": "0.1.26", - "@backstage/plugin-cicd-statistics-module-gitlab": "0.1.20", - "@backstage/plugin-circleci": "0.3.24", - "@backstage/plugin-cloudbuild": "0.3.24", - "@backstage/plugin-code-climate": "0.1.24", - "@backstage/plugin-code-coverage": "0.2.17", - "@backstage/plugin-code-coverage-backend": "0.2.17", - "@backstage/plugin-codescene": "0.1.17", - "@backstage/plugin-config-schema": "0.1.45", - "@backstage/plugin-cost-insights": "0.12.13", + "@backstage/plugin-badges": "0.2.49", + "@backstage/plugin-badges-backend": "0.3.3", + "@backstage/plugin-bazaar": "0.2.17", + "@backstage/plugin-bazaar-backend": "0.3.3", + "@backstage/plugin-bitbucket-cloud-common": "0.2.13", + "@backstage/plugin-bitrise": "0.1.52", + "@backstage/plugin-catalog": "1.14.0", + "@backstage/plugin-catalog-backend": "1.14.0", + "@backstage/plugin-catalog-backend-module-aws": "0.3.0", + "@backstage/plugin-catalog-backend-module-azure": "0.1.25", + "@backstage/plugin-catalog-backend-module-bitbucket": "0.2.21", + "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.1.21", + "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.1.19", + "@backstage/plugin-catalog-backend-module-gcp": "0.1.6", + "@backstage/plugin-catalog-backend-module-gerrit": "0.1.22", + "@backstage/plugin-catalog-backend-module-github": "0.4.4", + "@backstage/plugin-catalog-backend-module-github-org": "0.1.0", + "@backstage/plugin-catalog-backend-module-gitlab": "0.3.3", + "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.4.10", + "@backstage/plugin-catalog-backend-module-ldap": "0.5.21", + "@backstage/plugin-catalog-backend-module-msgraph": "0.5.13", + "@backstage/plugin-catalog-backend-module-openapi": "0.1.23", + "@backstage/plugin-catalog-backend-module-puppetdb": "0.1.11", + "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.1.3", + "@backstage/plugin-catalog-backend-module-unprocessed": "0.3.3", + "@backstage/plugin-catalog-common": "1.0.17", + "@backstage/plugin-catalog-graph": "0.2.37", + "@backstage/plugin-catalog-graphql": "0.4.0", + "@backstage/plugin-catalog-import": "0.10.1", + "@backstage/plugin-catalog-node": "1.4.7", + "@backstage/plugin-catalog-react": "1.8.5", + "@backstage/plugin-catalog-unprocessed-entities": "0.1.4", + "@backstage/plugin-cicd-statistics": "0.1.27", + "@backstage/plugin-cicd-statistics-module-gitlab": "0.1.21", + "@backstage/plugin-circleci": "0.3.25", + "@backstage/plugin-cloudbuild": "0.3.25", + "@backstage/plugin-code-climate": "0.1.25", + "@backstage/plugin-code-coverage": "0.2.18", + "@backstage/plugin-code-coverage-backend": "0.2.20", + "@backstage/plugin-codescene": "0.1.18", + "@backstage/plugin-config-schema": "0.1.46", + "@backstage/plugin-cost-insights": "0.12.14", "@backstage/plugin-cost-insights-common": "0.1.2", - "@backstage/plugin-devtools": "0.1.4", - "@backstage/plugin-devtools-backend": "0.2.0", - "@backstage/plugin-devtools-common": "0.1.4", - "@backstage/plugin-dynatrace": "7.0.4", - "@backstage/plugin-entity-feedback": "0.2.7", - "@backstage/plugin-entity-feedback-backend": "0.2.0", + "@backstage/plugin-devtools": "0.1.5", + "@backstage/plugin-devtools-backend": "0.2.3", + "@backstage/plugin-devtools-common": "0.1.5", + "@backstage/plugin-dynatrace": "7.0.5", + "@backstage/plugin-entity-feedback": "0.2.8", + "@backstage/plugin-entity-feedback-backend": "0.2.3", "@backstage/plugin-entity-feedback-common": "0.1.3", - "@backstage/plugin-entity-validation": "0.1.9", - "@backstage/plugin-events-backend": "0.2.12", - "@backstage/plugin-events-backend-module-aws-sqs": "0.2.6", - "@backstage/plugin-events-backend-module-azure": "0.1.13", - "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.1.13", - "@backstage/plugin-events-backend-module-gerrit": "0.1.13", - "@backstage/plugin-events-backend-module-github": "0.1.13", - "@backstage/plugin-events-backend-module-gitlab": "0.1.13", - "@backstage/plugin-events-backend-test-utils": "0.1.13", - "@backstage/plugin-events-node": "0.2.12", - "@internal/plugin-todo-list": "1.0.17", - "@internal/plugin-todo-list-backend": "1.0.17", - "@internal/plugin-todo-list-common": "1.0.13", - "@backstage/plugin-explore": "0.4.10", - "@backstage/plugin-explore-backend": "0.0.13", + "@backstage/plugin-entity-validation": "0.1.10", + "@backstage/plugin-events-backend": "0.2.15", + "@backstage/plugin-events-backend-module-aws-sqs": "0.2.9", + "@backstage/plugin-events-backend-module-azure": "0.1.16", + "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.1.16", + "@backstage/plugin-events-backend-module-gerrit": "0.1.16", + "@backstage/plugin-events-backend-module-github": "0.1.16", + "@backstage/plugin-events-backend-module-gitlab": "0.1.16", + "@backstage/plugin-events-backend-test-utils": "0.1.16", + "@backstage/plugin-events-node": "0.2.15", + "@internal/plugin-todo-list": "1.0.18", + "@internal/plugin-todo-list-backend": "1.0.18", + "@internal/plugin-todo-list-common": "1.0.14", + "@backstage/plugin-explore": "0.4.11", + "@backstage/plugin-explore-backend": "0.0.16", "@backstage/plugin-explore-common": "0.0.2", - "@backstage/plugin-explore-react": "0.0.31", - "@backstage/plugin-firehydrant": "0.2.8", - "@backstage/plugin-fossa": "0.2.56", - "@backstage/plugin-gcalendar": "0.3.18", - "@backstage/plugin-gcp-projects": "0.3.41", - "@backstage/plugin-git-release-manager": "0.3.37", - "@backstage/plugin-github-actions": "0.6.5", - "@backstage/plugin-github-deployments": "0.1.55", - "@backstage/plugin-github-issues": "0.2.13", - "@backstage/plugin-github-pull-requests-board": "0.1.18", - "@backstage/plugin-gitops-profiles": "0.3.40", - "@backstage/plugin-gocd": "0.1.30", - "@backstage/plugin-graphiql": "0.2.54", - "@backstage/plugin-graphql-backend": "0.1.41", - "@backstage/plugin-graphql-voyager": "0.1.7", - "@backstage/plugin-home": "0.5.8", - "@backstage/plugin-home-react": "0.1.3", - "@backstage/plugin-ilert": "0.2.13", - "@backstage/plugin-jenkins": "0.8.6", - "@backstage/plugin-jenkins-backend": "0.2.6", - "@backstage/plugin-jenkins-common": "0.1.19", - "@backstage/plugin-kafka": "0.3.24", - "@backstage/plugin-kafka-backend": "0.3.0", - "@backstage/plugin-kubernetes": "0.10.3", - "@backstage/plugin-kubernetes-backend": "0.12.0", - "@backstage/plugin-kubernetes-common": "0.6.6", - "@backstage/plugin-lighthouse": "0.4.9", - "@backstage/plugin-lighthouse-backend": "0.3.0", - "@backstage/plugin-lighthouse-common": "0.1.3", - "@backstage/plugin-linguist": "0.1.9", - "@backstage/plugin-linguist-backend": "0.5.0", + "@backstage/plugin-explore-react": "0.0.32", + "@backstage/plugin-firehydrant": "0.2.9", + "@backstage/plugin-fossa": "0.2.57", + "@backstage/plugin-gcalendar": "0.3.19", + "@backstage/plugin-gcp-projects": "0.3.42", + "@backstage/plugin-git-release-manager": "0.3.38", + "@backstage/plugin-github-actions": "0.6.6", + "@backstage/plugin-github-deployments": "0.1.56", + "@backstage/plugin-github-issues": "0.2.14", + "@backstage/plugin-github-pull-requests-board": "0.1.19", + "@backstage/plugin-gitops-profiles": "0.3.41", + "@backstage/plugin-gocd": "0.1.31", + "@backstage/plugin-graphiql": "0.2.55", + "@backstage/plugin-graphql-backend": "0.2.0", + "@backstage/plugin-graphql-voyager": "0.1.8", + "@backstage/plugin-home": "0.5.9", + "@backstage/plugin-home-react": "0.1.4", + "@backstage/plugin-ilert": "0.2.14", + "@backstage/plugin-jenkins": "0.9.0", + "@backstage/plugin-jenkins-backend": "0.3.0", + "@backstage/plugin-jenkins-common": "0.1.20", + "@backstage/plugin-kafka": "0.3.25", + "@backstage/plugin-kafka-backend": "0.3.3", + "@backstage/plugin-kubernetes": "0.11.0", + "@backstage/plugin-kubernetes-backend": "0.13.0", + "@backstage/plugin-kubernetes-cluster": "0.0.1", + "@backstage/plugin-kubernetes-common": "0.7.0", + "@backstage/plugin-kubernetes-node": "0.1.0", + "@backstage/plugin-kubernetes-react": "0.1.0", + "@backstage/plugin-lighthouse": "0.4.10", + "@backstage/plugin-lighthouse-backend": "0.3.3", + "@backstage/plugin-lighthouse-common": "0.1.4", + "@backstage/plugin-linguist": "0.1.10", + "@backstage/plugin-linguist-backend": "0.5.3", "@backstage/plugin-linguist-common": "0.1.2", - "@backstage/plugin-microsoft-calendar": "0.1.7", - "@backstage/plugin-newrelic": "0.3.40", - "@backstage/plugin-newrelic-dashboard": "0.2.17", - "@backstage/plugin-nomad": "0.1.5", - "@backstage/plugin-nomad-backend": "0.1.5", - "@backstage/plugin-octopus-deploy": "0.2.6", - "@backstage/plugin-opencost": "0.2.0", - "@backstage/plugin-org": "0.6.14", - "@backstage/plugin-org-react": "0.1.13", - "@backstage/plugin-pagerduty": "0.6.5", - "@backstage/plugin-periskop": "0.1.22", - "@backstage/plugin-periskop-backend": "0.2.0", - "@backstage/plugin-permission-backend": "0.5.26", - "@backstage/plugin-permission-backend-module-allow-all-policy": "0.1.0", - "@backstage/plugin-permission-common": "0.7.8", - "@backstage/plugin-permission-node": "0.7.14", - "@backstage/plugin-permission-react": "0.4.15", - "@backstage/plugin-playlist": "0.1.16", - "@backstage/plugin-playlist-backend": "0.3.7", - "@backstage/plugin-playlist-common": "0.1.10", - "@backstage/plugin-proxy-backend": "0.4.0", - "@backstage/plugin-puppetdb": "0.1.7", - "@backstage/plugin-rollbar": "0.4.24", - "@backstage/plugin-rollbar-backend": "0.1.48", - "@backstage/plugin-scaffolder": "1.15.0", - "@backstage/plugin-scaffolder-backend": "1.17.0", - "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.2.4", - "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.2.27", - "@backstage/plugin-scaffolder-backend-module-gitlab": "0.2.6", - "@backstage/plugin-scaffolder-backend-module-rails": "0.4.20", - "@backstage/plugin-scaffolder-backend-module-sentry": "0.1.11", - "@backstage/plugin-scaffolder-backend-module-yeoman": "0.2.24", - "@backstage/plugin-scaffolder-common": "1.4.1", - "@backstage/plugin-scaffolder-node": "0.2.3", - "@backstage/plugin-scaffolder-react": "1.5.5", - "@backstage/plugin-search": "1.4.0", - "@backstage/plugin-search-backend": "1.4.3", - "@backstage/plugin-search-backend-module-catalog": "0.1.7", - "@backstage/plugin-search-backend-module-elasticsearch": "1.3.6", - "@backstage/plugin-search-backend-module-explore": "0.1.7", - "@backstage/plugin-search-backend-module-pg": "0.5.12", - "@backstage/plugin-search-backend-module-techdocs": "0.1.7", - "@backstage/plugin-search-backend-node": "1.2.7", - "@backstage/plugin-search-common": "1.2.6", - "@backstage/plugin-search-react": "1.7.0", - "@backstage/plugin-sentry": "0.5.9", - "@backstage/plugin-shortcuts": "0.3.14", - "@backstage/plugin-sonarqube": "0.7.5", - "@backstage/plugin-sonarqube-backend": "0.2.5", - "@backstage/plugin-sonarqube-react": "0.1.8", - "@backstage/plugin-splunk-on-call": "0.4.13", - "@backstage/plugin-stack-overflow": "0.1.20", - "@backstage/plugin-stack-overflow-backend": "0.2.7", - "@backstage/plugin-stackstorm": "0.1.6", - "@backstage/plugin-tech-insights": "0.3.16", - "@backstage/plugin-tech-insights-backend": "0.5.17", - "@backstage/plugin-tech-insights-backend-module-jsonfc": "0.1.35", + "@backstage/plugin-microsoft-calendar": "0.1.8", + "@backstage/plugin-newrelic": "0.3.41", + "@backstage/plugin-newrelic-dashboard": "0.3.0", + "@backstage/plugin-nomad": "0.1.6", + "@backstage/plugin-nomad-backend": "0.1.8", + "@backstage/plugin-octopus-deploy": "0.2.7", + "@backstage/plugin-opencost": "0.2.1", + "@backstage/plugin-org": "0.6.15", + "@backstage/plugin-org-react": "0.1.14", + "@backstage/plugin-pagerduty": "0.6.6", + "@backstage/plugin-periskop": "0.1.23", + "@backstage/plugin-periskop-backend": "0.2.3", + "@backstage/plugin-permission-backend": "0.5.29", + "@backstage/plugin-permission-backend-module-allow-all-policy": "0.1.3", + "@backstage/plugin-permission-common": "0.7.9", + "@backstage/plugin-permission-node": "0.7.17", + "@backstage/plugin-permission-react": "0.4.16", + "@backstage/plugin-playlist": "0.1.17", + "@backstage/plugin-playlist-backend": "0.3.10", + "@backstage/plugin-playlist-common": "0.1.11", + "@backstage/plugin-proxy-backend": "0.4.3", + "@backstage/plugin-puppetdb": "0.1.8", + "@backstage/plugin-rollbar": "0.4.25", + "@backstage/plugin-rollbar-backend": "0.1.51", + "@backstage/plugin-scaffolder": "1.15.1", + "@backstage/plugin-scaffolder-backend": "1.18.0", + "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.2.7", + "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.2.30", + "@backstage/plugin-scaffolder-backend-module-gitlab": "0.2.9", + "@backstage/plugin-scaffolder-backend-module-rails": "0.4.23", + "@backstage/plugin-scaffolder-backend-module-sentry": "0.1.14", + "@backstage/plugin-scaffolder-backend-module-yeoman": "0.2.27", + "@backstage/plugin-scaffolder-common": "1.4.2", + "@backstage/plugin-scaffolder-node": "0.2.6", + "@backstage/plugin-scaffolder-react": "1.5.6", + "@backstage/plugin-search": "1.4.1", + "@backstage/plugin-search-backend": "1.4.6", + "@backstage/plugin-search-backend-module-catalog": "0.1.10", + "@backstage/plugin-search-backend-module-elasticsearch": "1.3.9", + "@backstage/plugin-search-backend-module-explore": "0.1.10", + "@backstage/plugin-search-backend-module-pg": "0.5.15", + "@backstage/plugin-search-backend-module-techdocs": "0.1.10", + "@backstage/plugin-search-backend-node": "1.2.10", + "@backstage/plugin-search-common": "1.2.7", + "@backstage/plugin-search-react": "1.7.1", + "@backstage/plugin-sentry": "0.5.10", + "@backstage/plugin-shortcuts": "0.3.15", + "@backstage/plugin-sonarqube": "0.7.6", + "@backstage/plugin-sonarqube-backend": "0.2.8", + "@backstage/plugin-sonarqube-react": "0.1.9", + "@backstage/plugin-splunk-on-call": "0.4.14", + "@backstage/plugin-stack-overflow": "0.1.21", + "@backstage/plugin-stack-overflow-backend": "0.2.10", + "@backstage/plugin-stackstorm": "0.1.7", + "@backstage/plugin-tech-insights": "0.3.17", + "@backstage/plugin-tech-insights-backend": "0.5.20", + "@backstage/plugin-tech-insights-backend-module-jsonfc": "0.1.38", "@backstage/plugin-tech-insights-common": "0.2.12", - "@backstage/plugin-tech-insights-node": "0.4.9", - "@backstage/plugin-tech-radar": "0.6.8", - "@backstage/plugin-techdocs": "1.7.0", - "@backstage/plugin-techdocs-addons-test-utils": "1.0.21", - "@backstage/plugin-techdocs-backend": "1.7.0", - "@backstage/plugin-techdocs-module-addons-contrib": "1.1.0", - "@backstage/plugin-techdocs-node": "1.8.0", - "@backstage/plugin-techdocs-react": "1.1.11", - "@backstage/plugin-todo": "0.2.27", - "@backstage/plugin-todo-backend": "0.3.1", - "@backstage/plugin-user-settings": "0.7.10", - "@backstage/plugin-user-settings-backend": "0.2.1", - "@backstage/plugin-vault": "0.1.19", - "@backstage/plugin-vault-backend": "0.3.8", - "@backstage/plugin-xcmetrics": "0.2.43", - "@backstage/e2e-test-utils": "0.0.0", - "@backstage/plugin-kubernetes-react": "0.0.0" + "@backstage/plugin-tech-insights-node": "0.4.12", + "@backstage/plugin-tech-radar": "0.6.9", + "@backstage/plugin-techdocs": "1.8.0", + "@backstage/plugin-techdocs-addons-test-utils": "1.0.22", + "@backstage/plugin-techdocs-backend": "1.8.0", + "@backstage/plugin-techdocs-module-addons-contrib": "1.1.1", + "@backstage/plugin-techdocs-node": "1.9.0", + "@backstage/plugin-techdocs-react": "1.1.12", + "@backstage/plugin-todo": "0.2.28", + "@backstage/plugin-todo-backend": "0.3.4", + "@backstage/plugin-user-settings": "0.7.11", + "@backstage/plugin-user-settings-backend": "0.2.4", + "@backstage/plugin-vault": "0.1.20", + "@backstage/plugin-vault-backend": "0.3.11", + "@backstage/plugin-xcmetrics": "0.2.44" }, - "changesets": [ - "angry-badgers-beg", - "big-spies-beam", - "breezy-dryers-thank", - "calm-scissors-rescue", - "chatty-papayas-care", - "clean-forks-love", - "cold-bees-jam", - "cold-seas-repeat", - "dull-bugs-build", - "dull-dolls-explode", - "dull-experts-kiss", - "dull-laws-camp", - "eight-melons-cough", - "eighty-actors-type", - "fair-frogs-enjoy", - "four-jars-protect", - "four-onions-clap", - "four-pans-sin", - "fresh-kangaroos-tap", - "gentle-elephants-fold", - "gentle-spies-deny", - "happy-books-smoke", - "heavy-forks-tie", - "itchy-bobcats-fly", - "itchy-monkeys-reply", - "itchy-rabbits-exist", - "large-comics-knock", - "late-papayas-push", - "lazy-doors-wink", - "lemon-cups-wait", - "lemon-masks-greet", - "lovely-coins-occur", - "lovely-fans-sniff", - "many-swans-eat", - "mean-dancers-burn", - "moody-lobsters-rescue", - "nervous-hounds-sleep", - "nice-clocks-smash", - "nice-dancers-explain", - "nine-garlics-attend", - "olive-cars-rescue", - "perfect-pumas-protect", - "plenty-llamas-double", - "polite-cooks-perform", - "polite-donuts-fail", - "polite-trainers-grin", - "popular-dots-design", - "pretty-apes-sneeze", - "pretty-steaks-serve", - "purple-chefs-wait", - "purple-forks-fetch", - "quick-weeks-explode", - "red-bees-try", - "renovate-a1c52e8", - "shy-clouds-reflect", - "shy-seas-sip", - "silent-years-bake", - "silly-swans-invent", - "small-pugs-build", - "spicy-chairs-film", - "spotty-badgers-wash", - "strong-falcons-tickle", - "stupid-drinks-trade", - "stupid-eagles-shave", - "tasty-avocados-hope", - "tasty-doors-switch", - "ten-seals-wait", - "thirty-coins-sneeze", - "tiny-garlics-cheer", - "twelve-clouds-design", - "violet-beers-cross", - "warm-drinks-argue", - "wet-olives-wave", - "wet-timers-chew", - "wicked-rings-flash", - "wild-jobs-greet", - "yellow-numbers-own", - "yellow-rings-invent" - ] + "changesets": [] } diff --git a/.changeset/pretty-apes-sneeze.md b/.changeset/pretty-apes-sneeze.md deleted file mode 100644 index a1008dc951..0000000000 --- a/.changeset/pretty-apes-sneeze.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-user-settings': patch ---- - -Fixed a bug where the theme icons would not be colored according to their active state. diff --git a/.changeset/pretty-steaks-serve.md b/.changeset/pretty-steaks-serve.md deleted file mode 100644 index 8ec78e0aea..0000000000 --- a/.changeset/pretty-steaks-serve.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Added a template for creating `node-library` packages with `yarn new`. diff --git a/.changeset/pretty-swans-worry.md b/.changeset/pretty-swans-worry.md new file mode 100644 index 0000000000..621ae98fe5 --- /dev/null +++ b/.changeset/pretty-swans-worry.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Fixed the type declaration of `DependencyGraphProps`, the `defs` prop now expects `JSX.Element`s. diff --git a/.changeset/purple-chefs-wait.md b/.changeset/purple-chefs-wait.md deleted file mode 100644 index 9a8b1f9799..0000000000 --- a/.changeset/purple-chefs-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch ---- - -Adding `requestInterceptor` option to `api-docs` and pass it to SwaggerUI. This will enable to configure a proxy or headers to be sent to all the request made through the `Try it out` button on SwaggerUI. diff --git a/.changeset/purple-forks-fetch.md b/.changeset/purple-forks-fetch.md deleted file mode 100644 index 022fc32e71..0000000000 --- a/.changeset/purple-forks-fetch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Register default api implementations when creating declarative integrated apps. diff --git a/.changeset/quick-pumpkins-shave.md b/.changeset/quick-pumpkins-shave.md new file mode 100644 index 0000000000..cbb4c48dce --- /dev/null +++ b/.changeset/quick-pumpkins-shave.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-home': patch +--- + +Added experimental support for declarative integration via the `/alpha` subpath. diff --git a/.changeset/quick-weeks-explode.md b/.changeset/quick-weeks-explode.md deleted file mode 100644 index fcc88263ec..0000000000 --- a/.changeset/quick-weeks-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Remove third type parameter used for `MockInstance`, in order to be compatible with older versions of `@types/jest`. diff --git a/.changeset/red-bees-try.md b/.changeset/red-bees-try.md deleted file mode 100644 index de7eacfe14..0000000000 --- a/.changeset/red-bees-try.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Fixed an issue where the new backend start command would not gracefully shut down the backend process on Windows. diff --git a/.changeset/red-geese-clean.md b/.changeset/red-geese-clean.md deleted file mode 100644 index b4fc9c0808..0000000000 --- a/.changeset/red-geese-clean.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/backend-openapi-utils': patch ---- - -Adds new public utility types for common OpenAPI values, like request and response shapes and parameters available on an endpoint. - -**deprecated** `internal` namespace -The internal namespace will continue to be exported but now uses OpenAPI format for path parameters. You should use the new utility types. diff --git a/.changeset/renovate-a1c52e8.md b/.changeset/renovate-a1c52e8.md deleted file mode 100644 index c11c866b68..0000000000 --- a/.changeset/renovate-a1c52e8.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-cost-insights': patch ---- - -Updated dependency `@types/pluralize` to `^0.0.31`. diff --git a/.changeset/rotten-rings-confess.md b/.changeset/rotten-rings-confess.md deleted file mode 100644 index 8948a90347..0000000000 --- a/.changeset/rotten-rings-confess.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/plugin-newrelic-dashboard': minor ---- - -Changes in `newrelic-dashboard` plugin: - -- Make DashboardSnapshotList component public -- Settle discrepancies in the exported API -- Deprecate DashboardSnapshotComponent diff --git a/.changeset/rude-tomatoes-itch.md b/.changeset/rude-tomatoes-itch.md new file mode 100644 index 0000000000..1071f65756 --- /dev/null +++ b/.changeset/rude-tomatoes-itch.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Installed features are now deduplicated both by reference and ID when available. Features passed to `createApp` now override both discovered and loaded features. diff --git a/.changeset/serious-penguins-tease.md b/.changeset/serious-penguins-tease.md deleted file mode 100644 index aa6aba7208..0000000000 --- a/.changeset/serious-penguins-tease.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-test-utils': patch ---- - -Updated to import `HostDiscovery` from `@backstage/backend-app-api`. diff --git a/.changeset/shaggy-beers-collect.md b/.changeset/shaggy-beers-collect.md new file mode 100644 index 0000000000..471368d6f2 --- /dev/null +++ b/.changeset/shaggy-beers-collect.md @@ -0,0 +1,6 @@ +--- +'@backstage/dev-utils': patch +'@backstage/plugin-techdocs': patch +--- + +Added support for React 18. The new `createRoot` API from `react-dom/client` will now be used if present. diff --git a/.changeset/sharp-falcons-clean.md b/.changeset/sharp-falcons-clean.md new file mode 100644 index 0000000000..bc247be451 --- /dev/null +++ b/.changeset/sharp-falcons-clean.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': patch +--- + +Register default implementation for the `Translation API` on the new `createApp`. diff --git a/.changeset/shiny-geese-watch.md b/.changeset/shiny-geese-watch.md new file mode 100644 index 0000000000..5394a0776d --- /dev/null +++ b/.changeset/shiny-geese-watch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-microsoft-provider': patch +--- + +Removed `prompt=consent` from start method to fix #20641 diff --git a/.changeset/short-terms-check.md b/.changeset/short-terms-check.md deleted file mode 100644 index 69d85fcb9c..0000000000 --- a/.changeset/short-terms-check.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -Removed `mock-fs` dev dependency. diff --git a/.changeset/shy-clouds-reflect.md b/.changeset/shy-clouds-reflect.md deleted file mode 100644 index 2861bad9f3..0000000000 --- a/.changeset/shy-clouds-reflect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/config-loader': patch ---- - -The `FileConfigSource` will now retry file reading after a short delay if it reads an empty file. This is to avoid flakiness during watch mode where change events can trigger before the file content has been written. diff --git a/.changeset/shy-seas-sip.md b/.changeset/shy-seas-sip.md deleted file mode 100644 index dfbc4ff0e0..0000000000 --- a/.changeset/shy-seas-sip.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend-module-gitlab': patch ---- - -Make sure the archived projects are skipped with the Gitlab API diff --git a/.changeset/silent-years-bake.md b/.changeset/silent-years-bake.md deleted file mode 100644 index 4f50c37c31..0000000000 --- a/.changeset/silent-years-bake.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/plugin-scaffolder-backend-module-rails': patch -'@techdocs/cli': patch -'@backstage/cli': patch -'@backstage/cli-common': patch -'@backstage/create-app': patch -'@backstage/codemods': patch -'@backstage/repo-tools': patch ---- - -Bumped dev dependencies `@types/node` and `mock-fs`. diff --git a/.changeset/silly-swans-invent.md b/.changeset/silly-swans-invent.md deleted file mode 100644 index 68b094aba7..0000000000 --- a/.changeset/silly-swans-invent.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-plugin-api': patch ---- - -Added `createThemeExtension` and `coreExtensionData.theme`. diff --git a/.changeset/six-weeks-raise.md b/.changeset/six-weeks-raise.md deleted file mode 100644 index 319555afa4..0000000000 --- a/.changeset/six-weeks-raise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-app-api': patch ---- - -Moved `HostDiscovery` from `@backstage/backend-common`. diff --git a/.changeset/slow-dodos-remember.md b/.changeset/slow-dodos-remember.md deleted file mode 100644 index fcc49e3f45..0000000000 --- a/.changeset/slow-dodos-remember.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': patch -'@backstage/plugin-kubernetes-cluster': patch -'@backstage/plugin-kubernetes-react': patch -'@backstage/plugin-kubernetes': patch ---- - -Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage diff --git a/.changeset/small-pugs-build.md b/.changeset/small-pugs-build.md deleted file mode 100644 index 68e11cd967..0000000000 --- a/.changeset/small-pugs-build.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Bump Docker base images to `node:18-bookworm-slim` to fix node compatibility issues raised during image build. - -You can apply these change to your own `Dockerfile` by replacing `node:16-bullseye-slim` with `node:18-bookworm-slim` diff --git a/.changeset/smooth-rings-mate.md b/.changeset/smooth-rings-mate.md deleted file mode 100644 index f46ef2cb5c..0000000000 --- a/.changeset/smooth-rings-mate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/theme': patch ---- - -Added support for string `fontSize` values (e.g. `"2.5rem"`) in themes in addition to numbers. Also added an optional `fontFamily` prop for header typography variants to allow further customization. diff --git a/.changeset/spicy-chairs-film.md b/.changeset/spicy-chairs-film.md deleted file mode 100644 index 475d786330..0000000000 --- a/.changeset/spicy-chairs-film.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-kubernetes-common': minor -'@backstage/plugin-kubernetes-react': minor -'@backstage/plugin-kubernetes': minor ---- - -Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet diff --git a/.changeset/spotty-badgers-wash.md b/.changeset/spotty-badgers-wash.md deleted file mode 100644 index 1ce9c66aee..0000000000 --- a/.changeset/spotty-badgers-wash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog-backend': minor ---- - -Instrumenting some missing metrics with `OpenTelemetry` diff --git a/.changeset/stale-rice-count.md b/.changeset/stale-rice-count.md new file mode 100644 index 0000000000..3d2caf168d --- /dev/null +++ b/.changeset/stale-rice-count.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-plugin-api': patch +--- + +Deprecated several types related to the routing system that are scheduled to be removed, as well as several fields on the route ref types themselves. diff --git a/.changeset/stale-stingrays-explode.md b/.changeset/stale-stingrays-explode.md deleted file mode 100644 index b8b66b8398..0000000000 --- a/.changeset/stale-stingrays-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-auth-node': patch ---- - -Fixed cookie persisted scope not returned in OAuth refresh handler response. diff --git a/.changeset/strong-falcons-tickle.md b/.changeset/strong-falcons-tickle.md deleted file mode 100644 index d6fa0eb565..0000000000 --- a/.changeset/strong-falcons-tickle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-adr': patch ---- - -Create an experimental `AdrSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. diff --git a/.changeset/stupid-drinks-trade.md b/.changeset/stupid-drinks-trade.md deleted file mode 100644 index a9eeacec8a..0000000000 --- a/.changeset/stupid-drinks-trade.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-techdocs': patch ---- - -Add kind column by default to TechDocsTable diff --git a/.changeset/stupid-eagles-shave.md b/.changeset/stupid-eagles-shave.md deleted file mode 100644 index 9bd88290ee..0000000000 --- a/.changeset/stupid-eagles-shave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-code-coverage': patch ---- - -Updated layout to improve contrasts and consistency with other plugins diff --git a/.changeset/sweet-buckets-fry.md b/.changeset/sweet-buckets-fry.md new file mode 100644 index 0000000000..8f17617645 --- /dev/null +++ b/.changeset/sweet-buckets-fry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +The `spec.type` field in entities will now always be rendered as a string. diff --git a/.changeset/tasty-avocados-hope.md b/.changeset/tasty-avocados-hope.md deleted file mode 100644 index 0772b55683..0000000000 --- a/.changeset/tasty-avocados-hope.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Migrate catalog api to declarative integration system, it is exported from `/alpha` subpath. diff --git a/.changeset/tasty-doors-switch.md b/.changeset/tasty-doors-switch.md deleted file mode 100644 index e35bf9cfa4..0000000000 --- a/.changeset/tasty-doors-switch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/cli': patch ---- - -Explicitly set `exports: 'named'` for CJS builds, ensuring that they have e.g. `exports["default"] = catalogPlugin;` diff --git a/.changeset/ten-seals-wait.md b/.changeset/ten-seals-wait.md deleted file mode 100644 index 780422449c..0000000000 --- a/.changeset/ten-seals-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-cost-insights': patch ---- - -The experimental plugin configuration has been removed. The trend line can now instead be hidden by setting `costInsights.hideTrendLine` to `true` in the configuration. diff --git a/.changeset/tender-maps-type.md b/.changeset/tender-maps-type.md new file mode 100644 index 0000000000..11aa814a17 --- /dev/null +++ b/.changeset/tender-maps-type.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-plugin-api': minor +--- + +Introduced `AnyRouteRefParams` as a replacement for `AnyParams`, which is now deprecated. diff --git a/.changeset/thick-dolphins-boil.md b/.changeset/thick-dolphins-boil.md new file mode 100644 index 0000000000..dd562e620c --- /dev/null +++ b/.changeset/thick-dolphins-boil.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +The `app.title` configuration is now properly required to be a string. diff --git a/.changeset/thirty-coins-sneeze.md b/.changeset/thirty-coins-sneeze.md deleted file mode 100644 index 58a93065b8..0000000000 --- a/.changeset/thirty-coins-sneeze.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/e2e-test-utils': minor ---- - -Initial release. diff --git a/.changeset/three-moles-mix.md b/.changeset/three-moles-mix.md new file mode 100644 index 0000000000..d1e48194a1 --- /dev/null +++ b/.changeset/three-moles-mix.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Fixed incorrect plugin ID in `/alpha` export. diff --git a/.changeset/tiny-garlics-cheer.md b/.changeset/tiny-garlics-cheer.md deleted file mode 100644 index 992ed7f007..0000000000 --- a/.changeset/tiny-garlics-cheer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@techdocs/cli': patch ---- - -Restructured tests. diff --git a/.changeset/tricky-cups-hammer.md b/.changeset/tricky-cups-hammer.md new file mode 100644 index 0000000000..4e1b6fe9ce --- /dev/null +++ b/.changeset/tricky-cups-hammer.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-plugin-api': patch +--- + +Added a new `/alpha` export `convertLegacyRouteRef`, which is a temporary utility to allow existing route refs to be used with the new experimental packages. diff --git a/.changeset/twelve-clouds-design.md b/.changeset/twelve-clouds-design.md deleted file mode 100644 index d71d6caec0..0000000000 --- a/.changeset/twelve-clouds-design.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -The E2E test setup based on Cypress has been replaced with one based on [Playwright](https://playwright.dev/). Migrating existing apps is not required as this is a standalone setup, only do so if you also want to switch from Cypress to Playwright. - -The scripts to run the E2E tests have been removed from `packages/app/package.json`, as they are now instead run from the root. Instead, a new script has been added to the root `package.json`, `yarn test:e2e`, which runs the E2E tests in development mode, unless `CI` is set in the environment. - -The Playwright setup uses utilities from the new `@backstage/e2e-test-utils` package to find and include all packages in the monorepo that have an `e2e-tests` folder. diff --git a/.changeset/twelve-days-walk.md b/.changeset/twelve-days-walk.md deleted file mode 100644 index 0b2d261c1a..0000000000 --- a/.changeset/twelve-days-walk.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-app-api': minor ---- - -URL encode some well known unsafe characters in `RouteResolver` (and therefore `useRouteRef`) diff --git a/.changeset/twenty-bags-sin.md b/.changeset/twenty-bags-sin.md deleted file mode 100644 index 797fd5bfef..0000000000 --- a/.changeset/twenty-bags-sin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-tech-insights': patch ---- - -Export `ScorecardInfo` and `ScorecardsList` components to be able to use manually queried check results directly. diff --git a/.changeset/two-dingos-dream.md b/.changeset/two-dingos-dream.md deleted file mode 100644 index 9ebefacc69..0000000000 --- a/.changeset/two-dingos-dream.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-kubernetes-backend': patch -'@backstage/plugin-kubernetes-react': patch -'@backstage/plugin-kubernetes-common': patch ---- - -The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies diff --git a/.changeset/unlucky-experts-breathe.md b/.changeset/unlucky-experts-breathe.md deleted file mode 100644 index 018b1826d2..0000000000 --- a/.changeset/unlucky-experts-breathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Added support for the existing routing system. diff --git a/.changeset/violet-beers-cross.md b/.changeset/violet-beers-cross.md deleted file mode 100644 index bdbb9da64e..0000000000 --- a/.changeset/violet-beers-cross.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Change overlay header colors in the mobile menu to use navigation color from the theme diff --git a/.changeset/violet-lamps-appear.md b/.changeset/violet-lamps-appear.md new file mode 100644 index 0000000000..23536fb728 --- /dev/null +++ b/.changeset/violet-lamps-appear.md @@ -0,0 +1,12 @@ +--- +'@backstage/plugin-scaffolder': minor +'@backstage/plugin-scaffolder-react': minor +--- + +Release design improvements for the `Scaffolder` plugin and support v5 of `@rjsf/*` libraries. + +This change should be non-breaking. If you're seeing typescript issues after migrating please [open an issue](https://github.com/backstage/backstage/issues/new/choose) + +The `next` versions like `createNextFieldExtension` and `NextScaffolderPage` have been promoted to the public interface under `createScaffolderFieldExtension` and `ScaffolderPage`, so any older imports which are no longer found will need updating from `@backstage/plugin-scaffolder/alpha` or `@backstage/plugin-scaffolder-react/alpha` will need to be imported from `@backstage/plugin-scaffolder` and `@backstage/plugin-scaffolder-react` respectively. + +The legacy versions are now available in `/alpha` under `createLegacyFieldExtension` and `LegacyScaffolderPage` if you're running into issues, but be aware that these will be removed in a next mainline release. diff --git a/.changeset/warm-drinks-argue.md b/.changeset/warm-drinks-argue.md deleted file mode 100644 index 5bd4fa63f1..0000000000 --- a/.changeset/warm-drinks-argue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-explore': patch ---- - -Create an experimental `ExploreSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. diff --git a/.changeset/wet-cows-brake.md b/.changeset/wet-cows-brake.md new file mode 100644 index 0000000000..9e694d8452 --- /dev/null +++ b/.changeset/wet-cows-brake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-react': patch +--- + +The filter options passed to `SearchResultGroupLayout` are now always explicitly rendered as strings by default. diff --git a/.changeset/wet-olives-wave.md b/.changeset/wet-olives-wave.md deleted file mode 100644 index 5b35e0ad90..0000000000 --- a/.changeset/wet-olives-wave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch ---- - -added aria-label on api definition button for better a11y. diff --git a/.changeset/wet-timers-chew.md b/.changeset/wet-timers-chew.md deleted file mode 100644 index 3be6368331..0000000000 --- a/.changeset/wet-timers-chew.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/backend-common': patch ---- - -The `useHotCleanup` and `useHotMemoize` helpers are now deprecated, since hot module reloads for backend are being phased out. diff --git a/.changeset/wicked-rings-flash.md b/.changeset/wicked-rings-flash.md deleted file mode 100644 index b872c0c71f..0000000000 --- a/.changeset/wicked-rings-flash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-search-react': patch ---- - -Create `createSearchResultListItem` alpha version that only supports declarative integration. diff --git a/.changeset/wild-geese-occur.md b/.changeset/wild-geese-occur.md new file mode 100644 index 0000000000..b97620e7f5 --- /dev/null +++ b/.changeset/wild-geese-occur.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Minor internal code cleanup. diff --git a/.changeset/wild-jobs-greet.md b/.changeset/wild-jobs-greet.md deleted file mode 100644 index fdbe6d56ac..0000000000 --- a/.changeset/wild-jobs-greet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/frontend-app-api': patch ---- - -Prevents root extension override and duplicated plugin extensions. diff --git a/.changeset/wild-queens-grab.md b/.changeset/wild-queens-grab.md deleted file mode 100644 index 287dc0482e..0000000000 --- a/.changeset/wild-queens-grab.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-playlist': patch ---- - -Updated Playlist read me with additional screenshots diff --git a/.changeset/yellow-numbers-own.md b/.changeset/yellow-numbers-own.md deleted file mode 100644 index 3a6e8937eb..0000000000 --- a/.changeset/yellow-numbers-own.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -Added missing `.eslintignore` file - -To apply this change to an existing app, create a new `.eslintignore` file at the root of your project with the following content: - -```diff -+ playwright.config.ts -``` diff --git a/.changeset/yellow-rings-invent.md b/.changeset/yellow-rings-invent.md deleted file mode 100644 index f0335ff492..0000000000 --- a/.changeset/yellow-rings-invent.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -MissingAnnotationEmptyState component can now dynamically generate a YAML example based off the current entity being used. diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cb8101e1b1..92f2d57885 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -13,6 +13,7 @@ yarn.lock @backstage/maintainers @backst /docs/features/techdocs @backstage/techdocs-maintainers /docs/plugins/integrating-search-into-plugins.md @backstage/discoverability-maintainers /packages/cli/src/commands/onboard @backstage/sharks +/packages/backend-openapi-utils @backstage/maintainers @backstage/reviewers @backstage/openapi-tooling-maintainers /packages/techdocs-cli @backstage/techdocs-maintainers /packages/techdocs-cli-embedded-app @backstage/techdocs-maintainers /plugins/adr @backstage/maintainers @backstage/reviewers @kuangp @@ -31,6 +32,7 @@ yarn.lock @backstage/maintainers @backst /plugins/catalog-backend-module-msgraph @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @pjungermann /plugins/catalog-backend-module-puppetdb @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers /plugins/catalog-graph @backstage/maintainers @backstage/reviewers @backstage/catalog-maintainers @backstage/sda-se-reviewers +/plugins/cicd-statistics @backstage/sharks /plugins/circleci @backstage/maintainers @backstage/reviewers @adamdmharvey /plugins/code-coverage @backstage/maintainers @backstage/reviewers @alde /plugins/code-coverage-backend @backstage/maintainers @backstage/reviewers @alde @@ -69,6 +71,8 @@ yarn.lock @backstage/maintainers @backst /plugins/playlist-* @backstage/maintainers @backstage/reviewers @kuangp /plugins/rollbar @backstage/maintainers @backstage/reviewers @andrewthauer /plugins/rollbar-backend @backstage/maintainers @backstage/reviewers @andrewthauer +/plugins/scaffolder @backstage/maintainers @backstage/reviewers @backstage/scaffolder-maintainers +/plugins/scaffolder-* @backstage/maintainers @backstage/reviewers @backstage/scaffolder-maintainers /plugins/search @backstage/discoverability-maintainers /plugins/search-* @backstage/discoverability-maintainers /plugins/sonarqube @backstage/maintainers @backstage/reviewers @backstage/sda-se-reviewers diff --git a/.github/vale/Vocab/Backstage/accept.txt b/.github/vale/Vocab/Backstage/accept.txt index aadbaa3985..1a028d1387 100644 --- a/.github/vale/Vocab/Backstage/accept.txt +++ b/.github/vale/Vocab/Backstage/accept.txt @@ -25,6 +25,7 @@ backend's backported backporting BEPs +bigint Bigtable Billett bitbucket @@ -453,4 +454,5 @@ zsh Pulumi Lightsail PR -rebasing \ No newline at end of file +rebasing +lookbehind diff --git a/.github/workflows/automate_area-labels.yml b/.github/workflows/automate_area-labels.yml index 3d616506e1..dfb60c9243 100644 --- a/.github/workflows/automate_area-labels.yml +++ b/.github/workflows/automate_area-labels.yml @@ -2,11 +2,22 @@ name: Automate area labels on: - pull_request_target +permissions: + contents: read + jobs: triage: + permissions: + contents: read # for actions/labeler to determine modified files + pull-requests: write # for actions/labeler to add labels to PRs runs-on: ubuntu-latest steps: - - uses: actions/labeler@v4 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/labeler@v4.3.0 with: repo-token: '${{ secrets.GITHUB_TOKEN }}' sync-labels: true diff --git a/.github/workflows/automate_changeset_feedback.yml b/.github/workflows/automate_changeset_feedback.yml index 9cadf12b4f..483d59dc8c 100644 --- a/.github/workflows/automate_changeset_feedback.yml +++ b/.github/workflows/automate_changeset_feedback.yml @@ -22,7 +22,12 @@ jobs: if: github.repository == 'backstage/backstage' && github.event.pull_request.user.login != 'backstage-service' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 with: # Fetch the commit that's merged into the base rather than the target ref # This will let us diff only the contents of the PR, without fetching more history diff --git a/.github/workflows/automate_merge_message.yml b/.github/workflows/automate_merge_message.yml index 9fed796aa5..4cbf6c69a2 100644 --- a/.github/workflows/automate_merge_message.yml +++ b/.github/workflows/automate_merge_message.yml @@ -23,7 +23,12 @@ jobs: if: github.repository == 'backstage/backstage' && github.event.pull_request.merged == true runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 with: ref: '${{ github.event.pull_request.merge_commit_sha }}' @@ -39,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@v6 + uses: actions/github-script@v6.4.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 452ecc48d6..40ebdf8a3e 100644 --- a/.github/workflows/automate_stale.yml +++ b/.github/workflows/automate_stale.yml @@ -4,11 +4,22 @@ on: schedule: - cron: '*/10 * * * *' # run every 10 minutes as it also removes labels. +permissions: + contents: read + jobs: stale: + permissions: + issues: write # for actions/stale to close stale issues + pull-requests: write # for actions/stale to close stale PRs runs-on: ubuntu-latest steps: - - uses: actions/stale@v7 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/stale@v7.0.0 id: stale with: stale-issue-message: > diff --git a/.github/workflows/ci-noop.yml b/.github/workflows/ci-noop.yml index 16bf11dd1a..7234e945e3 100644 --- a/.github/workflows/ci-noop.yml +++ b/.github/workflows/ci-noop.yml @@ -7,6 +7,9 @@ on: paths: - 'microsite/**' +permissions: + contents: read + jobs: # The verify jobs runs all the verification that doesn't require a # diff towards master, since it takes some time to fetch that. @@ -19,6 +22,11 @@ jobs: name: Verify ${{ matrix.node-version }} steps: + # - name: Harden Runner + # uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + # with: + # egress-policy: audit + - run: echo NOOP test-noop: @@ -30,4 +38,9 @@ jobs: name: Test ${{ matrix.node-version }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dbf2dc6705..81ea6f96d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [18.x] + node-version: [18.x, 20.x] env: CI: true @@ -26,10 +26,15 @@ jobs: name: Install ${{ matrix.node-version }} steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -49,7 +54,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [18.x] + node-version: [18.x, 20.x] env: CI: true @@ -57,10 +62,15 @@ jobs: name: Verify ${{ matrix.node-version }} steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -139,7 +149,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [18.x] + node-version: [18.x, 20.x] name: Test ${{ matrix.node-version }} services: @@ -186,12 +196,12 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v3.6.0 - name: fetch branch master run: git fetch origin master - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index ef8906818f..2874be512c 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -8,6 +8,11 @@ jobs: cron: runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - uses: backstage/actions/cron@v0.6.4 with: app-id: ${{ secrets.BACKSTAGE_GOALIE_APPLICATION_ID }} diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index 231b81598e..30e7badcd0 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -13,14 +13,19 @@ jobs: node-version: [18.x] steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v3.6.0 with: path: backstage ref: v${{ github.event.client_payload.version }} - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -40,17 +45,17 @@ jobs: working-directory: ./example-app - name: Login to GitHub Container Registry - uses: docker/login-action@v2 + uses: docker/login-action@v2.2.0 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v2.10.0 - name: Build and push - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v4.2.1 with: context: './example-app' file: ./example-app/packages/backend/Dockerfile diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index dddb2de4af..f614db31ca 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -4,8 +4,13 @@ on: branches: - master +permissions: + contents: read + jobs: deploy-microsite-and-storybook: + permissions: + contents: write # for JamesIves/github-pages-deploy-action to push changes in repo runs-on: ubuntu-latest env: @@ -18,10 +23,15 @@ jobs: cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 - name: use node.js 18.x - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: 18.x registry-url: https://registry.npmjs.org/ # Needed for auth @@ -56,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@v4.4.3 + uses: JamesIves/github-pages-deploy-action@a1ea191d508feb8485aceba848389d49f80ca2dc # v4.4.3 with: branch: gh-pages folder: microsite/build diff --git a/.github/workflows/deploy_nightly.yml b/.github/workflows/deploy_nightly.yml index e48a6b97ab..d5fe9f5a64 100644 --- a/.github/workflows/deploy_nightly.yml +++ b/.github/workflows/deploy_nightly.yml @@ -14,15 +14,20 @@ jobs: NODE_OPTIONS: --max-old-space-size=4096 steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: use node.js 18.x - uses: actions/setup-node@v3 + uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3.8.1 with: node-version: 18.x registry-url: https://registry.npmjs.org/ # Needed for auth - name: yarn install - uses: backstage/actions/yarn-install@v0.6.4 + uses: backstage/actions/yarn-install@497722d45fb5a35c14c721f63ed74e6ad5f629dd # v0.6.4 with: cache-prefix: ${{ runner.os }}-v18.x @@ -59,7 +64,7 @@ jobs: - name: Discord notification if: ${{ failure() }} - uses: Ilshidur/action-discord@0.3.2 + uses: Ilshidur/action-discord@0c4b27844ba47cb1c7bee539c8eead5284ce9fa9 # 0.3.2 env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} with: diff --git a/.github/workflows/deploy_packages.yml b/.github/workflows/deploy_packages.yml index 91b25fb323..f5ebfd7ee2 100644 --- a/.github/workflows/deploy_packages.yml +++ b/.github/workflows/deploy_packages.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [18.x] + node-version: [18.x, 20.x] services: postgres13: @@ -60,10 +60,10 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -112,7 +112,7 @@ jobs: - name: Discord notification if: ${{ failure() }} - uses: Ilshidur/action-discord@0.3.2 + uses: Ilshidur/action-discord@0c4b27844ba47cb1c7bee539c8eead5284ce9fa9 # 0.3.2 env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} with: @@ -137,10 +137,15 @@ jobs: NODE_OPTIONS: --max-old-space-size=4096 steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -185,7 +190,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} - name: Dispatch repository event - uses: peter-evans/repository-dispatch@v2 + uses: peter-evans/repository-dispatch@bf47d102fdb849e755b0b0023ea3e81a44b6f570 # v2.1.2 with: token: ${{ secrets.GH_SERVICE_ACCOUNT_TOKEN }} event-type: release-published @@ -193,7 +198,7 @@ jobs: # Notify everyone about this great new release :D - name: Discord notification - uses: Ilshidur/action-discord@0.3.2 + uses: Ilshidur/action-discord@0c4b27844ba47cb1c7bee539c8eead5284ce9fa9 # 0.3.2 env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_RELEASE_WEBHOOK }} TAG_NAME: ${{ steps.create_tag.outputs.tag_name }} diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index 89595db189..1c1c028f20 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -9,5 +9,10 @@ jobs: if: github.repository == 'backstage/backstage' steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Issue sync uses: backstage/actions/issue-sync@v0.6.4 diff --git a/.github/workflows/pr-review-comment-trigger.yaml b/.github/workflows/pr-review-comment-trigger.yaml index 67e4c5abba..784dc6cf79 100644 --- a/.github/workflows/pr-review-comment-trigger.yaml +++ b/.github/workflows/pr-review-comment-trigger.yaml @@ -7,6 +7,9 @@ on: types: - created +permissions: + contents: read + jobs: trigger: runs-on: ubuntu-latest @@ -16,13 +19,18 @@ jobs: if: github.repository == 'backstage/backstage' && github.event.comment.user.id == github.event.pull_request.user.id steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Save PR number env: PR_NUMBER: ${{ github.event.pull_request.number }} run: | mkdir -p ./pr echo $PR_NUMBER > ./pr/pr_number - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v3.1.3 with: name: pr_number-${{ github.event.pull_request.number }} path: pr/ diff --git a/.github/workflows/pr-review-comment.yaml b/.github/workflows/pr-review-comment.yaml index 0930c75ddd..e557c85d51 100644 --- a/.github/workflows/pr-review-comment.yaml +++ b/.github/workflows/pr-review-comment.yaml @@ -16,9 +16,14 @@ 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@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Read PR Number id: pr-number - uses: actions/github-script@v6 + uses: actions/github-script@v6.4.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index a92effbd14..8c99f105a9 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -17,6 +17,11 @@ jobs: # Avoid running on issue comments if: github.repository == 'backstage/backstage' && ( github.event.pull_request || github.event.issue.pull_request ) steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: PR sync uses: backstage/actions/pr-sync@v0.6.4 with: diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 6fe4ab0f9e..c9078f0086 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -28,13 +28,18 @@ jobs: id-token: write steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: 'Checkout code' - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@v3.6.0 with: persist-credentials: false - name: 'Run analysis' - uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0 + uses: ossf/scorecard-action@483ef80eb98fb506c348f7d62e28055e49fe2398 # v2.3.0 with: results_file: results.sarif results_format: sarif @@ -53,7 +58,7 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: 'Upload artifact' - uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 + uses: actions/upload-artifact@v3.1.3 with: name: SARIF file path: results.sarif @@ -61,6 +66,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@ddccb873888234080b77e9bc2d4764d5ccaaccf9 # v2.21.9 + uses: github/codeql-action/upload-sarif@fdcae64e1484d349b3366718cdfef3d404390e85 # v2.22.1 with: sarif_file: results.sarif diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index 6471b265bc..fa8d91f25a 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -9,13 +9,18 @@ jobs: name: Autofix Markdown files using Prettier runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 with: # Fetch changes to previous commit - required for 'only_changed' in Prettier action fetch-depth: 0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -25,7 +30,7 @@ jobs: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: Run Prettier on ADOPTERS.md - uses: creyD/prettier_action@v4.3 + uses: creyD/prettier_action@31355f8eef017f8aeba2e0bc09d8502b13dbbad1 # v4.3 with: # Modifies commit only if prettier autofixed the ADOPTERS.md prettier_options: --config docs/prettier.config.js --write ADOPTERS.md diff --git a/.github/workflows/sync_dependabot-changesets.yml b/.github/workflows/sync_dependabot-changesets.yml index d5f6f9a36c..2ac6d7f0d0 100644 --- a/.github/workflows/sync_dependabot-changesets.yml +++ b/.github/workflows/sync_dependabot-changesets.yml @@ -10,8 +10,13 @@ jobs: runs-on: ubuntu-latest if: github.actor == 'dependabot[bot]' && github.repository == 'backstage/backstage' steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v3.6.0 with: fetch-depth: 2 ref: ${{ github.head_ref }} @@ -21,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@v6 + uses: actions/github-script@v6.4.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 df8d3909f4..46d5d5382a 100644 --- a/.github/workflows/sync_release-manifest.yml +++ b/.github/workflows/sync_release-manifest.yml @@ -7,8 +7,13 @@ jobs: create-new-version: runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + # Setup node & install deps before checkout, keeping install quick - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v3.8.1 with: node-version: 18.x - name: Install dependencies @@ -16,7 +21,7 @@ jobs: run: npm install semver@7.3.5 fs-extra@10.0.0 @manypkg/get-packages@1.1.1 - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v3.6.0 with: path: backstage # 'v' prefix is added here for the tag, we keep it out of the manifest logic @@ -24,7 +29,7 @@ jobs: # Checkout backstage/versions into /backstage/versions, which is where store the output - name: Checkout versions - uses: actions/checkout@v3 + uses: actions/checkout@v3.6.0 with: repository: backstage/versions path: backstage/versions @@ -48,7 +53,7 @@ jobs: git push - name: Dispatch update-helper update - uses: actions/github-script@v6 + uses: actions/github-script@v6.4.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 cd67fa9954..738abcf773 100644 --- a/.github/workflows/sync_renovate-changesets.yml +++ b/.github/workflows/sync_renovate-changesets.yml @@ -10,8 +10,13 @@ jobs: runs-on: ubuntu-latest if: github.actor == 'renovate[bot]' && github.repository == 'backstage/backstage' steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v3.6.0 with: fetch-depth: 2 ref: ${{ github.head_ref }} @@ -21,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@v6 + uses: actions/github-script@v6.4.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 6b55609bd5..690e2fb76e 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -11,10 +11,15 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 - name: use node.js 18.x - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: 18.x registry-url: https://registry.npmjs.org/ # Needed for auth @@ -24,7 +29,7 @@ jobs: cache-prefix: ${{ runner.os }}-v18.x - name: Create Snyk report - uses: snyk/actions/node@master + uses: snyk/actions/node@299cde98a08ff8b1c2bfde1e5a067bce67a6d2b8 # master continue-on-error: true # Snyk CLI exits with error when vulnerabilities are found with: args: > diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml index 8bfa90d726..6450b1bd51 100644 --- a/.github/workflows/sync_snyk-monitor.yml +++ b/.github/workflows/sync_snyk-monitor.yml @@ -14,13 +14,24 @@ on: # ignore policies in the .snyk files and then have them show up in the snyk web # UI, and also automatically adds any new packages that are created. +permissions: + contents: read + jobs: sync: + permissions: + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 - name: Monitor and Synchronize Snyk Policies - uses: snyk/actions/node@master + uses: snyk/actions/node@299cde98a08ff8b1c2bfde1e5a067bce67a6d2b8 # master with: command: monitor args: > @@ -35,7 +46,7 @@ jobs: # Above we run the `monitor` command, this runs the `test` command which is # the one that generates the SARIF report that we can upload to GitHub. - name: Create Snyk report - uses: snyk/actions/node@master + uses: snyk/actions/node@299cde98a08ff8b1c2bfde1e5a067bce67a6d2b8 # master continue-on-error: true # To make sure that SARIF upload gets called with: args: > @@ -47,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 + uses: github/codeql-action/upload-sarif@v2.21.8 with: sarif_file: snyk.sarif diff --git a/.github/workflows/sync_version-packages.yml b/.github/workflows/sync_version-packages.yml index 127c11791d..929fb9cc89 100644 --- a/.github/workflows/sync_version-packages.yml +++ b/.github/workflows/sync_version-packages.yml @@ -13,7 +13,12 @@ jobs: name: Create Changeset PR runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 with: fetch-depth: 20000 fetch-tags: true @@ -21,7 +26,7 @@ jobs: - name: Install Dependencies run: yarn --immutable - name: Create Release Pull Request - uses: backstage/changesets-action@v2 + uses: backstage/changesets-action@v2.1.0 with: # Calls out to `changeset version`, but also runs prettier version: yarn release @@ -31,7 +36,7 @@ jobs: - name: Discord notification if: ${{ failure() }} - uses: Ilshidur/action-discord@0.3.2 + uses: Ilshidur/action-discord@0c4b27844ba47cb1c7bee539c8eead5284ce9fa9 # 0.3.2 env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} with: diff --git a/.github/workflows/uffizzi-build.yml b/.github/workflows/uffizzi-build.yml index 1bcd5ebcd8..3107b87b8f 100644 --- a/.github/workflows/uffizzi-build.yml +++ b/.github/workflows/uffizzi-build.yml @@ -19,11 +19,16 @@ jobs: outputs: tags: ${{ steps.meta.outputs.tags }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: checkout - uses: actions/checkout@v3 + uses: actions/checkout@v3.6.0 - name: setup-node - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: 18.x registry-url: https://registry.npmjs.org/ @@ -46,7 +51,7 @@ jobs: yarn workspace example-backend build - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2.10.0 - name: Generate UUID image name id: uuid @@ -54,13 +59,13 @@ jobs: - name: Docker metadata id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@818d4b7b91585d195f67373fd9cb0332e31a7175 # v4.6.0 with: images: registry.uffizzi.com/${{ env.UUID_TAG_APP }} tags: type=raw,value=60d - name: Build Image - uses: docker/build-push-action@v4 + uses: docker/build-push-action@0a97817b6ade9f46837855d676c4cca3a2471fc9 # v4.2.1 with: context: . file: packages/backend/Dockerfile @@ -76,8 +81,13 @@ jobs: outputs: compose-file-cache-key: ${{ steps.hash.outputs.hash }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Checkout git repo - uses: actions/checkout@v3 + uses: actions/checkout@v3.6.0 - name: Render Compose File run: | BACKSTAGE_IMAGE=$(echo ${{ needs.build-backstage.outputs.tags }}) @@ -86,13 +96,13 @@ jobs: envsubst '$BACKSTAGE_IMAGE $GITHUB_SHA' < .github/uffizzi/docker-compose.uffizzi.yml > docker-compose.rendered.yml cat docker-compose.rendered.yml - name: Upload Rendered Compose File as Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v3.1.3 with: name: preview-spec path: docker-compose.rendered.yml retention-days: 2 - name: Upload PR Event as Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v3.1.3 with: name: preview-spec path: ${{ github.event_path }} @@ -103,9 +113,14 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event.action == 'closed' }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + # If this PR is closing, we will not render a compose file nor pass it to the next workflow. - name: Upload PR Event as Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v3.1.3 with: name: preview-spec path: ${{ github.event_path }} diff --git a/.github/workflows/uffizzi-preview.yaml b/.github/workflows/uffizzi-preview.yaml index 87c1eaa02f..deebf356bf 100644 --- a/.github/workflows/uffizzi-preview.yaml +++ b/.github/workflows/uffizzi-preview.yaml @@ -17,9 +17,14 @@ jobs: git-ref: ${{ env.GIT_REF }} pr-number: ${{ env.PR_NUMBER }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: 'Download artifacts' # Fetch output (zip archive) from the workflow run that triggered this workflow. - uses: actions/github-script@v6 + uses: actions/github-script@v6.4.1 with: script: | let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ @@ -59,7 +64,7 @@ jobs: - name: Cache Rendered Compose File if: ${{ fromJSON(env.EVENT_JSON).action != 'closed' }} - uses: actions/cache@v3 + uses: actions/cache@v3.3.2 with: path: docker-compose.rendered.yml key: ${{ env.COMPOSE_FILE_HASH }} diff --git a/.github/workflows/verify_accessibility-noop.yml b/.github/workflows/verify_accessibility-noop.yml index bde483eece..e2b1860b28 100644 --- a/.github/workflows/verify_accessibility-noop.yml +++ b/.github/workflows/verify_accessibility-noop.yml @@ -17,9 +17,17 @@ on: - 'plugins/search/src/**' - 'plugins/search-react/src/**' +permissions: + contents: read + jobs: noop: name: Accessibility runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP diff --git a/.github/workflows/verify_accessibility.yml b/.github/workflows/verify_accessibility.yml index 32ded3bd3a..d53f3834d2 100644 --- a/.github/workflows/verify_accessibility.yml +++ b/.github/workflows/verify_accessibility.yml @@ -19,9 +19,14 @@ jobs: name: Accessibility runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 - name: Use Node.js 18.x - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: 18.x - name: yarn install diff --git a/.github/workflows/verify_codeql.yml b/.github/workflows/verify_codeql.yml index f3417ac582..666bd5f0f4 100644 --- a/.github/workflows/verify_codeql.yml +++ b/.github/workflows/verify_codeql.yml @@ -19,8 +19,15 @@ on: schedule: - cron: '0 8 * * 6' +permissions: + contents: read + jobs: analyze: + permissions: + actions: read # for github/codeql-action/init to get workflow details + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/autobuild to send a status report name: Analyze runs-on: ubuntu-latest @@ -34,8 +41,13 @@ jobs: # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v3.6.0 with: # We must fetch at least the immediate parents so that if this is # a pull request then we can checkout the head. @@ -43,7 +55,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v2.21.8 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -54,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 + uses: github/codeql-action/autobuild@v2.21.8 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -68,4 +80,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v2.21.8 diff --git a/.github/workflows/verify_docs-quality.yml b/.github/workflows/verify_docs-quality.yml index dc1d942e32..ce457a234f 100644 --- a/.github/workflows/verify_docs-quality.yml +++ b/.github/workflows/verify_docs-quality.yml @@ -11,7 +11,12 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 # Vale does not support file excludes, so we use the script to generate a list of files instead # The action also does not allow args or a local config file to be passed in, so the files array @@ -21,7 +26,7 @@ jobs: run: echo "args=$(node scripts/check-docs-quality.js --ci-args)" >> $GITHUB_OUTPUT - name: documentation quality check - uses: errata-ai/vale-action@v2.0.1 + uses: errata-ai/vale-action@c4213d4de3d5f718b8497bd86161531c78992084 # v2.0.1 with: # This also contains --config=.github/vale/config.ini ... :/ files: '${{ steps.generate.outputs.args }}' diff --git a/.github/workflows/verify_e2e-kubernetes-noop.yml b/.github/workflows/verify_e2e-kubernetes-noop.yml index bedf357079..5c52968820 100644 --- a/.github/workflows/verify_e2e-kubernetes-noop.yml +++ b/.github/workflows/verify_e2e-kubernetes-noop.yml @@ -9,6 +9,9 @@ on: - '.github/workflows/verify_e2e-kubernetes.yml' - 'packages/backend-common/src/**' +permissions: + contents: read + jobs: verify: runs-on: ubuntu-latest @@ -19,4 +22,9 @@ jobs: name: Kubernetes ${{ matrix.node-version }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP diff --git a/.github/workflows/verify_e2e-kubernetes.yml b/.github/workflows/verify_e2e-kubernetes.yml index 0c78c1f933..cddd6589d7 100644 --- a/.github/workflows/verify_e2e-kubernetes.yml +++ b/.github/workflows/verify_e2e-kubernetes.yml @@ -21,10 +21,15 @@ jobs: name: Kubernetes ${{ matrix.node-version }} steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -35,7 +40,7 @@ jobs: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: bootstrap kind - uses: helm/kind-action@v1.8.0 + uses: helm/kind-action@dda0770415bac9fc20092cacbc54aa298604d140 # v1.8.0 - name: kubernetes test working-directory: packages/backend-common diff --git a/.github/workflows/verify_e2e-linux-noop.yml b/.github/workflows/verify_e2e-linux-noop.yml index 1384b83378..27e08c7055 100644 --- a/.github/workflows/verify_e2e-linux-noop.yml +++ b/.github/workflows/verify_e2e-linux-noop.yml @@ -14,6 +14,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + jobs: noop: runs-on: ubuntu-latest @@ -24,4 +27,9 @@ jobs: name: E2E Linux ${{ matrix.node-version }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP diff --git a/.github/workflows/verify_e2e-linux.yml b/.github/workflows/verify_e2e-linux.yml index 61ce55e385..744a5d7e74 100644 --- a/.github/workflows/verify_e2e-linux.yml +++ b/.github/workflows/verify_e2e-linux.yml @@ -39,7 +39,12 @@ jobs: name: E2E Linux ${{ matrix.node-version }} steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 - name: Configure Git run: | @@ -47,7 +52,7 @@ jobs: git config --global user.name 'GitHub e2e user' - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth diff --git a/.github/workflows/verify_e2e-techdocs.yml b/.github/workflows/verify_e2e-techdocs.yml index fd5c4f0956..94f08a491f 100644 --- a/.github/workflows/verify_e2e-techdocs.yml +++ b/.github/workflows/verify_e2e-techdocs.yml @@ -12,6 +12,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + jobs: verify: runs-on: ubuntu-latest @@ -26,8 +29,13 @@ jobs: name: Techdocs steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 + - uses: actions/setup-python@v4.7.0 with: python-version: '3.9' diff --git a/.github/workflows/verify_e2e-windows-noop.yml b/.github/workflows/verify_e2e-windows-noop.yml index f042c350c2..e4b8556f58 100644 --- a/.github/workflows/verify_e2e-windows-noop.yml +++ b/.github/workflows/verify_e2e-windows-noop.yml @@ -11,6 +11,9 @@ on: - 'packages/e2e-test/**' - 'packages/create-app/**' +permissions: + contents: read + jobs: noop: runs-on: windows-2019 @@ -21,4 +24,9 @@ jobs: name: E2E Windows ${{ matrix.node-version }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP diff --git a/.github/workflows/verify_e2e-windows.yml b/.github/workflows/verify_e2e-windows.yml index b1decefd10..1385983c24 100644 --- a/.github/workflows/verify_e2e-windows.yml +++ b/.github/workflows/verify_e2e-windows.yml @@ -30,6 +30,11 @@ jobs: name: E2E Windows ${{ matrix.node-version }} steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + # In order to have the create-app template function as if it was downloaded from NPM # we need to make sure we checkout files with LF line endings only - name: Set git to use LF @@ -37,7 +42,7 @@ jobs: git config --global core.autocrlf false git config --global core.eol lf - - uses: actions/checkout@v3 + - uses: actions/checkout@v3.6.0 - name: Configure Git run: | @@ -45,13 +50,13 @@ jobs: git config --global user.name 'GitHub e2e user' - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth - name: setup python - uses: actions/setup-python@v4 + uses: actions/setup-python@v4.7.0 with: python-version: '3.10' @@ -70,7 +75,7 @@ jobs: npm prefix -g | % {npm config set node_gyp "$_\node_modules\node-gyp\bin\node-gyp.js"} - name: setup chrome - uses: browser-actions/setup-chrome@latest + uses: browser-actions/setup-chrome@803ef6dfb4fdf22089c9563225d95e4a515820a0 # latest - name: yarn install uses: backstage/actions/yarn-install@v0.6.4 diff --git a/.github/workflows/verify_fossa.yml b/.github/workflows/verify_fossa.yml index 8c6b25d2e4..393bcf9631 100644 --- a/.github/workflows/verify_fossa.yml +++ b/.github/workflows/verify_fossa.yml @@ -5,13 +5,21 @@ on: pull_request: branches: [master] +permissions: + contents: read + jobs: analyze: runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v3.6.0 - name: Install Fossa run: "curl -H 'Cache-Control: no-cache' https://raw.githubusercontent.com/fossas/fossa-cli/master/install.sh | bash" diff --git a/.github/workflows/verify_microsite-noop.yml b/.github/workflows/verify_microsite-noop.yml index cca7e512c5..8c329a0f27 100644 --- a/.github/workflows/verify_microsite-noop.yml +++ b/.github/workflows/verify_microsite-noop.yml @@ -11,10 +11,18 @@ on: - 'mkdocs.yml' - 'docs/**' +permissions: + contents: read + jobs: noop: runs-on: ubuntu-latest name: Microsite steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP diff --git a/.github/workflows/verify_microsite.yml b/.github/workflows/verify_microsite.yml index d219d0ea74..f0705bedc7 100644 --- a/.github/workflows/verify_microsite.yml +++ b/.github/workflows/verify_microsite.yml @@ -9,6 +9,9 @@ on: - 'mkdocs.yml' - 'docs/**' +permissions: + contents: read + jobs: build-microsite: runs-on: ubuntu-latest @@ -20,10 +23,15 @@ jobs: name: Microsite steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 - name: use node.js 18.x - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: 18.x diff --git a/.github/workflows/verify_storybook-noop.yml b/.github/workflows/verify_storybook-noop.yml index c1f16e4fbd..aee4623d5a 100644 --- a/.github/workflows/verify_storybook-noop.yml +++ b/.github/workflows/verify_storybook-noop.yml @@ -18,10 +18,18 @@ on: - 'packages/core-components/src/**' - '**/*.stories.tsx' +permissions: + contents: read + jobs: noop: runs-on: ubuntu-latest name: Storybook steps: + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + - run: echo NOOP diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index bcb0cfe178..f0354df296 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -27,12 +27,17 @@ jobs: name: Storybook steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 with: fetch-depth: 0 # Required to retrieve git history - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth @@ -46,7 +51,7 @@ jobs: - run: yarn build-storybook - - uses: chromaui/action@v1 + - uses: chromaui/action@807600692d28833b717c155e15ed20905cdc865c # 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 312c662b5a..f2c61938d8 100644 --- a/.github/workflows/verify_windows.yml +++ b/.github/workflows/verify_windows.yml @@ -7,6 +7,9 @@ on: paths: - '.github/workflows/verify_windows.yml' +permissions: + contents: read + jobs: build: runs-on: windows-2022 @@ -25,10 +28,15 @@ jobs: INTEGRATION_TEST_AZURE_TOKEN: ${{ secrets.INTEGRATION_TEST_AZURE_TOKEN }} steps: - - uses: actions/checkout@v3 + - name: Harden Runner + uses: step-security/harden-runner@8ca2b8b2ece13480cda6dacd3511b49857a23c09 # v2.5.1 + with: + egress-policy: audit + + - uses: actions/checkout@v3.6.0 - name: use node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v3.8.1 with: node-version: ${{ matrix.node-version }} registry-url: https://registry.npmjs.org/ # Needed for auth diff --git a/.gitignore b/.gitignore index 7149dbabc1..c0ef0d2001 100644 --- a/.gitignore +++ b/.gitignore @@ -159,4 +159,7 @@ e2e-test-report/ # VS Code backing up svg files *svg.bkp -*svg.dtmp \ No newline at end of file +*svg.dtmp + +# Scripts +plugins-report.csv \ No newline at end of file diff --git a/.yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch b/.yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch new file mode 100644 index 0000000000..1e3c82e9dd --- /dev/null +++ b/.yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch @@ -0,0 +1,112 @@ +diff --git a/DateTimePicker/DateTimePickerTabs.d.ts b/DateTimePicker/DateTimePickerTabs.d.ts +index 52396cccbb66861dd6519459141e7744aa25aaf8..75c5a9053a88abf2454b7783c0101a1a8c9375f1 100644 +--- a/DateTimePicker/DateTimePickerTabs.d.ts ++++ b/DateTimePicker/DateTimePickerTabs.d.ts +@@ -7,5 +7,5 @@ export interface DateTimePickerTabsProps { + timeIcon?: React.ReactNode; + } + export declare const useStyles: (props?: any) => Record<"tabs", string>; +-export declare const DateTimePickerTabs: React.SFC; ++export declare const DateTimePickerTabs: React.FC; + export default DateTimePickerTabs; +diff --git a/_shared/ModalDialog.d.ts b/_shared/ModalDialog.d.ts +index 067070067ccf6e7699d17f422934daf14370d225..c45a583adef09a2091865db91b2687e66af81b47 100644 +--- a/_shared/ModalDialog.d.ts ++++ b/_shared/ModalDialog.d.ts +@@ -15,7 +15,7 @@ export interface ModalDialogProps extends DialogProps { + showTabs?: boolean; + wider?: boolean; + } +-export declare const ModalDialog: React.SFC>; ++export declare const ModalDialog: React.FC>; + export declare const styles: Record<"dialog" | "dialogRoot" | "dialogRootWider" | "withAdditionalAction", import("@material-ui/core/styles/withStyles").CSSProperties | import("@material-ui/core/styles/withStyles").CreateCSSProperties<{}> | ((props: {}) => import("@material-ui/core/styles/withStyles").CreateCSSProperties<{}>)>; + declare const _default: React.ComponentType; +diff --git a/_shared/PickerToolbar.d.ts b/_shared/PickerToolbar.d.ts +index f1ccd368bf9ab853cf0356d03fce0390becad8cd..e75ef734788cb26cc07dc079c714f759f525c447 100644 +--- a/_shared/PickerToolbar.d.ts ++++ b/_shared/PickerToolbar.d.ts +@@ -5,5 +5,5 @@ export declare const useStyles: (props?: any) => Record<"toolbar" | "toolbarLand + interface PickerToolbarProps extends ExtendMui { + isLandscape: boolean; + } +-declare const PickerToolbar: React.SFC; ++declare const PickerToolbar: React.FC; + export default PickerToolbar; +diff --git a/_shared/WithUtils.d.ts b/_shared/WithUtils.d.ts +index 22fe0425817be182a6c9a1a21a0f9eefb61696e7..b5b2a966ec0ea8427c4355227d8425b9c1af3790 100644 +--- a/_shared/WithUtils.d.ts ++++ b/_shared/WithUtils.d.ts +@@ -4,4 +4,4 @@ import { MaterialUiPickersDate } from '../typings/date'; + export interface WithUtilsProps { + utils: IUtils; + } +-export declare const withUtils: () =>

(Component: React.ComponentType

) => React.SFC>>; ++export declare const withUtils: () =>

(Component: React.ComponentType

) => React.FC>>; +diff --git a/_shared/icons/ArrowLeftIcon.d.ts b/_shared/icons/ArrowLeftIcon.d.ts +index ce0f208a2aa6dae03a77dfe830a10a95c2085030..95a516da22e02b9a4167ee4a52bf2cd0a1b4aec6 100644 +--- a/_shared/icons/ArrowLeftIcon.d.ts ++++ b/_shared/icons/ArrowLeftIcon.d.ts +@@ -1,3 +1,3 @@ + import React from 'react'; + import { SvgIconProps } from '@material-ui/core/SvgIcon'; +-export declare const ArrowLeftIcon: React.SFC; ++export declare const ArrowLeftIcon: React.FC; +diff --git a/_shared/icons/ArrowRightIcon.d.ts b/_shared/icons/ArrowRightIcon.d.ts +index 71443a34f7bbd2cef8c2af487c817b7ea788dd7a..a96314aa8750180773f1d006ed766e5a7e8e071d 100644 +--- a/_shared/icons/ArrowRightIcon.d.ts ++++ b/_shared/icons/ArrowRightIcon.d.ts +@@ -1,3 +1,3 @@ + import React from 'react'; + import { SvgIconProps } from '@material-ui/core/SvgIcon'; +-export declare const ArrowRightIcon: React.SFC; ++export declare const ArrowRightIcon: React.FC; +diff --git a/_shared/icons/DateRangeIcon.d.ts b/_shared/icons/DateRangeIcon.d.ts +index 722f8736d86f248d464c5af855795663d9e220d3..6018043d41861d96335f060ea1dc78336892ce66 100644 +--- a/_shared/icons/DateRangeIcon.d.ts ++++ b/_shared/icons/DateRangeIcon.d.ts +@@ -1,3 +1,3 @@ + import React from 'react'; + import { SvgIconProps } from '@material-ui/core/SvgIcon'; +-export declare const DateRangeIcon: React.SFC; ++export declare const DateRangeIcon: React.FC; +diff --git a/_shared/icons/KeyboardIcon.d.ts b/_shared/icons/KeyboardIcon.d.ts +index c1a0a111d831acc58cf19aa6d54f8324e68de9d8..8d7d1dac47815cef02215c4f11f36e73509b4219 100644 +--- a/_shared/icons/KeyboardIcon.d.ts ++++ b/_shared/icons/KeyboardIcon.d.ts +@@ -1,3 +1,3 @@ + import React from 'react'; + import { SvgIconProps } from '@material-ui/core/SvgIcon'; +-export declare const KeyboardIcon: React.SFC; ++export declare const KeyboardIcon: React.FC; +diff --git a/_shared/icons/TimeIcon.d.ts b/_shared/icons/TimeIcon.d.ts +index 49e0b627132f7d31d1b0a205548229a9f7a2c0a6..15ebc6e630992edb3b01790c0dd651651adf51de 100644 +--- a/_shared/icons/TimeIcon.d.ts ++++ b/_shared/icons/TimeIcon.d.ts +@@ -1,3 +1,3 @@ + import React from 'react'; + import { SvgIconProps } from '@material-ui/core/SvgIcon'; +-export declare const TimeIcon: React.SFC; ++export declare const TimeIcon: React.FC; +diff --git a/views/Calendar/CalendarHeader.d.ts b/views/Calendar/CalendarHeader.d.ts +index 842cbd8e021eb6d8e6553ba68033f13140485b61..7f60b4bffce1a96ade02e2671fd705c8fe87dfa2 100644 +--- a/views/Calendar/CalendarHeader.d.ts ++++ b/views/Calendar/CalendarHeader.d.ts +@@ -15,5 +15,5 @@ export interface CalendarHeaderProps { + onMonthChange: (date: MaterialUiPickersDate, direction: SlideDirection) => void | Promise; + } + export declare const useStyles: (props?: any) => Record<"transitionContainer" | "switchHeader" | "iconButton" | "daysHeader" | "dayLabel", string>; +-export declare const CalendarHeader: React.SFC; ++export declare const CalendarHeader: React.FC; + export default CalendarHeader; +diff --git a/views/Calendar/SlideTransition.d.ts b/views/Calendar/SlideTransition.d.ts +index f00e98a72bd0e6cfd80ab45b33b905e802b60e9b..699119009fa5ea886e7f782425aee39b7608b8c2 100644 +--- a/views/Calendar/SlideTransition.d.ts ++++ b/views/Calendar/SlideTransition.d.ts +@@ -7,5 +7,5 @@ interface SlideTransitionProps { + children: React.ReactChild; + } + export declare const useStyles: (props?: any) => Record<"transitionContainer" | "slideEnter-left" | "slideEnter-right" | "slideEnterActive" | "slideExit" | "slideExitActiveLeft-left" | "slideExitActiveLeft-right", string>; +-declare const SlideTransition: React.SFC; ++declare const SlideTransition: React.FC; + export default SlideTransition; diff --git a/docs/assets/plugins/create-plugin_types.png b/docs/assets/plugins/create-plugin_types.png new file mode 100644 index 0000000000..ea45d1cdd1 Binary files /dev/null and b/docs/assets/plugins/create-plugin_types.png differ diff --git a/docs/assets/my-plugin_screenshot.png b/docs/assets/plugins/my-plugin_screenshot.png similarity index 100% rename from docs/assets/my-plugin_screenshot.png rename to docs/assets/plugins/my-plugin_screenshot.png diff --git a/docs/features/software-catalog/configuration.md b/docs/features/software-catalog/configuration.md index bd914cc56c..97c75a01ff 100644 --- a/docs/features/software-catalog/configuration.md +++ b/docs/features/software-catalog/configuration.md @@ -44,6 +44,20 @@ When multiple `catalog-info.yaml` files with the same `metadata.name` property are discovered, one will be processed and all others will be skipped. This action is logged for further investigation. +### Local File (`type: file`) Configurations + +In addition to url locations, you can use the `file` location type to bring in content from the local file system. You should only use this for local development, test setups and example data, not for production data. +You are also not able to use placeholders in them like `$text`. You can however reference other files relative to the current file. See the full [catalog example data set here](https://github.com/backstage/backstage/tree/master/packages/catalog-model/examples) for an extensive example. + +Here is an example pulling in the `all.yaml` file from the examples folder. Note the use of `../../` to go up two levels from the current execution path of the backend. This is typically `packages/backend/`. + +```yaml +catalog: + locations: + - type: file + target: ../../examples/all.yaml +``` + ### Integration Processors Integrations may simply provide a mechanism to handle `url` location type for an diff --git a/docs/features/software-catalog/extending-the-model.md b/docs/features/software-catalog/extending-the-model.md index 52ef565837..fec924fa91 100644 --- a/docs/features/software-catalog/extending-the-model.md +++ b/docs/features/software-catalog/extending-the-model.md @@ -447,6 +447,9 @@ want to have an isomorphic package that houses these types. Within the Backstage main repo the package naming pattern of `-common` is used for isomorphic packages, and you may choose to adopt this pattern as well. +You can generate an isomorphic plugin package by running:`yarn new --select plugin-common` +or you can run `yarn new` and then select "plugin-common" from the list of options + There's at this point no existing templates for generating isomorphic plugins using the `@backstage/cli`. Perhaps the simplest wat to get started right now is to copy the contents of one of the existing packages in the main repository, diff --git a/docs/features/software-templates/input-examples.md b/docs/features/software-templates/input-examples.md index c44ee39269..ad56ef2d36 100644 --- a/docs/features/software-templates/input-examples.md +++ b/docs/features/software-templates/input-examples.md @@ -110,10 +110,11 @@ parameters: arrayObjects: title: Array with custom objects type: array + minItems: 0 ui:options: - addable: false - orderable: false - removable: false + addable: true + orderable: true + removable: true items: type: object properties: diff --git a/docs/features/techdocs/cli.md b/docs/features/techdocs/cli.md index 87eb67d04a..9704b9b21b 100644 --- a/docs/features/techdocs/cli.md +++ b/docs/features/techdocs/cli.md @@ -95,6 +95,7 @@ Options: --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. Can only be used with "--preview-app-bundle-path". (default: "3000") + -c, --mkdocs-config-file-name Yaml file to use as config by mkdocs. -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 8c98ec48d4..29f985904f 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -525,6 +525,39 @@ techdocs: This way, all iframes where the host in the src attribute is in the `sanitizer.allowedIframeHosts` list will be displayed. +## How to render PlantUML diagram in TechDocs + +PlantUML allows you to create diagrams from plain text language. Each diagram description begins with the keyword - (@startXYZ and @endXYZ, depending on the kind of diagram). For UML Diagrams, Keywords @startuml & @enduml should be used. Further details for all types of diagrams can be found at [PlantUML Language Reference Guide](https://plantuml.com/guide). + +### UML Diagram Details:- + +#### Embedded PlantUML Diagram Example + +Here, the markdown file itself contains the diagram description. + +````md +```plantuml +@startuml +title Login Sequence + ComponentA->ComponentB: Login Request + note right of ComponentB: ComponentB logs message + ComponentB->ComponentA: Login Response +@enduml +``` +```` + +#### Referenced PlantUML Diagram Example + +Here, the markdown file refers to another file (`*.puml` or `*.pu`) which contains the diagram description. + +````md +```plantuml +!include umldiagram.puml +``` +```` + +Note: To refer external diagram files, we need to include the diagrams directory in the path. Please refer [`Dockerfile`](https://github.com/backstage/techdocs-container/blob/main/Dockerfile) for details. + ## How to add Mermaid support in TechDocs To add `Mermaid` support in TechDocs, you can use [`kroki`](https://kroki.io) diff --git a/docs/local-dev/cli-build-system.md b/docs/local-dev/cli-build-system.md index 06aec945b9..61e24863fe 100644 --- a/docs/local-dev/cli-build-system.md +++ b/docs/local-dev/cli-build-system.md @@ -484,30 +484,29 @@ of the build system, including the bundling, tests, builds, and type checking. Loaders are always selected based on the file extension. The following is a list of all supported file extensions: -| Extension | Exports | Purpose | -| ----------- | --------------- | -------------------------------------------------------------------------------------- | -| `.ts` | Script Module | TypeScript | -| `.tsx` | Script Module | TypeScript and XML | -| `.js` | Script Module | JavaScript | -| `.jsx` | Script Module | JavaScript and XML | -| `.mjs` | Script Module | ECMAScript Module | -| `.cjs` | Script Module | CommonJS Module | -| `.json` | JSON Data | JSON Data | -| `.yml` | JSON Data | YAML Data | -| `.yaml` | JSON Data | YAML Data | -| `.css` | classes | Style sheet | -| `.eot` | URL Path | Font | -| `.ttf` | URL Path | Font | -| `.woff2` | URL Path | Font | -| `.woff` | URL Path | Font | -| `.bmp` | URL Path | Image | -| `.gif` | URL Path | Image | -| `.jpeg` | URL Path | Image | -| `.jpg` | URL Path | Image | -| `.png` | URL Path | Image | -| `.svg` | URL Path | Image | -| `.md` | URL Path | Markdown File | -| `.icon.svg` | React Component | SVG converted into a [Material UI SvgIcon](https://mui.com/material-ui/icons/#svgicon) | +| Extension | Exports | Purpose | +| --------- | ------------- | ------------------ | +| `.ts` | Script Module | TypeScript | +| `.tsx` | Script Module | TypeScript and XML | +| `.js` | Script Module | JavaScript | +| `.jsx` | Script Module | JavaScript and XML | +| `.mjs` | Script Module | ECMAScript Module | +| `.cjs` | Script Module | CommonJS Module | +| `.json` | JSON Data | JSON Data | +| `.yml` | JSON Data | YAML Data | +| `.yaml` | JSON Data | YAML Data | +| `.css` | classes | Style sheet | +| `.eot` | URL Path | Font | +| `.ttf` | URL Path | Font | +| `.woff2` | URL Path | Font | +| `.woff` | URL Path | Font | +| `.bmp` | URL Path | Image | +| `.gif` | URL Path | Image | +| `.jpeg` | URL Path | Image | +| `.jpg` | URL Path | Image | +| `.png` | URL Path | Image | +| `.svg` | URL Path | Image | +| `.md` | URL Path | Markdown File | ## Jest Configuration diff --git a/docs/overview/architecture-overview.md b/docs/overview/architecture-overview.md index 3ba3f4ba0b..f975baf1e1 100644 --- a/docs/overview/architecture-overview.md +++ b/docs/overview/architecture-overview.md @@ -323,8 +323,11 @@ backend: cache: store: redis connection: redis://user:pass@cache.example.com:6379 + useRedisSets: true ``` +The useRedisSets flag is explained [here](https://github.com/jaredwray/keyv/tree/main/packages/redis#useredissets). + Contributions supporting other cache stores are welcome! ## Containerization diff --git a/docs/plugins/create-a-plugin.md b/docs/plugins/create-a-plugin.md index cbd789c757..481b610e4e 100644 --- a/docs/plugins/create-a-plugin.md +++ b/docs/plugins/create-a-plugin.md @@ -8,7 +8,7 @@ A Backstage Plugin adds functionality to Backstage. ## Create a Plugin -To create a new plugin, make sure you've run `yarn install` and installed +To create a new frontend plugin, make sure you've run `yarn install` and installed dependencies, then run the following on your command line (a shortcut to invoking the [`backstage-cli new --select plugin`](../local-dev/cli-commands.md#new)) @@ -18,7 +18,7 @@ from the root of your project. yarn new --select plugin ``` -![](../assets/getting-started/create-plugin_output.png) +![Example of output when creating a new plugin](../assets/getting-started/create-plugin_output.png) This will create a new Backstage Plugin based on the ID that was provided. It will be built and added to the Backstage App automatically. @@ -27,7 +27,7 @@ will be built and added to the Backstage App automatically. > should be able to see the default page for your new plugin directly by > navigating to `http://localhost:3000/my-plugin`. -![](../assets/my-plugin_screenshot.png) +![Example of new plugin running in browser](../assets/plugins/my-plugin_screenshot.png) You can also serve the plugin in isolation by running `yarn start` in the plugin directory. Or by using the yarn workspace command, for example: @@ -39,3 +39,11 @@ yarn workspace @backstage/plugin-my-plugin start # Also supports --check This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads. It is only meant for local development, and the setup for it can be found inside the plugin's `dev/` directory. + +### Other Plugin Library Package Types + +There are other plugin library package types that you can chose from. To be able to +select the type when you create a new plugin just run: `yarn new`. You'll then be asked +what type of plugin you wish to create like this: + +![List of available plugin types to pick from](../assets/plugins/create-plugin_types.png) diff --git a/docs/plugins/index.md b/docs/plugins/index.md index a582556311..755c1b8a7d 100644 --- a/docs/plugins/index.md +++ b/docs/plugins/index.md @@ -12,7 +12,7 @@ development tool as a plugin in Backstage. By following strong [design guidelines](../dls/design.md) we ensure the overall user experience stays consistent between plugins. -![plugin](../assets/my-plugin_screenshot.png) +![plugin](../assets/plugins/my-plugin_screenshot.png) ## Creating a plugin diff --git a/docs/publishing.md b/docs/publishing.md index 2424bc1352..f8964278b5 100644 --- a/docs/publishing.md +++ b/docs/publishing.md @@ -40,7 +40,7 @@ Congratulations on the release! There should be now a post in the [`#announcemen Additional steps for the main line release - [Switch Release Mode](#switching-release-modes) to exit pre-release mode. This can be done at any time after the last Next Line Release. - - Check [`.changeset/pre.json`](https://github.com/backstage/backstage/blob/master/.changeset/pre.json) if the `mode` is set to `exit`. If you encounter `mode: "pre"` it indicates a next line release. + - Check `.changeset/pre.json` if the `mode` is set to `exit`. If you encounter `mode: "pre"` it indicates a next line release. - Check [`Version Packages` Pull Request](https://github.com/backstage/backstage/pulls?q=is%3Aopen+is%3Apr+in%3Atitle+%22Version+Packages) - Check for mentions of "major" & "breaking" and if they are expected in the current release - Verify the version we are shipping is correct diff --git a/docs/release-notes-template.md b/docs/release-notes-template.md index 9f9a0b76ee..4861bf0b22 100644 --- a/docs/release-notes-template.md +++ b/docs/release-notes-template.md @@ -12,7 +12,7 @@ A huge thanks to the whole team of maintainers and contributors as well as the a ### -<short description>. Contributed by [@<user>](https://github.com/<user>) [#<pr>](https://github.com/backstage/backstage/pull/<pr>) +<short description>. Contributed by [@<user>](https://github.com/<user>) in [#<pr>](https://github.com/backstage/backstage/pull/<pr>) ## Security Fixes diff --git a/docs/releases/v1.19.0-changelog.md b/docs/releases/v1.19.0-changelog.md new file mode 100644 index 0000000000..7397ccdba7 --- /dev/null +++ b/docs/releases/v1.19.0-changelog.md @@ -0,0 +1,3632 @@ +# Release v1.19.0 + +## @backstage/cli@0.23.0 + +### Minor Changes + +- 8defbd5434: Update typescript-eslint to 6.7.x, adding compatibility with TypeScript 5.2. + + This includes a major update on typescript-eslint, you can see the details in the [release notes](https://typescript-eslint.io/blog/announcing-typescript-eslint-v6/). + +- 7077dbf131: **BREAKING** The new backend start command that used to be enabled by setting `EXPERIMENTAL_BACKEND_START` is now the default. To revert to the old behavior set `LEGACY_BACKEND_START`, which is recommended if you haven't migrated to the new backend system. + + This new command is no longer based on Webpack, but instead uses Node.js loaders to transpile on the fly. Rather than hot reloading modules the entire backend is now restarted on change, but the SQLite database state is still maintained across restarts via a parent process. + +### Patch Changes + +- 9468a67b92: In frontend builds and tests `process.env.HAS_REACT_DOM_CLIENT` will now be defined if `react-dom/client` is present, i.e. if using React 18. This allows for conditional imports of `react-dom/client`. + +- 68158034e8: Fix for the new backend `start` command to make it work on Windows. + +- 4f16e60e6d: Request slightly smaller pages of data from GitHub + +- 21cd3b1b24: Added a template for creating `node-library` packages with `yarn new`. + +- d0f26cfa4f: Fixed an issue where the new backend start command would not gracefully shut down the backend process on Windows. + +- 1ea20b0be5: Updated dependency `@typescript-eslint/eslint-plugin` to `6.7.5`. + +- 2ef6522552: Support for the `.icon.svg` extension has been deprecated and will be removed in the future. The implementation of this extension is too tied to a particular version of MUI and the SVGO, and it makes it harder to evolve the build system. We may introduce the ability to reintroduce this kind of functionality in the future through configuration for use in internal plugins, but for now we're forced to remove it. + + To migrate existing code, rename the `.icon.svg` file to `.tsx` and replace the `<svg>` element with `<SvgIcon>` from MUI and add necessary imports. For example: + + ```tsx + import React from 'react'; + import SvgIcon from '@material-ui/core/SvgIcon'; + import { IconComponent } from '@backstage/core-plugin-api'; + + export const CodeSceneIcon = (props: SvgIconProps) => ( + <SvgIcon {...props}> + <g> + <path d="..." /> + </g> + </SvgIcon> + ); + ``` + +- b9ec93430e: The scaffolder-module template now recommends usage of `createMockDirectory` instead of `mock-fs`. + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. + +- 425203f898: Fixed recursive reloading issues of the backend, caused by unwanted watched files. + +- 3ef18f8c06: Explicitly set `exports: 'named'` for CJS builds, ensuring that they have e.g. `exports["default"] = catalogPlugin;` + +- 7187f2953e: The experimental package discovery will now always use the package name for include and exclude filtering, rather than the full module id. Entries pointing to a subpath export will now instead have an `export` field specifying the subpath that the import is from. + +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.1.5 + - @backstage/config@1.1.1 + - @backstage/eslint-plugin@0.1.3 + - @backstage/release-manifests@0.0.10 + - @backstage/types@1.1.1 + +## @backstage/core-app-api@1.11.0 + +### Minor Changes + +- c9d9bfeca2: URL encode some well known unsafe characters in `RouteResolver` (and therefore `useRouteRef`) + +### Patch Changes + +- 29e4d8b76b: Fixed bug in `AppRouter` to determine the correct `signOutTargetUrl` if `app.baseUrl` contains a `basePath` +- acca17e91a: Wrap entire app in `<Suspense>`, enabling support for using translations outside plugins. +- 1a0616fa10: Add missing resource and template app icons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- f1b349cfba: Fixed a bug in `TranslationApi` implementation where in some cases it wouldn't notify subscribers of language changes. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/version-bridge@1.0.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/core-plugin-api@1.7.0 + +### Minor Changes + +- 322bbcae24: Removed the exprimental plugin configuration API. The `__experimentalReconfigure()` from the plugin options as well as the `__experimentalConfigure()` method on plugin instances have both been removed. + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/version-bridge@1.0.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/e2e-test-utils@0.1.0 + +### Minor Changes + +- f5b41b27a9: Initial release. + +## @backstage/frontend-app-api@0.2.0 + +### Minor Changes + +- 4461d87d5a: Removed support for the new `useRouteRef`. +- 9d03dfe5e3: The `createApp` config option has been replaced by a new `configLoader` option. There is now also a `pluginLoader` option that can be used to dynamically load plugins into the app. +- d7c5d80c57: The hidden `'root'` extension has been removed and has instead been made an input of the `'core'` extension. The checks for rejecting configuration of the `'root'` extension to rejects configuration of the `'core'` extension instead. +- d920b8c343: Added support for installing `ExtensionOverrides` via `createApp` options. As part of this change the `plugins` option has been renamed to `features`, and the `pluginLoader` has been renamed to `featureLoader`. + +### Patch Changes + +- 322bbcae24: Internal update for removal of experimental plugin configuration API. +- f78ac58f88: Filters for discovered packages are now also applied at runtime. This makes it possible to disable packages through the `app.experimental.packages` config at runtime. +- 68ffb9e67d: The app will now reject any extensions that attach to nonexistent inputs. +- 5072824817: Implement `toString()` and `toJSON()` for extension instances. +- 1e60a9c3a5: Fixed an issue preventing the routing system to match subroutes +- 52366db5b3: Make themes configurable through extensions, and switched default themes to use extensions instead. +- 2ecd33618a: Added the `bindRoutes` option to `createApp`. +- e5a2956dd2: Register default api implementations when creating declarative integrated apps. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 06432f900c: Updates for `at` -> `attachTo` refactor. +- 1718ec75b7: Added support for the existing routing system. +- 66d51a4827: Prevents root extension override and duplicated plugin extensions. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/plugin-graphiql@0.2.55 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/frontend-plugin-api@0.2.0 + +### Minor Changes + +- 06432f900c: Extension attachment point is now configured via `attachTo: { id, input }` instead of `at: 'id/input'`. +- 4461d87d5a: Removed support for the new `useRouteRef`. + +### Patch Changes + +- d3a37f55c0: Add support for `SidebarGroup` on the sidebar item extension. +- 2ecd33618a: Plugins can now be assigned `routes` and `externalRoutes` when created. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- c1e9ca6500: Added `createExtensionOverrides` which can be used to install a collection of extensions in an app that will replace any existing ones. +- 52366db5b3: Added `createThemeExtension` and `coreExtensionData.theme`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/types@1.1.1 + +## @techdocs/cli@1.6.0 + +### Minor Changes + +- d06b30b050: Add possibility to use a mkdocs config file with a different name than `mkdocs.<yaml|yml> with the serve command using the `--mkdocs-config-file-name\` argument + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- 2b6e572051: Restructured tests. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-techdocs-node@1.9.0 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.0 + +### Minor Changes + +- 6f142d5356: **BREAKING** `gcpIapAuthenticator.initialize()` is no longer `async` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/types@1.1.1 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.1.0 + +### Minor Changes + +- 2d8f7e82c1: Migrated the Microsoft auth provider to new `@backstage/plugin-auth-backend-module-microsoft-provider` module package. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.1.0 + +### Minor Changes + +- ae34255836: Add new Pinniped auth module and authenticator to be used alongside the new Pinniped auth provider. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-auth-node@0.4.0 + +### Minor Changes + +- 6f142d5356: **BREAKING**: The recently introduced `ProxyAuthenticator.initialize()` method is no longer `async` to match the way the OAuth equivalent is implemented. + +### Patch Changes + +- 6c2b0793bf: Fix for persisted scopes not being properly restored on sign-in. +- 8b8b1d23ae: Fixed cookie persisted scope not returned in OAuth refresh handler response. +- ae34255836: Adding optional audience parameter to OAuthState type declaration +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog@1.14.0 + +### Minor Changes + +- 28f1ab2e1a: The catalog plugin no longer implements the experimental reconfiguration API. The create button title can now instead be configured using the new experimental internationalization API, via the `catalogTranslationRef` exported at `/alpha`. For example: + + ```ts + import { catalogTranslationRef } from '@backstage/plugin-catalog/alpha'; + + const app = createApp({ + __experimentalTranslations: { + resources: [ + createTranslationMessages({ + ref: catalogTranslationRef, + catalog_page_create_button_title: 'Create Software', + }), + ], + }, + }); + ``` + +- f3561a2935: include owner chip in catalog search result item + +### Patch Changes + +- 7c4a8e4d5f: Create an experimental `CatalogSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- 0296f272b4: The \`spec.lifecycle' field in entities will now always be rendered as a string. +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- e5a2956dd2: Migrate catalog api to declarative integration system, it is exported from `/alpha` subpath. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-scaffolder-common@1.4.2 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-catalog-backend@1.14.0 + +### Minor Changes + +- 78af9433c8: Instrumenting some missing metrics with `OpenTelemetry` + +### Patch Changes + +- 7a2e2924c7: Marked the `LocationEntityProcessor` as deprecated, as it is no longer used internally since way back and can even be harmful at this point. +- 0b55f773a7: Removed some unused dependencies +- 348e8c1cdb: Fixes a bug where eagerly deleted entities did not properly trigger re-stitching of entities that they had relations to. +- b97e9790f0: Internal refactors, laying the foundation for later introducing deferred stitching (see #18062). +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-openapi-utils@0.0.5 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-module-catalog@0.1.10 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-catalog-backend-module-aws@0.3.0 + +### Minor Changes + +- 5abc2fd4d6: AwsEksClusterProcessor supports Entity callback function and passes in region when initialize EKS cluster + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-catalog-backend-module-github-org@0.1.0 + +### Minor Changes + +- c101e683d5: Added `catalogModuleGithubOrgEntityProvider` to ingest users and teams from multiple Github organizations. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-backend-module-github@0.4.4 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-catalog-graphql@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 + +## @backstage/plugin-graphql-backend@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 + +## @backstage/plugin-jenkins@0.9.0 + +### Minor Changes + +- 411896faf9: Added JobRunTable Component. + Added new Route and extended Api to get buildJobs. + Actions column has a new icon button, clicking on which takes us to page where we + can see all the job runs. + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 1a05cf34f6: Extend EntityJenkinsContent to receive columns as prop +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-jenkins-common@0.1.20 + +## @backstage/plugin-jenkins-backend@0.3.0 + +### Minor Changes + +- 411896faf9: Added JobRunTable Component. + Added new Route and extended Api to get buildJobs. + Actions column has a new icon button, clicking on which takes us to page where we + can see all the job runs. + +### Patch Changes + +- 930ac236d8: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-jenkins-common@0.1.20 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-kubernetes@0.11.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- b0aca1a798: Updated dependency `xterm-addon-attach` to `^0.9.0`. + Updated dependency `xterm-addon-fit` to `^0.8.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-react@0.1.0 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-kubernetes-backend@0.13.0 + +### Minor Changes + +- ae943c3bb1: **BREAKING** Allow passing undefined `labelSelector` to `KubernetesFetcher` + + `KubernetesFetch` no longer auto-adds `labelSelector` when empty string was passed. + This is only applicable if you have custom ObjectProvider implementation, as build-in `KubernetesFanOutHandler` already does this + +### Patch Changes + +- cbb0e3c3f4: A new plugin has been introduced to house the extension points for Kubernetes backend plugin; at the moment only the `KubernetesObjectsProviderExtensionPoint` is present. The `kubernetes-backend` plugin was modified to use this new extension point. +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-node@0.1.0 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-kubernetes-common@0.7.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-kubernetes-node@0.1.0 + +### Minor Changes + +- cbb0e3c3f4: A new plugin has been introduced to house the extension points for Kubernetes backend plugin; at the moment only the `KubernetesObjectsProviderExtensionPoint` is present. The `kubernetes-backend` plugin was modified to use this new extension point. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-kubernetes-react@0.1.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- 4262e12921: Handle mixed decimals and bigint when calculating k8s resource usage +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-newrelic-dashboard@0.3.0 + +### Minor Changes + +- d7eba6cab4: Changes in `newrelic-dashboard` plugin: + + - Make DashboardSnapshotList component public + - Settle discrepancies in the exported API + - Deprecate DashboardSnapshotComponent + +- e605ea4906: Add storybook for newrelic-dashboard plugin. + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 61d55942ae: Fix the styles for NewRelicDashboard, add more responsiveness +- 5194a51a1c: Fixed React Warning: "Each child in a list should have a unique 'key' prop" during the rendering of `EntityNewRelicDashboardCard` +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/plugin-scaffolder-backend@1.18.0 + +### Minor Changes + +- dea0aafda7: Updated `publish:gitlab` action properties to support additional Gitlab project settings: + + - general project settings provided by gitlab project create API (new `settings` property) + - branch level settings to create additional branches and make them protected (new `branches` property) + - project level environment variables settings (new `projectVariables` property) + + Marked existed properties `repoVisibility` and `topics` as deprecated, as they are covered by `settings` property. + +- f41099bb31: Display meaningful error to the output if Gitlab namespace not found inside `publish:gitlab`. + +### Patch Changes + +- 7dd82cc07e: Add examples for `github:issues:label` scaffolder action & improve related tests +- 733ddf7130: Add examples for `publish:Azure` scaffolder action. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-scaffolder-common@1.4.2 + +## @backstage/plugin-techdocs@1.8.0 + +### Minor Changes + +- 27740caa2d: Added experimental support for declarative integration via the `/alpha` subpath. + +### Patch Changes + +- 4918f65ab2: Create an experimental `TechDocsSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- 3605370af6: Improved `DocsTable` to display pagination controls dynamically, appearing only when needed. +- 0296f272b4: The \`spec.lifecycle' field in entities will now always be rendered as a string. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 9468a67b92: Added support for React 18. The new `createRoot` API from `react-dom/client` will now be used if present. +- df449a7a31: Add kind column by default to TechDocsTable +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-techdocs-backend@1.8.0 + +### Minor Changes + +- 344cfbcfbc: Allow prepared directory clean up for custom preparers + + When using custom preparer for TechDocs, the `preparedDir` might + end up taking disk space. This requires all custom preparers to + implement a new method `shouldCleanPreparedDirectory` which indicates + whether the prepared directory should be cleaned after generation. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-techdocs-node@1.9.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-module-techdocs@0.1.10 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-techdocs-node@1.9.0 + +### Minor Changes + +- 344cfbcfbc: Allow prepared directory clean up for custom preparers + + When using custom preparer for TechDocs, the `preparedDir` might + end up taking disk space. This requires all custom preparers to + implement a new method `shouldCleanPreparedDirectory` which indicates + whether the prepared directory should be cleaned after generation. + +- d06b30b050: Add possibility to use a mkdocs config file with a different name than `mkdocs.<yaml|yml> with the serve command using the `--mkdocs-config-file-name\` argument + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/app-defaults@1.4.4 + +### Patch Changes + +- 1a0616fa10: Add missing resource and template app icons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + +## @backstage/backend-app-api@0.5.6 + +### Patch Changes + +- 74491c9602: Moved `HostDiscovery` from `@backstage/backend-common`. +- a4617c422a: Added `watch` option to configuration loaders that can be used to disable file watching by setting it to `false`. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/cli-node@0.1.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/backend-common@0.19.8 + +### Patch Changes + +- 74491c9602: The `HostDiscovery` export has been deprecated, import it from `@backstage/backend-app-api` instead. +- b95d66d4ea: Properly close write stream when writing temporary archive for processing zip-based `.readTree()` responses. +- b94f32271e: Added the ability to fetch git tags through the `Git` class. This is useful for scaffolder actions that want to take action based on tag versions in a cloned repository +- 0b55f773a7: Removed some unused dependencies +- 4c39e38f1e: Added `/testUtils` entry point, with a utility for mocking resolve package paths as returned by `resolvePackagePath`. +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- a250ad775f: Removed `mock-fs` dev dependency. +- 2a40cd46a8: Adds the optional flag for useRedisSets for the Redis cache to the config. +- 1c3d6fa2b2: The `useHotCleanup` and `useHotMemoize` helpers are now deprecated, since hot module reloads for backend are being phased out. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/backend-dev-utils@0.1.2 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-app-api@0.5.6 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/types@1.1.1 + +## @backstage/backend-defaults@0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-app-api@0.5.6 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/backend-dev-utils@0.1.2 + +### Patch Changes + +- afa48341fb: Fix an issue where early IPC responses would be lost. + +## @backstage/backend-openapi-utils@0.0.5 + +### Patch Changes + +- 7c83975531: Adds new public utility types for common OpenAPI values, like request and response shapes and parameters available on an endpoint. + + **deprecated** `internal` namespace + The internal namespace will continue to be exported but now uses OpenAPI format for path parameters. You should use the new utility types. + +- Updated dependencies + - @backstage/errors@1.2.3 + +## @backstage/backend-plugin-api@0.6.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/backend-tasks@0.5.11 + +### Patch Changes + +- 5db102bfdf: Instrument `backend-tasks` with some counters and histograms for duration. + + `backend_tasks.task.runs.count`: Counter with the total number of times a task has been run. + `backend_tasks.task.runs.duration`: Histogram with the run durations for each task. + + Both these metrics have come with `result` `taskId` and `scope` labels for finer grained grouping. + +- ddd76ac98d: Fix bug where backend tasks that are defined with HumanDuration are immediately triggered on application startup + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/backend-test-utils@0.2.7 + +### Patch Changes + +- a250ad775f: Added `createMockDirectory()` to help out with file system mocking in tests. +- 5ddc03813e: Remove third type parameter used for `MockInstance`, in order to be compatible with older versions of `@types/jest`. +- 74491c9602: Updated to import `HostDiscovery` from `@backstage/backend-app-api`. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-app-api@0.5.6 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/catalog-client@1.4.5 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## @backstage/catalog-model@1.4.3 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/cli-common@0.1.13 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. + +## @backstage/cli-node@0.1.5 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/types@1.1.1 + +## @backstage/codemods@0.1.46 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- Updated dependencies + - @backstage/cli-common@0.1.13 + +## @backstage/config@1.1.1 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## @backstage/config-loader@1.5.1 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 30c553c1d2: Updated dependency `typescript-json-schema` to `^0.61.0`. +- 773ea341d2: The `FileConfigSource` will now retry file reading after a short delay if it reads an empty file. This is to avoid flakiness during watch mode where change events can trigger before the file content has been written. +- a4617c422a: Added `watch` option to configuration loaders that can be used to disable file watching by setting it to `false`. +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/core-components@0.13.6 + +### Patch Changes + +- 4eab5cf901: The `TabbedLayout` component will now also navigate when clicking the active tab, which allows for navigation back from any sub routes. +- 0b55f773a7: Removed some unused dependencies +- 8a15360bb4: Fixed overflowing messages in `WarningPanel`. +- 997a71850c: Changed SupportButton menuitems to support text wrap +- 0296f272b4: Fixed the type declaration of `DependencyGraphProps`, the `defs` prop now expects `JSX.Element`s. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 16126dbe6a: Change overlay header colors in the mobile menu to use navigation color from the theme +- d19a827ef1: MissingAnnotationEmptyState component can now dynamically generate a YAML example based off the current entity being used. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/create-app@0.5.6 + +### Patch Changes + +- ba6a3b59c1: Removed duplicate `apple-touch-icon` link from `packages/app/public/index.html` that linked to nonexistent icon. + +- c8ec0dea4a: Create unique temp directory for each `create-app` execution. + +- e43d3eb1b7: Bumped create-app version. + +- b665f2ce65: Change base node image from node:18-bullseye-slim to node:18-bookworm-slim due to Docker build error on bullseye. + + You can apply these change to your own `Dockerfile` by replacing `node:18-bullseye-slim` with `node:18-bookworm-slim` + +- deed089a3d: Bump `cypress` to fix the end-to-end tests + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. + +- 04a3f65e15: Bump Docker base images to `node:18-bookworm-slim` to fix node compatibility issues raised during image build. + + You can apply these change to your own `Dockerfile` by replacing `node:16-bullseye-slim` with `node:18-bookworm-slim` + +- 9864f263ba: Bump dev dependencies `lerna@7.3.0` on the template + +- 5eacd5d213: The E2E test setup based on Cypress has been replaced with one based on [Playwright](https://playwright.dev/). Migrating existing apps is not required as this is a standalone setup, only do so if you also want to switch from Cypress to Playwright. + + The scripts to run the E2E tests have been removed from `packages/app/package.json`, as they are now instead run from the root. Instead, a new script has been added to the root `package.json`, `yarn test:e2e`, which runs the E2E tests in development mode, unless `CI` is set in the environment. + + The Playwright setup uses utilities from the new `@backstage/e2e-test-utils` package to find and include all packages in the monorepo that have an `e2e-tests` folder. + +- 8d2e640af4: Added missing `.eslintignore` file + + To apply this change to an existing app, create a new `.eslintignore` file at the root of your project with the following content: + + ```diff + + playwright.config.ts + ``` + +- Updated dependencies + - @backstage/cli-common@0.1.13 + +## @backstage/dev-utils@1.0.22 + +### Patch Changes + +- 080d1beb2a: Moving development `dependencies` to `devDependencies` +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 9468a67b92: Added support for React 18. The new `createRoot` API from `react-dom/client` will now be used if present. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/app-defaults@1.4.4 + - @backstage/theme@0.4.3 + +## @backstage/errors@1.2.3 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/types@1.1.1 + +## @backstage/integration@1.7.1 + +### Patch Changes + +- 3963d0b885: Ensure that all relevant config fields are properly marked as secret +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/config@1.1.1 + +## @backstage/integration-aws-node@0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + +## @backstage/integration-react@1.1.20 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/config@1.1.1 + +## @backstage/repo-tools@0.3.5 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.1.5 + +## @backstage/test-utils@1.4.4 + +### Patch Changes + +- 322bbcae24: Removed the alpha `MockPluginProvider` export since the plugin configuration API has been removed. +- 1a0616fa10: Add missing resource and template app icons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/theme@0.4.3 + +### Patch Changes + +- 5ad5344756: Added support for string `fontSize` values (e.g. `"2.5rem"`) in themes in addition to numbers. Also added an optional `fontFamily` prop for header typography variants to allow further customization. + +## @backstage/version-bridge@1.0.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. + +## @backstage/plugin-adr@0.6.8 + +### Patch Changes + +- 499e34656e: Fix icon alignment in `AdrSearchResultListItem` +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 1204e7628e: Create an experimental `AdrSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/theme@0.4.3 + - @backstage/plugin-adr-common@0.2.16 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-adr-backend@0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-adr-common@0.2.16 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-adr-common@0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-airbrake@0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/test-utils@1.4.4 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/dev-utils@1.0.22 + - @backstage/theme@0.4.3 + +## @backstage/plugin-airbrake-backend@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-allure@0.1.41 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-analytics-module-ga@0.1.34 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-analytics-module-ga4@0.1.5 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-analytics-module-newrelic-browser@0.0.3 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-apache-airflow@0.2.16 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + +## @backstage/plugin-api-docs@0.9.12 + +### Patch Changes + +- 0117a6b47e: Adding `requestInterceptor` option to `api-docs` and pass it to SwaggerUI. This will enable to configure a proxy or headers to be sent to all the request made through the `Try it out` button on SwaggerUI. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 18f1756908: added aria-label on api definition button for better a11y. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-api-docs-module-protoc-gen-doc@0.1.4 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. + +## @backstage/plugin-apollo-explorer@0.1.16 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-app-backend@0.3.54 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config-loader@1.5.1 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-app-node@0.1.6 + +## @backstage/plugin-app-node@0.1.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-auth-backend@0.19.3 + +### Patch Changes + +- 9ff7935152: Fixed bug in oidc refresh handler, if token endpoints response on refresh request does not contain a scope, the requested scope is used. +- 2d8f7e82c1: Migrated the Microsoft auth provider to new `@backstage/plugin-auth-backend-module-microsoft-provider` module package. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-backend-module-github-provider@0.1.3 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.0 + - @backstage/plugin-auth-backend-module-microsoft-provider@0.1.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.3 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-backend-module-google-provider@0.1.3 + +## @backstage/plugin-auth-backend-module-github-provider@0.1.3 + +### Patch Changes + +- 5d32a58b5a: Fixed a bug where the GitHub authenticator did not properly persist granted OAuth scopes. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-auth-backend-module-google-provider@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-azure-devops@0.3.7 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-azure-devops-common@0.3.1 + +## @backstage/plugin-azure-devops-backend@0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-devops-common@0.3.1 + +## @backstage/plugin-azure-sites@0.1.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-azure-sites-common@0.1.1 + +## @backstage/plugin-azure-sites-backend@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-sites-common@0.1.1 + +## @backstage/plugin-badges@0.2.49 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-badges-backend@0.3.3 + +### Patch Changes + +- 817f2acbb1: Make sure the default badge factory is used if nothing is defined +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + +## @backstage/plugin-bazaar@0.2.17 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + +## @backstage/plugin-bazaar-backend@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-bitbucket-cloud-common@0.2.13 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1 + +## @backstage/plugin-bitrise@0.1.52 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-catalog-backend-module-azure@0.1.25 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.21 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-bitbucket-cloud-common@0.2.13 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.21 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-bitbucket-cloud-common@0.2.13 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.19 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-catalog-backend-module-gcp@0.1.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.22 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-catalog-backend-module-github@0.4.4 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- 0b55f773a7: Removed some unused dependencies +- 4f16e60e6d: Request slightly smaller pages of data from GitHub +- b4b1cbf9fa: Make `defaultUserTransformer` resolve to `UserEntity` instead of `Entity` +- c101e683d5: Removed `catalogModuleGithubOrgEntityProvider`. Import from `@backstage/plugin-catalog-backend-module-github-org` instead. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-catalog-backend-module-gitlab@0.3.3 + +### Patch Changes + +- 4f70fdfc93: fix: use REST API to get root group memberships for GitLab SaaS users listing + + This API is the only one that shows `email` field for enterprise users and + allows to filter out bot users not using a license using the `is_using_seat` + field. + + We also added the annotation `gitlab.com/saml-external-uid` taking the value + of `group_saml_identity.extern_uid` of the `groups/:group-id/members` endpoint + response. This is useful in case you want to create a `SignInResolver` that + references the user with the id of your identity provider (e.g. OneLogin). + + ref: + + <https://docs.gitlab.com/ee/user/enterprise_user/#get-users-email-addresses-through-the-api> + <https://docs.gitlab.com/ee/api/members.html#limitations> + +- 890e3b5ad4: Make sure to include the error message when ingestion fails + +- 0b55f773a7: Removed some unused dependencies + +- 6ae7f12abb: Make sure the archived projects are skipped with the Gitlab API + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.4.10 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.21 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.13 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.23 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.11 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-scaffolder-common@1.4.2 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-catalog-common@1.0.17 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-catalog-graph@0.2.37 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-import@0.10.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: The `app.title` configuration is now properly required to be a string. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-catalog-node@1.4.7 + +### Patch Changes + +- 7a2e2924c7: Added docs to `processingResult` +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-catalog-react@1.8.5 + +### Patch Changes + +- a402e1dfb9: Fixed an issue causing `EntityPage` to show an error for entities containing special characters +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: The `spec.type` field in entities will now always be rendered as a string. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.6 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-catalog-unprocessed-entities@0.1.4 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-cicd-statistics@0.1.27 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.21 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-cicd-statistics@0.1.27 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-circleci@0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-cloudbuild@0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-code-climate@0.1.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-code-coverage@0.2.18 + +### Patch Changes + +- 88b0b32547: Fixed the coverage history statistics to compare newest with oldest record +- 0296f272b4: The warning for missing code coverage will now render the entity as a reference. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- a468544fa9: Updated layout to improve contrasts and consistency with other plugins +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-code-coverage-backend@0.2.20 + +### Patch Changes + +- 4aa27aa200: Added option to set body size limit +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + +## @backstage/plugin-codescene@0.1.18 + +### Patch Changes + +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-config-schema@0.1.46 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-cost-insights@0.12.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- ba4820883c: Updated dependency `@types/pluralize` to `^0.0.31`. +- 959aa2a09f: The experimental plugin configuration has been removed. The trend line can now instead be hidden by setting `costInsights.hideTrendLine` to `true` in the configuration. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-cost-insights-common@0.1.2 + +## @backstage/plugin-devtools@0.1.5 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.5 + +## @backstage/plugin-devtools-backend@0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.5 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-devtools-common@0.1.5 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-dynatrace@7.0.5 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-entity-feedback@0.2.8 + +### Patch Changes + +- 48c8b93e98: Added tooltip to like dislike buttons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-feedback-backend@0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-validation@0.1.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/plugin-catalog-common@1.0.17 + +## @backstage/plugin-events-backend@0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-backend-module-aws-sqs@0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-backend-module-azure@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-backend-module-gerrit@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-backend-module-github@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-backend-module-gitlab@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-backend-test-utils@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.15 + +## @backstage/plugin-events-node@0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + +## @backstage/plugin-explore@0.4.11 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0f10c53a05: Create an experimental `ExploreSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-explore-react@0.0.32 + - @backstage/theme@0.4.3 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-explore-backend@0.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-search-backend-module-explore@0.1.10 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-explore-react@0.0.32 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-explore-common@0.0.2 + +## @backstage/plugin-firehydrant@0.2.9 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-fossa@0.2.57 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-gcalendar@0.3.19 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-gcp-projects@0.3.42 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-git-release-manager@0.3.38 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-github-actions@0.6.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-github-deployments@0.1.56 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-github-issues@0.2.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 7bd0a8ab3c: Filters out entities that belonged to a different github instance other than the one configured by the plugin +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-github-pull-requests-board@0.1.19 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-gitops-profiles@0.3.41 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-gocd@0.1.31 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-graphiql@0.2.55 + +### Patch Changes + +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- 06432f900c: Updated `/alpha` exports to use new `attachTo` option. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-graphql-voyager@0.1.8 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-home@0.5.9 + +### Patch Changes + +- f997f771da: Adds Top/Recently Visited components to homepage +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-home-react@0.1.4 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-home-react@0.1.4 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + +## @backstage/plugin-ilert@0.2.14 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-jenkins-common@0.1.20 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-kafka@0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-kafka-backend@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-kubernetes-cluster@0.0.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-react@0.1.0 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-lighthouse@0.4.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4 + +## @backstage/plugin-lighthouse-backend@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4 + +## @backstage/plugin-lighthouse-common@0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + +## @backstage/plugin-linguist@0.1.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-linguist-backend@0.5.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-microsoft-calendar@0.1.8 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-newrelic@0.3.41 + +### Patch Changes + +- ce50a15506: Fixed sorting and searching in the NewRelic table. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-nomad@0.1.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-nomad-backend@0.1.8 + +### Patch Changes + +- 6822918c50: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-octopus-deploy@0.2.7 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-opencost@0.2.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 777b9a16a4: Fix for broken image reference. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-org@0.6.15 + +### Patch Changes + +- dc5b6b971b: Fixed the display of OwnershipCard with aggregated relations by loading relations when getting children of entity. + This allows the already existing recursive method to work properly when children of entity have children themselves. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-org-react@0.1.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + +## @backstage/plugin-pagerduty@0.6.6 + +### Patch Changes + +- b9ce306814: Minor fix to avoid usage of deprecated prop +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-home-react@0.1.4 + - @backstage/theme@0.4.3 + +## @backstage/plugin-periskop@0.1.23 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-periskop-backend@0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-permission-backend@0.5.29 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-permission-common@0.7.9 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-permission-node@0.7.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-permission-react@0.4.16 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-playlist@0.1.17 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 65498193e8: Updated Playlist read me with additional screenshots +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-playlist-common@0.1.11 + +## @backstage/plugin-playlist-backend@0.3.10 + +### Patch Changes + +- 9e46f5ff49: Added support to the playlist plugin for the new backend +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-playlist-common@0.1.11 + +## @backstage/plugin-playlist-common@0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-proxy-backend@0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-puppetdb@0.1.8 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-rollbar@0.4.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-rollbar-backend@0.1.51 + +### Patch Changes + +- 407f4284be: ensure rollbar token is hidden +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + +## @backstage/plugin-scaffolder@1.15.1 + +### Patch Changes + +- b337d78c3b: fixed issue related template editor fails with multiple templates per file. +- ff2ab02690: Make entity picker more reliable with only one available entity +- 83e4a42ccd: Display log visibility button on the template panel +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 4c70fe497d: `RepoUrlPickerRepoName` now correctly handles value changes in allowed repos. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/plugin-scaffolder-react@1.5.6 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-scaffolder-common@1.4.2 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.30 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.23 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.14 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.27 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-common@1.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-scaffolder-node@0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.2 + +## @backstage/plugin-scaffolder-react@1.5.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.2 + +## @backstage/plugin-search@1.4.1 + +### Patch Changes + +- e5a2956dd2: Create an experimental search plugin that is compatible with the declarative integration system, it is exported from `/alpha` subpath. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: Minor internal code cleanup. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-backend@1.4.6 + +### Patch Changes + +- 16be6f9473: Set the default length limit to search query to 100. To override it, define `search.maxTermLength` in the config file. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-openapi-utils@0.0.5 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-backend-module-catalog@0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-backend-module-elasticsearch@1.3.9 + +### Patch Changes + +- 3963d0b885: Ensure that all relevant config fields are properly marked as secret +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-backend-module-explore@0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/config@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-backend-module-pg@0.5.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-backend-module-techdocs@0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-techdocs-node@1.9.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-backend-node@1.2.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-search-common@1.2.7 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/plugin-search-react@1.7.1 + +### Patch Changes + +- 06432f900c: Updated `/alpha` exports to use new `attachTo` option. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: The filter options passed to `SearchResultGroupLayout` are now always explicitly rendered as strings by default. +- 703a4ffc5b: Create `createSearchResultListItem` alpha version that only supports declarative integration. +- Updated dependencies + - @backstage/frontend-app-api@0.2.0 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-sentry@0.5.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-shortcuts@0.3.15 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-sonarqube@0.7.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-sonarqube-react@0.1.9 + +## @backstage/plugin-sonarqube-backend@0.2.8 + +### Patch Changes + +- a5d592d0ad: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-sonarqube-react@0.1.9 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + +## @backstage/plugin-splunk-on-call@0.4.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-stack-overflow@0.1.21 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-home-react@0.1.4 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-stack-overflow-backend@0.2.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## @backstage/plugin-stackstorm@0.1.7 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-tech-insights@0.3.17 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 21f409d776: Export `ScorecardInfo` and `ScorecardsList` components to be able to use manually queried check results directly. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-backend@0.5.20 + +### Patch Changes + +- cc7dddfa7f: Increase the maximum allowed length of an entity filter for tech insights fact schemas. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-tech-insights-node@0.4.12 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.38 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/plugin-tech-insights-node@0.4.12 + - @backstage/config@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-node@0.4.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-radar@0.6.9 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- c09d2fa1d6: Added experimental support for the declarative integration. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.22 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog@1.14.0 + - @backstage/test-utils@1.4.4 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + +## @backstage/plugin-techdocs-react@1.1.12 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/version-bridge@1.0.6 + - @backstage/config@1.1.1 + +## @backstage/plugin-todo@0.2.28 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-todo-backend@0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-openapi-utils@0.0.5 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + +## @backstage/plugin-user-settings@0.7.11 + +### Patch Changes + +- 18c8dee6f5: Added experimental support for declarative integration via the `/alpha` subpath. +- d1b637d005: Fixed a bug where the theme icons would not be colored according to their active state. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + +## @backstage/plugin-user-settings-backend@0.2.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/types@1.1.1 + +## @backstage/plugin-vault@0.1.20 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## @backstage/plugin-vault-backend@0.3.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + +## @backstage/plugin-xcmetrics@0.2.44 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## example-app@0.2.88 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.2.0 + - @backstage/plugin-pagerduty@0.6.6 + - @backstage/plugin-org@0.6.15 + - @backstage/plugin-code-coverage@0.2.18 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-home@0.5.9 + - @backstage/plugin-newrelic@0.3.41 + - @backstage/plugin-user-settings@0.7.11 + - @backstage/plugin-scaffolder@1.15.1 + - @backstage/core-components@0.13.6 + - @backstage/plugin-entity-feedback@0.2.8 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-tech-radar@0.6.9 + - @backstage/plugin-adr@0.6.8 + - @backstage/app-defaults@1.4.4 + - @backstage/plugin-graphiql@0.2.55 + - @backstage/plugin-search@1.4.1 + - @backstage/plugin-jenkins@0.9.0 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-api-docs@0.9.12 + - @backstage/plugin-kubernetes@0.11.0 + - @backstage/plugin-airbrake@0.3.25 + - @backstage/plugin-apache-airflow@0.2.16 + - @backstage/plugin-azure-devops@0.3.7 + - @backstage/plugin-azure-sites@0.1.14 + - @backstage/plugin-badges@0.2.49 + - @backstage/plugin-catalog-graph@0.2.37 + - @backstage/plugin-catalog-import@0.10.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4 + - @backstage/plugin-circleci@0.3.25 + - @backstage/plugin-cloudbuild@0.3.25 + - @backstage/plugin-cost-insights@0.12.14 + - @backstage/plugin-devtools@0.1.5 + - @backstage/plugin-dynatrace@7.0.5 + - @backstage/plugin-explore@0.4.11 + - @backstage/plugin-gcalendar@0.3.19 + - @backstage/plugin-gcp-projects@0.3.42 + - @backstage/plugin-github-actions@0.6.6 + - @backstage/plugin-gocd@0.1.31 + - @backstage/plugin-kafka@0.3.25 + - @backstage/plugin-kubernetes-cluster@0.0.1 + - @backstage/plugin-lighthouse@0.4.10 + - @backstage/plugin-linguist@0.1.10 + - @backstage/plugin-microsoft-calendar@0.1.8 + - @backstage/plugin-newrelic-dashboard@0.3.0 + - @backstage/plugin-nomad@0.1.6 + - @backstage/plugin-octopus-deploy@0.2.7 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/plugin-playlist@0.1.17 + - @backstage/plugin-puppetdb@0.1.8 + - @backstage/plugin-rollbar@0.4.25 + - @backstage/plugin-scaffolder-react@1.5.6 + - @backstage/plugin-sentry@0.5.10 + - @backstage/plugin-shortcuts@0.3.15 + - @backstage/plugin-stack-overflow@0.1.21 + - @backstage/plugin-stackstorm@0.1.7 + - @backstage/plugin-tech-insights@0.3.17 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/plugin-todo@0.2.28 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.7 + +## example-app-next@0.0.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.2.0 + - @backstage/plugin-pagerduty@0.6.6 + - @backstage/plugin-org@0.6.15 + - @backstage/plugin-code-coverage@0.2.18 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-home@0.5.9 + - @backstage/plugin-newrelic@0.3.41 + - @backstage/plugin-user-settings@0.7.11 + - @backstage/plugin-scaffolder@1.15.1 + - @backstage/core-components@0.13.6 + - @backstage/plugin-entity-feedback@0.2.8 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-tech-radar@0.6.9 + - @backstage/plugin-adr@0.6.8 + - @backstage/app-defaults@1.4.4 + - @backstage/plugin-graphiql@0.2.55 + - @backstage/plugin-search@1.4.1 + - @backstage/plugin-jenkins@0.9.0 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-api-docs@0.9.12 + - @backstage/plugin-kubernetes@0.11.0 + - @backstage/plugin-airbrake@0.3.25 + - @backstage/plugin-apache-airflow@0.2.16 + - @backstage/plugin-azure-devops@0.3.7 + - @backstage/plugin-azure-sites@0.1.14 + - @backstage/plugin-badges@0.2.49 + - @backstage/plugin-catalog-graph@0.2.37 + - @backstage/plugin-catalog-import@0.10.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4 + - @backstage/plugin-circleci@0.3.25 + - @backstage/plugin-cloudbuild@0.3.25 + - @backstage/plugin-cost-insights@0.12.14 + - @backstage/plugin-devtools@0.1.5 + - @backstage/plugin-dynatrace@7.0.5 + - @backstage/plugin-explore@0.4.11 + - @backstage/plugin-gcalendar@0.3.19 + - @backstage/plugin-gcp-projects@0.3.42 + - @backstage/plugin-github-actions@0.6.6 + - @backstage/plugin-gocd@0.1.31 + - @backstage/plugin-kafka@0.3.25 + - @backstage/plugin-lighthouse@0.4.10 + - @backstage/plugin-linguist@0.1.10 + - @backstage/plugin-microsoft-calendar@0.1.8 + - @backstage/plugin-newrelic-dashboard@0.3.0 + - @backstage/plugin-octopus-deploy@0.2.7 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/plugin-playlist@0.1.17 + - @backstage/plugin-puppetdb@0.1.8 + - @backstage/plugin-rollbar@0.4.25 + - @backstage/plugin-scaffolder-react@1.5.6 + - @backstage/plugin-sentry@0.5.10 + - @backstage/plugin-shortcuts@0.3.15 + - @backstage/plugin-stack-overflow@0.1.21 + - @backstage/plugin-stackstorm@0.1.7 + - @backstage/plugin-tech-insights@0.3.17 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/plugin-todo@0.2.28 + - @backstage/theme@0.4.3 + - app-next-example-plugin@0.0.2 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.7 + +## app-next-example-plugin@0.0.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-components@0.13.6 + +## example-backend@0.2.88 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-nomad-backend@0.1.8 + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-scaffolder-backend@1.18.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.9 + - @backstage/integration@1.7.1 + - @backstage/plugin-playlist-backend@0.3.10 + - @backstage/plugin-techdocs-backend@1.8.0 + - @backstage/plugin-auth-backend@0.19.3 + - @backstage/plugin-rollbar-backend@0.1.51 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/plugin-graphql-backend@0.2.0 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-badges-backend@0.3.3 + - @backstage/plugin-tech-insights-backend@0.5.20 + - @backstage/plugin-kubernetes-backend@0.13.0 + - @backstage/plugin-jenkins-backend@0.3.0 + - @backstage/plugin-code-coverage-backend@0.2.20 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.23 + - @backstage/plugin-search-backend@1.4.6 + - example-app@0.2.88 + - @backstage/plugin-lighthouse-backend@0.3.3 + - @backstage/plugin-linguist-backend@0.5.3 + - @backstage/plugin-search-backend-module-catalog@0.1.10 + - @backstage/plugin-search-backend-module-explore@0.1.10 + - @backstage/plugin-search-backend-module-techdocs@0.1.10 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/plugin-tech-insights-node@0.4.12 + - @backstage/plugin-adr-backend@0.4.3 + - @backstage/plugin-app-backend@0.3.54 + - @backstage/plugin-azure-devops-backend@0.4.3 + - @backstage/plugin-azure-sites-backend@0.1.16 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3 + - @backstage/plugin-devtools-backend@0.2.3 + - @backstage/plugin-entity-feedback-backend@0.2.3 + - @backstage/plugin-events-backend@0.2.15 + - @backstage/plugin-explore-backend@0.0.16 + - @backstage/plugin-kafka-backend@0.3.3 + - @backstage/plugin-permission-backend@0.5.29 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-proxy-backend@0.4.3 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.7 + - @backstage/plugin-search-backend-module-pg@0.5.15 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.38 + - @backstage/plugin-todo-backend@0.3.4 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.3 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## example-backend-next@0.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-nomad-backend@0.1.8 + - @backstage/backend-tasks@0.5.11 + - @backstage/plugin-sonarqube-backend@0.2.8 + - @backstage/plugin-scaffolder-backend@1.18.0 + - @backstage/plugin-playlist-backend@0.3.10 + - @backstage/plugin-techdocs-backend@1.8.0 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/plugin-badges-backend@0.3.3 + - @backstage/plugin-kubernetes-backend@0.13.0 + - @backstage/plugin-jenkins-backend@0.3.0 + - @backstage/plugin-search-backend@1.4.6 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-lighthouse-backend@0.3.3 + - @backstage/plugin-linguist-backend@0.5.3 + - @backstage/plugin-search-backend-module-catalog@0.1.10 + - @backstage/plugin-search-backend-module-explore@0.1.10 + - @backstage/plugin-search-backend-module-techdocs@0.1.10 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/backend-defaults@0.2.6 + - @backstage/plugin-adr-backend@0.4.3 + - @backstage/plugin-app-backend@0.3.54 + - @backstage/plugin-azure-devops-backend@0.4.3 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3 + - @backstage/plugin-devtools-backend@0.2.3 + - @backstage/plugin-entity-feedback-backend@0.2.3 + - @backstage/plugin-permission-backend@0.5.29 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.3 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-proxy-backend@0.4.3 + - @backstage/plugin-todo-backend@0.3.4 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.3 + - @backstage/plugin-permission-common@0.7.9 + +## @backstage/backend-plugin-manager@0.0.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/plugin-events-backend@0.2.15 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/cli-node@0.1.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## e2e-test@0.2.8 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.6 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + +## techdocs-cli-embedded-app@0.2.87 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/test-utils@1.4.4 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/app-defaults@1.4.4 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## @internal/plugin-todo-list@1.0.18 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## @internal/plugin-todo-list-backend@1.0.18 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## @internal/plugin-todo-list-common@1.0.14 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.9 diff --git a/docs/releases/v1.19.0-next.0-changelog.md b/docs/releases/v1.19.0-next.0-changelog.md index d1861165b9..b1c85e238e 100644 --- a/docs/releases/v1.19.0-next.0-changelog.md +++ b/docs/releases/v1.19.0-next.0-changelog.md @@ -4,7 +4,7 @@ ### Minor Changes -- 7077dbf131: The new backend start command that used to be enabled by setting `EXPERIMENTAL_BACKEND_START` is now the default. To revert to the old behavior, set `LEGACY_BACKEND_START` instead. +- 7077dbf131: **BREAKING** The new backend start command that used to be enabled by setting `EXPERIMENTAL_BACKEND_START` is now the default. To revert to the old behavior set `LEGACY_BACKEND_START`, which is recommended if you haven't migrated to the new backend system. This new command is no longer based on Webpack, but instead uses Node.js loaders to transpile on the fly. Rather than hot reloading modules the entire backend is now restarted on change, but the SQLite database state is still maintained across restarts via a parent process. diff --git a/docs/releases/v1.19.0-next.2-changelog.md b/docs/releases/v1.19.0-next.2-changelog.md new file mode 100644 index 0000000000..3ac5fcfb48 --- /dev/null +++ b/docs/releases/v1.19.0-next.2-changelog.md @@ -0,0 +1,3142 @@ +# Release v1.19.0-next.2 + +## @backstage/cli@0.23.0-next.2 + +### Minor Changes + +- 8defbd5434: Update typescript-eslint to 6.7.x, adding compatibility with TypeScript 5.2. + + This includes a major update on typescript-eslint, you can see the details in the [release notes](https://typescript-eslint.io/blog/announcing-typescript-eslint-v6/). + +### Patch Changes + +- 2ef6522552: Support for the `.icon.svg` extension has been deprecated and will be removed in the future. The implementation of this extension is too tied to a particular version of MUI and the SVGO, and it makes it harder to evolve the build system. We may introduce the ability to reintroduce this kind of functionality in the future through configuration for use in internal plugins, but for now we're forced to remove it. + + To migrate existing code, rename the `.icon.svg` file to `.tsx` and replace the `<svg>` element with `<SvgIcon>` from MUI and add necessary imports. For example: + + ```tsx + import React from 'react'; + import SvgIcon from '@material-ui/core/SvgIcon'; + import { IconComponent } from '@backstage/core-plugin-api'; + + export const CodeSceneIcon = (props: SvgIconProps) => ( + <SvgIcon {...props}> + <g> + <path d="..." /> + </g> + </SvgIcon> + ); + ``` + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/config-loader@1.5.1-next.1 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/cli-node@0.1.5-next.1 + - @backstage/config@1.1.1-next.0 + - @backstage/eslint-plugin@0.1.3 + - @backstage/release-manifests@0.0.10 + - @backstage/types@1.1.1 + +## @backstage/core-app-api@1.11.0-next.2 + +### Minor Changes + +- c9d9bfeca2: URL encode some well known unsafe characters in `RouteResolver` (and therefore `useRouteRef`) + +### Patch Changes + +- acca17e91a: Wrap entire app in `<Suspense>`, enabling support for using translations outside plugins. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + +## @backstage/frontend-app-api@0.2.0-next.2 + +### Minor Changes + +- 4461d87d5a: Removed support for the new `useRouteRef`. + +### Patch Changes + +- 5072824817: Implement `toString()` and `toJSON()` for extension instances. +- 06432f900c: Updates for `at` -> `attachTo` refactor. +- 1718ec75b7: Added support for the existing routing system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/plugin-graphiql@0.2.55-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + +## @backstage/frontend-plugin-api@0.2.0-next.2 + +### Minor Changes + +- 06432f900c: Extension attachment point is now configured via `attachTo: { id, input }` instead of `at: 'id/input'`. +- 4461d87d5a: Removed support for the new `useRouteRef`. + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/types@1.1.1 + +## @techdocs/cli@1.6.0-next.2 + +### Minor Changes + +- d06b30b050: Add possibility to use a mkdocs config file with a different name than `mkdocs.<yaml|yml> with the serve command using the `--mkdocs-config-file-name\` argument + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-techdocs-node@1.9.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.0-next.2 + +### Minor Changes + +- 6f142d5356: **BREAKING** `gcpIapAuthenticator.initialize()` is no longer `async` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/types@1.1.1 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.1.0-next.0 + +### Minor Changes + +- 2d8f7e82c1: Migrated the Microsoft auth provider to new `@backstage/plugin-auth-backend-module-microsoft-provider` module package. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + +## @backstage/plugin-auth-node@0.4.0-next.2 + +### Minor Changes + +- 6f142d5356: **BREAKING**: The recently introduced `ProxyAuthenticator.initialize()` method is no longer `async` to match the way the OAuth equivalent is implemented. + +### Patch Changes + +- 8b8b1d23ae: Fixed cookie persisted scope not returned in OAuth refresh handler response. +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-backend-module-github-org@0.1.0-next.0 + +### Minor Changes + +- c101e683d5: Added `catalogModuleGithubOrgEntityProvider` to ingest users and teams from multiple Github organizations. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-catalog-backend-module-github@0.4.4-next.2 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-kubernetes-node@0.1.0-next.0 + +### Minor Changes + +- cbb0e3c3f4: A new plugin has been introduced to house the extension points for Kubernetes backend plugin; at the moment only the `KubernetesObjectsProviderExtensionPoint` is present. The `kubernetes-backend` plugin was modified to use this new extension point. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-kubernetes-common@0.7.0-next.1 + - @backstage/backend-plugin-api@0.6.6-next.2 + +## @backstage/plugin-newrelic-dashboard@0.3.0-next.2 + +### Minor Changes + +- d7eba6cab4: Changes in `newrelic-dashboard` plugin: + + - Make DashboardSnapshotList component public + - Settle discrepancies in the exported API + - Deprecate DashboardSnapshotComponent + +### Patch Changes + +- 5194a51a1c: Fixed React Warning: "Each child in a list should have a unique 'key' prop" during the rendering of `EntityNewRelicDashboardCard` +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + +## @backstage/plugin-scaffolder-backend@1.18.0-next.2 + +### Minor Changes + +- dea0aafda7: Updated `publish:gitlab` action properties to support additional Gitlab project settings: + + - general project settings provided by gitlab project create API (new `settings` property) + - branch level settings to create additional branches and make them protected (new `branches` property) + - project level environment variables settings (new `projectVariables` property) + + Marked existed properties `repoVisibility` and `topics` as deprecated, as they are covered by `settings` property. + +### Patch Changes + +- 7dd82cc07e: Add examples for `github:issues:label` scaffolder action & improve related tests +- 733ddf7130: Add examples for `publish:Azure` scaffolder action. +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/plugin-catalog-backend@1.14.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-scaffolder-common@1.4.2-next.0 + +## @backstage/plugin-techdocs-backend@1.8.0-next.2 + +### Minor Changes + +- 344cfbcfbc: Allow prepared directory clean up for custom preparers + + When using custom preparer for TechDocs, the `preparedDir` might + end up taking disk space. This requires all custom preparers to + implement a new method `shouldCleanPreparedDirectory` which indicates + whether the prepared directory should be cleaned after generation. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-techdocs-node@1.9.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-techdocs-node@1.9.0-next.2 + +### Minor Changes + +- 344cfbcfbc: Allow prepared directory clean up for custom preparers + + When using custom preparer for TechDocs, the `preparedDir` might + end up taking disk space. This requires all custom preparers to + implement a new method `shouldCleanPreparedDirectory` which indicates + whether the prepared directory should be cleaned after generation. + +- d06b30b050: Add possibility to use a mkdocs config file with a different name than `mkdocs.<yaml|yml> with the serve command using the `--mkdocs-config-file-name\` argument + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/integration-aws-node@0.1.7-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/app-defaults@1.4.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-permission-react@0.4.16-next.1 + +## @backstage/backend-app-api@0.5.6-next.2 + +### Patch Changes + +- 74491c9602: Moved `HostDiscovery` from `@backstage/backend-common`. +- a4617c422a: Added `watch` option to configuration loaders that can be used to disable file watching by setting it to `false`. +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/config-loader@1.5.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/cli-node@0.1.5-next.1 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/backend-common@0.19.8-next.2 + +### Patch Changes + +- 74491c9602: The `HostDiscovery` export has been deprecated, import it from `@backstage/backend-app-api` instead. +- b95d66d4ea: Properly close write stream when writing temporary archive for processing zip-based `.readTree()` responses. +- 0b55f773a7: Removed some unused dependencies +- 4c39e38f1e: Added `/testUtils` entry point, with a utility for mocking resolve package paths as returned by `resolvePackagePath`. +- a250ad775f: Removed `mock-fs` dev dependency. +- Updated dependencies + - @backstage/config-loader@1.5.1-next.1 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-app-api@0.5.6-next.2 + - @backstage/backend-dev-utils@0.1.2-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/integration-aws-node@0.1.7-next.0 + - @backstage/types@1.1.1 + +## @backstage/backend-defaults@0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-app-api@0.5.6-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + +## @backstage/backend-openapi-utils@0.0.5-next.0 + +### Patch Changes + +- 7c83975531: Adds new public utility types for common OpenAPI values, like request and response shapes and parameters available on an endpoint. + + **deprecated** `internal` namespace + The internal namespace will continue to be exported but now uses OpenAPI format for path parameters. You should use the new utility types. + +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + +## @backstage/backend-plugin-api@0.6.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/backend-tasks@0.5.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/backend-test-utils@0.2.7-next.2 + +### Patch Changes + +- a250ad775f: Added `createMockDirectory()` to help out with file system mocking in tests. +- 74491c9602: Updated to import `HostDiscovery` from `@backstage/backend-app-api`. +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-app-api@0.5.6-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/catalog-client@1.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + +## @backstage/catalog-model@1.4.3-next.0 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + - @backstage/types@1.1.1 + +## @backstage/cli-node@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/types@1.1.1 + +## @backstage/config@1.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + - @backstage/types@1.1.1 + +## @backstage/config-loader@1.5.1-next.1 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 30c553c1d2: Updated dependency `typescript-json-schema` to `^0.61.0`. +- a4617c422a: Added `watch` option to configuration loaders that can be used to disable file watching by setting it to `false`. +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/core-components@0.13.6-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 8a15360bb4: Fixed overflowing messages in `WarningPanel`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/version-bridge@1.0.5 + +## @backstage/core-plugin-api@1.7.0-next.1 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + +## @backstage/create-app@0.5.6-next.2 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.13-next.0 + +## @backstage/dev-utils@1.0.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/app-defaults@1.4.4-next.2 + - @backstage/test-utils@1.4.4-next.2 + +## @backstage/errors@1.2.3-next.0 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/types@1.1.1 + +## @backstage/integration@1.7.1-next.1 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/config@1.1.1-next.0 + +## @backstage/integration-aws-node@0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + - @backstage/config@1.1.1-next.0 + +## @backstage/integration-react@1.1.20-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/integration@1.7.1-next.1 + - @backstage/config@1.1.1-next.0 + +## @backstage/repo-tools@0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/cli-node@0.1.5-next.1 + +## @backstage/test-utils@1.4.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-permission-react@0.4.16-next.1 + +## @backstage/theme@0.4.3-next.0 + +### Patch Changes + +- 5ad5344756: Added support for string `fontSize` values (e.g. `"2.5rem"`) in themes in addition to numbers. Also added an optional `fontFamily` prop for header typography variants to allow further customization. + +## @backstage/plugin-adr@0.6.8-next.2 + +### Patch Changes + +- 499e34656e: Fix icon alignment in `AdrSearchResultListItem` +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-adr-common@0.2.16-next.1 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-adr-backend@0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-adr-common@0.2.16-next.1 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-adr-common@0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-airbrake@0.3.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/dev-utils@1.0.22-next.2 + - @backstage/test-utils@1.4.4-next.2 + +## @backstage/plugin-airbrake-backend@0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-allure@0.1.41-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-analytics-module-ga@0.1.34-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-analytics-module-ga4@0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-analytics-module-newrelic-browser@0.0.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-apache-airflow@0.2.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + +## @backstage/plugin-api-docs@0.9.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/plugin-catalog@1.14.0-next.2 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-apollo-explorer@0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-app-backend@0.3.54-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/config-loader@1.5.1-next.1 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-app-node@0.1.6-next.2 + +## @backstage/plugin-app-node@0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6-next.2 + +## @backstage/plugin-auth-backend@0.19.3-next.2 + +### Patch Changes + +- 2d8f7e82c1: Migrated the Microsoft auth provider to new `@backstage/plugin-auth-backend-module-microsoft-provider` module package. +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.0-next.2 + - @backstage/plugin-auth-backend-module-microsoft-provider@0.1.0-next.0 + - @backstage/plugin-auth-backend-module-github-provider@0.1.3-next.2 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.3-next.2 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.3-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-backend-module-google-provider@0.1.3-next.2 + +## @backstage/plugin-auth-backend-module-github-provider@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + +## @backstage/plugin-auth-backend-module-google-provider@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + +## @backstage/plugin-azure-devops@0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-azure-devops-common@0.3.1 + +## @backstage/plugin-azure-devops-backend@0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-azure-devops-common@0.3.1 + +## @backstage/plugin-azure-sites@0.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-azure-sites-common@0.1.1 + +## @backstage/plugin-azure-sites-backend@0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-azure-sites-common@0.1.1 + +## @backstage/plugin-badges@0.2.49-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-badges-backend@0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-bazaar@0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.23.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-catalog@1.14.0-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + +## @backstage/plugin-bazaar-backend@0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-bitbucket-cloud-common@0.2.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1-next.1 + +## @backstage/plugin-bitrise@0.1.52-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-catalog@1.14.0-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-scaffolder-common@1.4.2-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-catalog-backend@1.14.0-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-openapi-utils@0.0.5-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/plugin-search-backend-module-catalog@0.1.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-events-node@0.2.15-next.2 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-catalog-backend-module-aws@0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-kubernetes-common@0.7.0-next.1 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/integration-aws-node@0.1.7-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + +## @backstage/plugin-catalog-backend-module-azure@0.1.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + +## @backstage/plugin-catalog-backend-module-bitbucket@0.2.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.13-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.13-next.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-events-node@0.2.15-next.2 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.1.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-catalog-backend-module-gcp@0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-kubernetes-common@0.7.0-next.1 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-catalog-backend-module-gerrit@0.1.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-catalog-backend-module-github@0.4.4-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- c101e683d5: Removed `catalogModuleGithubOrgEntityProvider`. Import from `@backstage/plugin-catalog-backend-module-github-org` instead. +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-catalog-backend@1.14.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-events-node@0.2.15-next.2 + +## @backstage/plugin-catalog-backend-module-gitlab@0.3.3-next.2 + +### Patch Changes + +- 4f70fdfc93: fix: use REST API to get root group memberships for GitLab SaaS users listing + + This API is the only one that shows `email` field for enterprise users and + allows to filter out bot users not using a license using the `is_using_seat` + field. + + We also added the annotation `gitlab.com/saml-external-uid` taking the value + of `group_saml_identity.extern_uid` of the `groups/:group-id/members` endpoint + response. This is useful in case you want to create a `SignInResolver` that + references the user with the id of your identity provider (e.g. OneLogin). + + ref: + + <https://docs.gitlab.com/ee/user/enterprise_user/#get-users-email-addresses-through-the-api> + <https://docs.gitlab.com/ee/api/members.html#limitations> + +- 0b55f773a7: Removed some unused dependencies + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.4.10-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-catalog-backend@1.14.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-events-node@0.2.15-next.2 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-catalog-backend-module-ldap@0.5.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + +## @backstage/plugin-catalog-backend-module-msgraph@0.5.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + +## @backstage/plugin-catalog-backend-module-openapi@0.1.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-catalog-backend@1.14.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-scaffolder-common@1.4.2-next.0 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + +## @backstage/plugin-catalog-common@1.0.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-catalog-graph@0.2.37-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-catalog-graphql@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 + +## @backstage/plugin-catalog-import@0.10.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + +## @backstage/plugin-catalog-node@1.4.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + +## @backstage/plugin-catalog-react@1.8.5-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-permission-react@0.4.16-next.1 + +## @backstage/plugin-catalog-unprocessed-entities@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-cicd-statistics@0.1.27-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + +## @backstage/plugin-cicd-statistics-module-gitlab@0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/plugin-cicd-statistics@0.1.27-next.2 + - @backstage/catalog-model@1.4.3-next.0 + +## @backstage/plugin-circleci@0.3.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-cloudbuild@0.3.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-code-climate@0.1.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-code-coverage@0.2.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-code-coverage-backend@0.2.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-codescene@0.1.18-next.2 + +### Patch Changes + +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-config-schema@0.1.46-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-cost-insights@0.12.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-cost-insights-common@0.1.2 + +## @backstage/plugin-devtools@0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.5-next.0 + - @backstage/plugin-permission-react@0.4.16-next.1 + +## @backstage/plugin-devtools-backend@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/config-loader@1.5.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.5-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-devtools-common@0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-dynatrace@7.0.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-entity-feedback@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-feedback-backend@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## @backstage/plugin-entity-validation@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + +## @backstage/plugin-events-backend@0.2.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-events-node@0.2.15-next.2 + +## @backstage/plugin-events-backend-module-aws-sqs@0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.15-next.2 + +## @backstage/plugin-events-backend-module-azure@0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/plugin-events-node@0.2.15-next.2 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/plugin-events-node@0.2.15-next.2 + +## @backstage/plugin-events-backend-module-gerrit@0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/plugin-events-node@0.2.15-next.2 + +## @backstage/plugin-events-backend-module-github@0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-events-node@0.2.15-next.2 + +## @backstage/plugin-events-backend-module-gitlab@0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-events-node@0.2.15-next.2 + +## @backstage/plugin-events-backend-test-utils@0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.15-next.2 + +## @backstage/plugin-events-node@0.2.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6-next.2 + +## @backstage/plugin-explore@0.4.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-explore-react@0.0.32-next.1 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-explore-backend@0.0.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-search-backend-module-explore@0.1.10-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-explore-react@0.0.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/plugin-explore-common@0.0.2 + +## @backstage/plugin-firehydrant@0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-fossa@0.2.57-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-gcalendar@0.3.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-gcp-projects@0.3.42-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-git-release-manager@0.3.38-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/integration@1.7.1-next.1 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-github-actions@0.6.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-github-deployments@0.1.56-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-github-issues@0.2.14-next.2 + +### Patch Changes + +- 7bd0a8ab3c: Filters out entities that belonged to a different github instance other than the one configured by the plugin +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-github-pull-requests-board@0.1.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-gitops-profiles@0.3.41-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-gocd@0.1.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-graphiql@0.2.55-next.2 + +### Patch Changes + +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- 06432f900c: Updated `/alpha` exports to use new `attachTo` option. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-graphql-backend@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 + +## @backstage/plugin-graphql-voyager@0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-home@0.5.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-home-react@0.1.4-next.2 + +## @backstage/plugin-home-react@0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + +## @backstage/plugin-ilert@0.2.14-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-jenkins@0.8.7-next.2 + +### Patch Changes + +- 1a05cf34f6: Extend EntityJenkinsContent to receive columns as prop +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-jenkins-common@0.1.20-next.0 + +## @backstage/plugin-jenkins-backend@0.2.9-next.2 + +### Patch Changes + +- 930ac236d8: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-jenkins-common@0.1.20-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-jenkins-common@0.1.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-kafka@0.3.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-kafka-backend@0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-kubernetes@0.11.0-next.2 + +### Patch Changes + +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-kubernetes-react@0.1.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-kubernetes-common@0.7.0-next.1 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-kubernetes-backend@0.12.3-next.2 + +### Patch Changes + +- cbb0e3c3f4: A new plugin has been introduced to house the extension points for Kubernetes backend plugin; at the moment only the `KubernetesObjectsProviderExtensionPoint` is present. The `kubernetes-backend` plugin was modified to use this new extension point. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-kubernetes-node@0.1.0-next.0 + - @backstage/plugin-kubernetes-common@0.7.0-next.1 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/integration-aws-node@0.1.7-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-kubernetes-cluster@0.0.1-next.0 + +### Patch Changes + +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-kubernetes-react@0.1.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-kubernetes-common@0.7.0-next.1 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-kubernetes-common@0.7.0-next.1 + +### Patch Changes + +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-kubernetes-react@0.1.0-next.1 + +### Patch Changes + +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-kubernetes-common@0.7.0-next.1 + - @backstage/types@1.1.1 + +## @backstage/plugin-lighthouse@0.4.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-lighthouse-common@0.1.4-next.0 + +## @backstage/plugin-lighthouse-backend@0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4-next.0 + +## @backstage/plugin-lighthouse-common@0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-linguist@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-linguist-backend@0.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-linguist-common@0.1.2 + +## @backstage/plugin-microsoft-calendar@0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-newrelic@0.3.41-next.2 + +### Patch Changes + +- ce50a15506: Fixed sorting and searching in the NewRelic table. +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-nomad@0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-nomad-backend@0.1.8-next.2 + +### Patch Changes + +- 6822918c50: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-octopus-deploy@0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-opencost@0.2.1-next.2 + +### Patch Changes + +- 777b9a16a4: Fix for broken image reference. +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-org@0.6.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-org-react@0.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + +## @backstage/plugin-pagerduty@0.6.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-home-react@0.1.4-next.2 + +## @backstage/plugin-periskop@0.1.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-periskop-backend@0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-permission-backend@0.5.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-permission-common@0.7.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-permission-node@0.7.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-permission-react@0.4.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-playlist@0.1.17-next.2 + +### Patch Changes + +- 65498193e8: Updated Playlist read me with additional screenshots +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-permission-react@0.4.16-next.1 + - @backstage/plugin-playlist-common@0.1.11-next.0 + +## @backstage/plugin-playlist-backend@0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-playlist-common@0.1.11-next.0 + +## @backstage/plugin-playlist-common@0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-proxy-backend@0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-puppetdb@0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-rollbar@0.4.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-rollbar-backend@0.1.51-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-scaffolder@1.15.1-next.2 + +### Patch Changes + +- ff2ab02690: Make entity picker more reliable with only one available entity +- 83e4a42ccd: Display log visibility button on the template panel +- 4c70fe497d: `RepoUrlPickerRepoName` now correctly handles value changes in allowed repos. +- Updated dependencies + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-react@0.4.16-next.1 + - @backstage/plugin-scaffolder-common@1.4.2-next.0 + - @backstage/plugin-scaffolder-react@1.5.6-next.2 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.2.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-rails@0.4.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.2.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-scaffolder-common@1.4.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-scaffolder-node@0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.2-next.0 + +## @backstage/plugin-scaffolder-react@1.5.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-scaffolder-common@1.4.2-next.0 + +## @backstage/plugin-search@1.4.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-search-backend@1.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-openapi-utils@0.0.5-next.0 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-search-backend-module-catalog@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-search-backend-module-elasticsearch@1.3.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/integration-aws-node@0.1.7-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-search-backend-module-explore@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-search-backend-module-pg@0.5.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-search-backend-module-techdocs@0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-techdocs-node@1.9.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-search-backend-node@1.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-search-common@1.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/plugin-search-react@1.7.1-next.2 + +### Patch Changes + +- 06432f900c: Updated `/alpha` exports to use new `attachTo` option. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/frontend-app-api@0.2.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-sentry@0.5.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-shortcuts@0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-sonarqube@0.7.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-sonarqube-react@0.1.9-next.1 + +## @backstage/plugin-sonarqube-backend@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-sonarqube-react@0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + +## @backstage/plugin-splunk-on-call@0.4.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-stack-overflow@0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-home-react@0.1.4-next.2 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-stack-overflow-backend@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + +## @backstage/plugin-stackstorm@0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-tech-insights@0.3.17-next.2 + +### Patch Changes + +- 21f409d776: Export `ScorecardInfo` and `ScorecardsList` components to be able to use manually queried check results directly. +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-backend@0.5.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-tech-insights-node@0.4.12-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.38-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-tech-insights-node@0.4.12-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-insights-node@0.4.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## @backstage/plugin-tech-radar@0.6.9-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-techdocs@1.7.1-next.2 + +### Patch Changes + +- 3605370af6: Improved `DocsTable` to display pagination controls dynamically, appearing only when needed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + - @backstage/plugin-techdocs-react@1.1.12-next.2 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/plugin-techdocs@1.7.1-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/plugin-catalog@1.14.0-next.2 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/test-utils@1.4.4-next.2 + - @backstage/plugin-techdocs-react@1.1.12-next.2 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/integration@1.7.1-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-techdocs-react@1.1.12-next.2 + +## @backstage/plugin-techdocs-react@1.1.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/version-bridge@1.0.5 + +## @backstage/plugin-todo@0.2.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-todo-backend@0.3.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-openapi-utils@0.0.5-next.0 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-user-settings@0.7.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/types@1.1.1 + +## @backstage/plugin-user-settings-backend@0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/types@1.1.1 + +## @backstage/plugin-vault@0.1.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## @backstage/plugin-vault-backend@0.3.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/config@1.1.1-next.0 + +## @backstage/plugin-xcmetrics@0.2.44-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + +## example-app@0.2.88-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.23.0-next.2 + - @backstage/frontend-app-api@0.2.0-next.2 + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/plugin-techdocs@1.7.1-next.2 + - @backstage/plugin-newrelic@0.3.41-next.2 + - @backstage/plugin-scaffolder@1.15.1-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/plugin-tech-radar@0.6.9-next.2 + - @backstage/plugin-catalog@1.14.0-next.2 + - @backstage/plugin-adr@0.6.8-next.2 + - @backstage/plugin-graphiql@0.2.55-next.2 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/plugin-newrelic-dashboard@0.3.0-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.1-next.0 + - @backstage/plugin-kubernetes@0.11.0-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-jenkins@0.8.7-next.2 + - @backstage/plugin-tech-insights@0.3.17-next.2 + - @backstage/plugin-playlist@0.1.17-next.2 + - @backstage/app-defaults@1.4.4-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-airbrake@0.3.25-next.2 + - @backstage/plugin-apache-airflow@0.2.16-next.2 + - @backstage/plugin-api-docs@0.9.12-next.2 + - @backstage/plugin-azure-devops@0.3.7-next.2 + - @backstage/plugin-azure-sites@0.1.14-next.2 + - @backstage/plugin-badges@0.2.49-next.2 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-catalog-graph@0.2.37-next.2 + - @backstage/plugin-catalog-import@0.10.1-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4-next.2 + - @backstage/plugin-circleci@0.3.25-next.2 + - @backstage/plugin-cloudbuild@0.3.25-next.2 + - @backstage/plugin-code-coverage@0.2.18-next.2 + - @backstage/plugin-cost-insights@0.12.14-next.2 + - @backstage/plugin-devtools@0.1.5-next.2 + - @backstage/plugin-dynatrace@7.0.5-next.2 + - @backstage/plugin-entity-feedback@0.2.8-next.2 + - @backstage/plugin-explore@0.4.11-next.2 + - @backstage/plugin-gcalendar@0.3.19-next.2 + - @backstage/plugin-gcp-projects@0.3.42-next.2 + - @backstage/plugin-github-actions@0.6.6-next.2 + - @backstage/plugin-gocd@0.1.31-next.2 + - @backstage/plugin-home@0.5.9-next.2 + - @backstage/plugin-kafka@0.3.25-next.2 + - @backstage/plugin-lighthouse@0.4.10-next.2 + - @backstage/plugin-linguist@0.1.10-next.2 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-microsoft-calendar@0.1.8-next.2 + - @backstage/plugin-nomad@0.1.6-next.2 + - @backstage/plugin-octopus-deploy@0.2.7-next.2 + - @backstage/plugin-org@0.6.15-next.2 + - @backstage/plugin-pagerduty@0.6.6-next.2 + - @backstage/plugin-permission-react@0.4.16-next.1 + - @backstage/plugin-puppetdb@0.1.8-next.2 + - @backstage/plugin-rollbar@0.4.25-next.2 + - @backstage/plugin-scaffolder-react@1.5.6-next.2 + - @backstage/plugin-search@1.4.1-next.2 + - @backstage/plugin-search-common@1.2.7-next.0 + - @backstage/plugin-sentry@0.5.10-next.2 + - @backstage/plugin-shortcuts@0.3.15-next.2 + - @backstage/plugin-stack-overflow@0.1.21-next.2 + - @backstage/plugin-stackstorm@0.1.7-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1-next.2 + - @backstage/plugin-techdocs-react@1.1.12-next.2 + - @backstage/plugin-todo@0.2.28-next.2 + - @backstage/plugin-user-settings@0.7.11-next.2 + +## example-app-next@0.0.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.23.0-next.2 + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/frontend-app-api@0.2.0-next.2 + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/plugin-techdocs@1.7.1-next.2 + - @backstage/plugin-newrelic@0.3.41-next.2 + - @backstage/plugin-scaffolder@1.15.1-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/plugin-tech-radar@0.6.9-next.2 + - @backstage/plugin-catalog@1.14.0-next.2 + - @backstage/plugin-adr@0.6.8-next.2 + - @backstage/plugin-graphiql@0.2.55-next.2 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/plugin-newrelic-dashboard@0.3.0-next.2 + - @backstage/plugin-kubernetes@0.11.0-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-jenkins@0.8.7-next.2 + - @backstage/plugin-tech-insights@0.3.17-next.2 + - @backstage/plugin-playlist@0.1.17-next.2 + - @backstage/app-defaults@1.4.4-next.2 + - app-next-example-plugin@0.0.2-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-airbrake@0.3.25-next.2 + - @backstage/plugin-apache-airflow@0.2.16-next.2 + - @backstage/plugin-api-docs@0.9.12-next.2 + - @backstage/plugin-azure-devops@0.3.7-next.2 + - @backstage/plugin-azure-sites@0.1.14-next.2 + - @backstage/plugin-badges@0.2.49-next.2 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-catalog-graph@0.2.37-next.2 + - @backstage/plugin-catalog-import@0.10.1-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4-next.2 + - @backstage/plugin-circleci@0.3.25-next.2 + - @backstage/plugin-cloudbuild@0.3.25-next.2 + - @backstage/plugin-code-coverage@0.2.18-next.2 + - @backstage/plugin-cost-insights@0.12.14-next.2 + - @backstage/plugin-devtools@0.1.5-next.2 + - @backstage/plugin-dynatrace@7.0.5-next.2 + - @backstage/plugin-entity-feedback@0.2.8-next.2 + - @backstage/plugin-explore@0.4.11-next.2 + - @backstage/plugin-gcalendar@0.3.19-next.2 + - @backstage/plugin-gcp-projects@0.3.42-next.2 + - @backstage/plugin-github-actions@0.6.6-next.2 + - @backstage/plugin-gocd@0.1.31-next.2 + - @backstage/plugin-home@0.5.9-next.2 + - @backstage/plugin-kafka@0.3.25-next.2 + - @backstage/plugin-lighthouse@0.4.10-next.2 + - @backstage/plugin-linguist@0.1.10-next.2 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-microsoft-calendar@0.1.8-next.2 + - @backstage/plugin-octopus-deploy@0.2.7-next.2 + - @backstage/plugin-org@0.6.15-next.2 + - @backstage/plugin-pagerduty@0.6.6-next.2 + - @backstage/plugin-permission-react@0.4.16-next.1 + - @backstage/plugin-puppetdb@0.1.8-next.2 + - @backstage/plugin-rollbar@0.4.25-next.2 + - @backstage/plugin-scaffolder-react@1.5.6-next.2 + - @backstage/plugin-search@1.4.1-next.2 + - @backstage/plugin-search-common@1.2.7-next.0 + - @backstage/plugin-sentry@0.5.10-next.2 + - @backstage/plugin-shortcuts@0.3.15-next.2 + - @backstage/plugin-stack-overflow@0.1.21-next.2 + - @backstage/plugin-stackstorm@0.1.7-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1-next.2 + - @backstage/plugin-techdocs-react@1.1.12-next.2 + - @backstage/plugin-todo@0.2.28-next.2 + - @backstage/plugin-user-settings@0.7.11-next.2 + +## app-next-example-plugin@0.0.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/core-components@0.13.6-next.2 + +## example-backend@0.2.88-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-nomad-backend@0.1.8-next.2 + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-scaffolder-backend@1.18.0-next.2 + - @backstage/plugin-techdocs-backend@1.8.0-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/plugin-catalog-backend@1.14.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/plugin-kubernetes-backend@0.12.3-next.2 + - @backstage/plugin-jenkins-backend@0.2.9-next.2 + - @backstage/plugin-auth-backend@0.19.3-next.2 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-adr-backend@0.4.3-next.2 + - @backstage/plugin-app-backend@0.3.54-next.2 + - @backstage/plugin-azure-devops-backend@0.4.3-next.2 + - @backstage/plugin-azure-sites-backend@0.1.16-next.2 + - @backstage/plugin-badges-backend@0.3.3-next.2 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/plugin-code-coverage-backend@0.2.20-next.2 + - @backstage/plugin-devtools-backend@0.2.3-next.2 + - @backstage/plugin-entity-feedback-backend@0.2.3-next.2 + - @backstage/plugin-events-backend@0.2.15-next.2 + - @backstage/plugin-explore-backend@0.0.16-next.2 + - @backstage/plugin-graphql-backend@0.1.44-next.2 + - @backstage/plugin-kafka-backend@0.3.3-next.2 + - @backstage/plugin-lighthouse-backend@0.3.3-next.2 + - @backstage/plugin-linguist-backend@0.5.3-next.2 + - @backstage/plugin-permission-backend@0.5.29-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/plugin-playlist-backend@0.3.10-next.2 + - @backstage/plugin-proxy-backend@0.4.3-next.2 + - @backstage/plugin-rollbar-backend@0.1.51-next.2 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.7-next.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.23-next.2 + - @backstage/plugin-search-backend@1.4.6-next.2 + - @backstage/plugin-search-backend-module-catalog@0.1.10-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.9-next.2 + - @backstage/plugin-search-backend-module-explore@0.1.10-next.2 + - @backstage/plugin-search-backend-module-pg@0.5.15-next.2 + - @backstage/plugin-search-backend-module-techdocs@0.1.10-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/plugin-tech-insights-backend@0.5.20-next.2 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.38-next.2 + - @backstage/plugin-tech-insights-node@0.4.12-next.2 + - @backstage/plugin-todo-backend@0.3.4-next.2 + - example-app@0.2.88-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.3-next.2 + - @backstage/plugin-events-node@0.2.15-next.2 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + +## example-backend-next@0.0.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-nomad-backend@0.1.8-next.2 + - @backstage/plugin-scaffolder-backend@1.18.0-next.2 + - @backstage/plugin-techdocs-backend@1.8.0-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/plugin-catalog-backend@1.14.0-next.2 + - @backstage/plugin-kubernetes-backend@0.12.3-next.2 + - @backstage/plugin-jenkins-backend@0.2.9-next.2 + - @backstage/backend-defaults@0.2.6-next.2 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-adr-backend@0.4.3-next.2 + - @backstage/plugin-app-backend@0.3.54-next.2 + - @backstage/plugin-azure-devops-backend@0.4.3-next.2 + - @backstage/plugin-badges-backend@0.3.3-next.2 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3-next.2 + - @backstage/plugin-devtools-backend@0.2.3-next.2 + - @backstage/plugin-entity-feedback-backend@0.2.3-next.2 + - @backstage/plugin-lighthouse-backend@0.3.3-next.2 + - @backstage/plugin-linguist-backend@0.5.3-next.2 + - @backstage/plugin-permission-backend@0.5.29-next.2 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.3-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/plugin-playlist-backend@0.3.10-next.2 + - @backstage/plugin-proxy-backend@0.4.3-next.2 + - @backstage/plugin-search-backend@1.4.6-next.2 + - @backstage/plugin-search-backend-module-catalog@0.1.10-next.2 + - @backstage/plugin-search-backend-module-explore@0.1.10-next.2 + - @backstage/plugin-search-backend-module-techdocs@0.1.10-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/plugin-sonarqube-backend@0.2.8-next.2 + - @backstage/plugin-todo-backend@0.3.4-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.3-next.2 + - @backstage/plugin-permission-common@0.7.9-next.0 + +## @backstage/backend-plugin-manager@0.0.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/plugin-catalog-backend@1.14.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-events-backend@0.2.15-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/cli-node@0.1.5-next.1 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.15-next.2 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + +## e2e-test@0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.6-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/cli-common@0.1.13-next.0 + +## techdocs-cli-embedded-app@0.2.87-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.23.0-next.2 + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/plugin-techdocs@1.7.1-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog@1.14.0-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/app-defaults@1.4.4-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/test-utils@1.4.4-next.2 + - @backstage/plugin-techdocs-react@1.1.12-next.2 + +## @internal/plugin-todo-list@1.0.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + +## @internal/plugin-todo-list-backend@1.0.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + +## @internal/plugin-todo-list-common@1.0.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.9-next.0 diff --git a/docs/releases/v1.19.0.md b/docs/releases/v1.19.0.md new file mode 100644 index 0000000000..49a31f32b6 --- /dev/null +++ b/docs/releases/v1.19.0.md @@ -0,0 +1,86 @@ +--- +id: v1.19.0 +title: v1.19.0 +description: Backstage Release v1.19.0 +--- + +These are the release notes for the v1.19.0 release of [Backstage](https://backstage.io/). + +A huge thanks to the whole team of maintainers and contributors as well as the amazing Backstage Community for the hard work in getting this release developed and done. + +## Highlights + +### Node.js v18 + v20 + +The supported versions of Node.js are now v18 and v20. Be sure to update the `engine` field in your root `package.json` accordingly and update your Dockerfile base images, for example to `node:18-bookworm-slim`. + +### New default `start` command for backends + +Backend packages now use the new `package start` implementation by default. This new version uses module loaders rather than a Webpack build for transpilation. The largest difference from the old version is that the backend process is now restarted on change, rather than using Webpack hot module reloads. When using SQLite the database state is serialized and stored in the parent process across restart, which requires a [migration to the new backend system](https://backstage.io/docs/backend-system/building-backends/migrating). If you have yet to migrate to the new system it is recommended that you set the `LEGACY_BACKEND_START` environment variable when starting the backend to keep the old behavior. + +### **BREAKING**: Allow passing undefined `labelSelector` to `KubernetesFetcher` + +`KubernetesFetch` no longer auto-adds `labelSelector` when an empty string is passed. +This is only applicable if you have a custom ObjectProvider implementation, as build-in `KubernetesFanOutHandler` already does this. + +Contributed by [@szubster](https://github.com/szubster) in [#20541](https://github.com/backstage/backstage/pull/20541) + +### **DEPRECATION**: Catalog GraphQL Backend Package + +This package has been deprecated, consider using [@frontside/backstage-plugin-graphql-backend](https://www.npmjs.com/package/@frontside/backstage-plugin-graphql-backend) instead. + +### **DEPRECATION**: `.icon.svg` Extension Support + +Support for the `.icon.svg` extension has been deprecated and will be removed in a future release. Please migrate existing usage to either inline the SVG elements in a `<SvgIcon>` component from MUI, or switch to a regular `.svg` asset import. + +### Insightful Homepage + +You can now create an Insightful homepage to show your users their recent and top visited activity in Backstage. Add [this](https://github.com/backstage/backstage/tree/master/plugins/home#page-visit-homepage-component-homepagetopvisited--homepagerecentlyvisited) plugin to track your users’ recent navigation history in your Backstage database and display it in the Backstage Homepage using the customizable Recent and Top visits components (`<HomePageTopVisited />` and `<HomePageRecentlyVisited />`)and the extensible Visits API interface. This feature is released with an example that extends the Visits API with LocalStorage as an alternative storage solution for user visit activity. + +### New plugin: Kubernetes Clusters + +This plugin lets you view Kubernetes clusters as an admin. + +### New feature: New Pinniped Auth Provider Module + +This module provides a Pinniped auth provider implementation for the auth backend. + +Contributed by [@RubenV-dev](https://github.com/RubenV-dev) in [#19846](https://github.com/backstage/backstage/pull/19846) + +## More Movement Toward the New Backend System + +Since the last release, a lot of contributions have been made toward migrating features to support [the new backend system](https://backstage.io/docs/backend-system/). + +The following backend plugins were migrated: + +- jenkins +- nomad +- sonarqube +- playlist + +The Kubernetes backend broadened its backend system feature set, with a new extension point. For the catalog backend, some new modules were added, including GitHub org and Microsoft/Azure. + +If you would like to help out with these efforts, check out [this issue](https://github.com/backstage/backstage/issues/18301)! + +## Security Fixes + +Some improvements were made in the configuration schemas, ensuring that no secret fields could be read outside of a backend context. + +The `lerna` package in newly scaffolded Backstage repositories is now of version >7 which has security fixes. + +## Upgrade path + +We recommend that you keep your Backstage project up to date with this latest release. For more guidance on how to upgrade, check out the documentation for [keeping Backstage updated](https://backstage.io/docs/getting-started/keeping-backstage-updated). + +## Links and References + +Below you can find a list of links and references to help you learn about and start using this new release. + +- [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) +- [GitHub repository](https://github.com/backstage/backstage) +- Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support +- [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.19.0-changelog.md) +- Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) + +Sign up for our [newsletter](https://info.backstage.spotify.com/newsletter_subscribe) if you want to be informed about what is happening in the world of Backstage. diff --git a/microsite/data/plugins/dynatrace.yaml b/microsite/data/plugins/dynatrace.yaml index 9ec1fee7b3..94a2e423a6 100644 --- a/microsite/data/plugins/dynatrace.yaml +++ b/microsite/data/plugins/dynatrace.yaml @@ -1,13 +1,15 @@ --- title: Dynatrace -author: TELUS -authorUrl: https://github.com/telus +author: Dynatrace +authorUrl: https://github.com/dynatrace category: Monitoring description: View monitoring info from Dynatrace for services in your software catalog. documentation: https://github.com/backstage/backstage/tree/master/plugins/dynatrace iconUrl: /img/dynatrace.svg npmPackageName: '@backstage/plugin-dynatrace' tags: - - dynatrace - monitoring + - observability + - alerting + - problems addedDate: '2022-06-23' diff --git a/microsite/data/plugins/tips.yaml b/microsite/data/plugins/tips.yaml new file mode 100644 index 0000000000..e58ad0fb46 --- /dev/null +++ b/microsite/data/plugins/tips.yaml @@ -0,0 +1,10 @@ +--- +title: Tips +author: dweber019 +authorUrl: https://github.com/dweber019 +category: Discovery +description: The tips plugin will show the end user some helpful information for entities. +documentation: https://github.com/dweber019/backstage-plugin-tips +iconUrl: https://raw.githubusercontent.com/dweber019/backstage-plugin-tips/main/plugins/tips/docs/pluginIcon.png +npmPackageName: '@dweber019/backstage-plugin-tips' +addedDate: '2023-10-08' diff --git a/microsite/docusaurus.config.js b/microsite/docusaurus.config.js index 1879e35e72..f4dd76b8e3 100644 --- a/microsite/docusaurus.config.js +++ b/microsite/docusaurus.config.js @@ -73,6 +73,7 @@ module.exports = { // Replace all HTML comments with emtpy strings as these are not supported by MDXv2. return fileContent.replace(/<!--.*?-->/gs, ''); }, + format: 'md', }, webpack: { jsLoader: isServer => ({ @@ -177,7 +178,7 @@ module.exports = { position: 'left', }, { - to: 'docs/releases/v1.18.0', + to: 'docs/releases/v1.19.0', label: 'Releases', position: 'left', }, diff --git a/microsite/package.json b/microsite/package.json index 720179093a..3f266c189e 100644 --- a/microsite/package.json +++ b/microsite/package.json @@ -17,28 +17,28 @@ "docusaurus": "docusaurus" }, "devDependencies": { - "@docusaurus/module-type-aliases": "0.0.0-5591", + "@docusaurus/module-type-aliases": "0.0.0-5703", "@spotify/prettier-config": "^14.0.0", "@tsconfig/docusaurus": "^1.0.6", "@types/luxon": "^3.0.0", "@types/webpack-env": "^1.18.0", "js-yaml": "^4.1.0", "prettier": "^2.6.2", - "typescript": "^4.9.4", + "typescript": "~5.0.0", "yaml-loader": "^0.8.0" }, "prettier": "@spotify/prettier-config", "dependencies": { - "@docusaurus/core": "0.0.0-5591", - "@docusaurus/plugin-client-redirects": "0.0.0-5591", - "@docusaurus/preset-classic": "0.0.0-5591", + "@docusaurus/core": "0.0.0-5703", + "@docusaurus/plugin-client-redirects": "0.0.0-5703", + "@docusaurus/preset-classic": "0.0.0-5703", "@swc/core": "^1.3.46", "clsx": "^1.1.1", "docusaurus-plugin-sass": "^0.2.3", "luxon": "^3.0.0", "prism-react-renderer": "^1.3.5", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.0.0", + "react-dom": "^18.0.0", "sass": "^1.57.1", "swc-loader": "^0.2.3" } diff --git a/microsite/sidebars.json b/microsite/sidebars.json index bc394982ca..8d8cb39eaa 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -1,6 +1,7 @@ { "releases": { "Release Notes": [ + "releases/v1.19.0", "releases/v1.18.0", "releases/v1.17.0", "releases/v1.16.0", diff --git a/microsite/yarn.lock b/microsite/yarn.lock index 81d3ccfb42..8147655315 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -5,111 +5,126 @@ __metadata: version: 6 cacheKey: 8 -"@algolia/autocomplete-core@npm:1.8.2": - version: 1.8.2 - resolution: "@algolia/autocomplete-core@npm:1.8.2" +"@algolia/autocomplete-core@npm:1.9.3": + version: 1.9.3 + resolution: "@algolia/autocomplete-core@npm:1.9.3" dependencies: - "@algolia/autocomplete-shared": 1.8.2 - checksum: 03c164d8ce685e8b690734364a2e8653a7ebaf9b49ccbea5f94236b1231d66ed6771010406a0b00a2ce884b767712d71903a7d124ec11f35a87006d1456da762 + "@algolia/autocomplete-plugin-algolia-insights": 1.9.3 + "@algolia/autocomplete-shared": 1.9.3 + checksum: ce78048568660184a4fa3c6548f344a7f5ce0ba45d4cfc233f9756b6d4f360afd5ae3a18efefcd27a626d3a0d6cf22d9cba3e21b217afae62b8e9d11bc4960da languageName: node linkType: hard -"@algolia/autocomplete-preset-algolia@npm:1.8.2": - version: 1.8.2 - resolution: "@algolia/autocomplete-preset-algolia@npm:1.8.2" +"@algolia/autocomplete-plugin-algolia-insights@npm:1.9.3": + version: 1.9.3 + resolution: "@algolia/autocomplete-plugin-algolia-insights@npm:1.9.3" dependencies: - "@algolia/autocomplete-shared": 1.8.2 + "@algolia/autocomplete-shared": 1.9.3 + peerDependencies: + search-insights: ">= 1 < 3" + checksum: 030695bf692021c27f52a3d4931efed23032796e326d4ae7957ae91b51c36a10dc2d885fb043909e853f961c994b8e9ff087f50bb918cfa075370562251a199f + languageName: node + linkType: hard + +"@algolia/autocomplete-preset-algolia@npm:1.9.3": + version: 1.9.3 + resolution: "@algolia/autocomplete-preset-algolia@npm:1.9.3" + dependencies: + "@algolia/autocomplete-shared": 1.9.3 peerDependencies: "@algolia/client-search": ">= 4.9.1 < 6" algoliasearch: ">= 4.9.1 < 6" - checksum: f968b0f9d0ad9e75d3e1cfe35a02816ed01d83eb3d702bb8d4297bb9abf542991659c4a16c6ea323eea9268f189e85f58fcb109de76e6c4a9f58a0d63812c92e + checksum: 1ab3273d3054b348eed286ad1a54b21807846326485507b872477b827dc688006d4f14233cebd0bf49b2932ec8e29eca6d76e48a3c9e9e963b25153b987549c0 languageName: node linkType: hard -"@algolia/autocomplete-shared@npm:1.8.2": - version: 1.8.2 - resolution: "@algolia/autocomplete-shared@npm:1.8.2" - checksum: 1ec17deb594c41e983643cfd888e3590963aa7207ef6a67859c49a8f4835340493ba3b025b8b617b488365730ba9817ad58ee44a610c172332446e560fb68780 +"@algolia/autocomplete-shared@npm:1.9.3": + version: 1.9.3 + resolution: "@algolia/autocomplete-shared@npm:1.9.3" + peerDependencies: + "@algolia/client-search": ">= 4.9.1 < 6" + algoliasearch: ">= 4.9.1 < 6" + checksum: 06014c8b08d30c452de079f48c0235d8fa09904bf511da8dc1b7e491819940fd4ff36b9bf65340242b2e157a26799a3b9aea01feee9c5bf67be3c48d7dff43d7 languageName: node linkType: hard -"@algolia/cache-browser-local-storage@npm:4.17.0": - version: 4.17.0 - resolution: "@algolia/cache-browser-local-storage@npm:4.17.0" +"@algolia/cache-browser-local-storage@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/cache-browser-local-storage@npm:4.20.0" dependencies: - "@algolia/cache-common": 4.17.0 - checksum: cca4bd274a93ff4b47895b7396666294297e650ae8f9f50cc1a1dfe70d4bcf9bd1c5dbc15027f4b42c51693d1d0b996fa6c53b95462f3e31d44f4f4b76384a48 + "@algolia/cache-common": 4.20.0 + checksum: b9ca7e190ab77ddf4d30d22223345f69fc89899aa6887ee716e4ffcef14c8c9d28b782cb7cc96a0f04eed95a989878a6feca5b9aa6add0cd1846222c3308bb65 languageName: node linkType: hard -"@algolia/cache-common@npm:4.17.0": - version: 4.17.0 - resolution: "@algolia/cache-common@npm:4.17.0" - checksum: cbf8d6ca4ee653f2bef6665eb36b7afee2d4031abe5444cd121d60614189f2c96d0e00cfef990cbe68d318dbcef9b38f5df70476f9088ef43f8c83d69d0802b8 +"@algolia/cache-common@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/cache-common@npm:4.20.0" + checksum: a46377de8a309feea109aae1283fc9157c73766a4c51e3085870a1fc49f6e33698814379f3bbdf475713fa0663dace86fc90f0466e64469b1b885a0538abace4 languageName: node linkType: hard -"@algolia/cache-in-memory@npm:4.17.0": - version: 4.17.0 - resolution: "@algolia/cache-in-memory@npm:4.17.0" +"@algolia/cache-in-memory@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/cache-in-memory@npm:4.20.0" dependencies: - "@algolia/cache-common": 4.17.0 - checksum: 95d8a831d86da4971b62ddfa3a0bad991dc78d2482b47e409ab3e81a88e2d1e020287f36900a71caee7ef76c8730609e74bad10f3a7fa0fa7fd7fe1ece68a29e + "@algolia/cache-common": 4.20.0 + checksum: 3d67dcfae431605c8b9b1502f14865722f13b97b2822e1e3ed53bbf7bf66a120a825ccf5ed03476ebdf4aa15482dad5bfc6c2c93d81f07f862c373c689f49317 languageName: node linkType: hard -"@algolia/client-account@npm:4.17.0": - version: 4.17.0 - resolution: "@algolia/client-account@npm:4.17.0" +"@algolia/client-account@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/client-account@npm:4.20.0" dependencies: - "@algolia/client-common": 4.17.0 - "@algolia/client-search": 4.17.0 - "@algolia/transporter": 4.17.0 - checksum: 5ba40c348c07c059e303857a726a163256a159ca4ca9419f3c6eb80ef979838b375614674cf778fd35faaecd5e51c91811e19e9d5fabc3c421182dfc9464b798 + "@algolia/client-common": 4.20.0 + "@algolia/client-search": 4.20.0 + "@algolia/transporter": 4.20.0 + checksum: b59e9c7a324bbfba4abdab3f41d333522eb1abce7dab74e69d297acd9ee2a3c60e82e5e9db42e6a46b5ea26a35728533e6e4ff846c631b588ceb73d14dcbc5fb languageName: node linkType: hard -"@algolia/client-analytics@npm:4.17.0": - version: 4.17.0 - resolution: "@algolia/client-analytics@npm:4.17.0" +"@algolia/client-analytics@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/client-analytics@npm:4.20.0" dependencies: - "@algolia/client-common": 4.17.0 - "@algolia/client-search": 4.17.0 - "@algolia/requester-common": 4.17.0 - "@algolia/transporter": 4.17.0 - checksum: 6cddb0bc8fb2f7ce46c0f051f282a9ecb22333f32e43274bbec61228bcb040af87029b759ab300c9f1af90e4b4a08adf7b4899faf13ab94426a43823c39e951a + "@algolia/client-common": 4.20.0 + "@algolia/client-search": 4.20.0 + "@algolia/requester-common": 4.20.0 + "@algolia/transporter": 4.20.0 + checksum: 0be4120ab72162e0640e49eedddff81bfc2c590e9a9322d1788b8c01e06fdabcaaaa9cd75b5b516e502deb888d3ba2285ac5e1c3bb91fc9eb552a24a716dc6e3 languageName: node linkType: hard -"@algolia/client-common@npm:4.17.0": - version: 4.17.0 - resolution: "@algolia/client-common@npm:4.17.0" +"@algolia/client-common@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/client-common@npm:4.20.0" dependencies: - "@algolia/requester-common": 4.17.0 - "@algolia/transporter": 4.17.0 - checksum: 05791d5483e16a0776a1fb16f42a8e62c67be844e82ff506b5ed82669367f6ea5fba79bcffa90ff4af2039bd8fb16db395edc4c0b1e0c11c050de8a118642180 + "@algolia/requester-common": 4.20.0 + "@algolia/transporter": 4.20.0 + checksum: 88a27b5f8bba38349e1dbe47634e2ee159a413ff1a3baf6a65fbf244835f8d368e9f0a5ccce8bfe94ec405b38608be5bed45bcb140517f3aba6fe3b7045db373 languageName: node linkType: hard -"@algolia/client-personalization@npm:4.17.0": - version: 4.17.0 - resolution: "@algolia/client-personalization@npm:4.17.0" +"@algolia/client-personalization@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/client-personalization@npm:4.20.0" dependencies: - "@algolia/client-common": 4.17.0 - "@algolia/requester-common": 4.17.0 - "@algolia/transporter": 4.17.0 - checksum: 01e08bd8919d30469bfb01acd221528b3a25b56ac5a4754353e87d73643fe85e0126b1ab070bdb2b6d442fc260f4f781b95cbd5c1363fca5ba37a0a2bf6292b2 + "@algolia/client-common": 4.20.0 + "@algolia/requester-common": 4.20.0 + "@algolia/transporter": 4.20.0 + checksum: ddb92ebe135564e03db6ac75da7fdc1c7500a0deffb7e41d5a02a413216a06daea008f8062dab606ba8af4c3c34e550354f48e6ea7b048882c385d915643799a languageName: node linkType: hard -"@algolia/client-search@npm:4.17.0": - version: 4.17.0 - resolution: "@algolia/client-search@npm:4.17.0" +"@algolia/client-search@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/client-search@npm:4.20.0" dependencies: - "@algolia/client-common": 4.17.0 - "@algolia/requester-common": 4.17.0 - "@algolia/transporter": 4.17.0 - checksum: ca6aedd67e69112e3a86086e48de4f38b9d127c2e606b345de58a528dd2d2016e70783cf446dfa669036c69ffbd0616f27b180cacb6ab0fafe85065b2b8d323f + "@algolia/client-common": 4.20.0 + "@algolia/requester-common": 4.20.0 + "@algolia/transporter": 4.20.0 + checksum: 9fb6624dab6753f336f3207ee2af3558baeec4772ef739b6f6ed6a754c366e2e8d62cbf1cf8b28d5f763bec276a0a5fc36db2bf6f53a707890a411afcf550e92 languageName: node linkType: hard @@ -120,55 +135,55 @@ __metadata: languageName: node linkType: hard -"@algolia/logger-common@npm:4.17.0": - version: 4.17.0 - resolution: "@algolia/logger-common@npm:4.17.0" - checksum: e6359266544ed9d9eab8d4217c126a8209f74fbd1e407f2249b886915a521e89e419dc6401a65389523f3bdffb3880c0a95578c3c437653f941ddb1095c37e08 +"@algolia/logger-common@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/logger-common@npm:4.20.0" + checksum: 06ed28f76b630c8e7597534b15138ab6f71c10dfc6e13f1fb1b76965b39c88fd1d9cb3fe6bb9d046de6533ebcbe5ad92e751bc36fabe98ceda39d1d5f47bb637 languageName: node linkType: hard -"@algolia/logger-console@npm:4.17.0": - version: 4.17.0 - resolution: "@algolia/logger-console@npm:4.17.0" +"@algolia/logger-console@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/logger-console@npm:4.20.0" dependencies: - "@algolia/logger-common": 4.17.0 - checksum: b58790af42258a586a2584154674dbe13802e05602ff000ce9c34cadc2b5d29a3d41af150bde3f29aa5711a468d56d4c7fd16a72a350243e81af794bfadab213 + "@algolia/logger-common": 4.20.0 + checksum: 721dffe37563e2998d4c361f09a05736b4baa141bfb7da25d50f890ba8257ac99845dd94b43d0d6db38e2fdab96508a726e184a00e5b1e83ef18a16da6fc716c languageName: node linkType: hard -"@algolia/requester-browser-xhr@npm:4.17.0": - version: 4.17.0 - resolution: "@algolia/requester-browser-xhr@npm:4.17.0" +"@algolia/requester-browser-xhr@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/requester-browser-xhr@npm:4.20.0" dependencies: - "@algolia/requester-common": 4.17.0 - checksum: 374247cf30887be1c4649d0cdee5b9bbd59c9bc663122e14e157c70978a87a58e8708956bc4b58fbe9ad5b31ee1014a097322f748d27ad9b9de051943f1ebba2 + "@algolia/requester-common": 4.20.0 + checksum: 669790c7dfd491318976b9d61d98d9785880d7385ba33669f3f8b9c66ea88320bcded82d34f58b5df74b2cb8beb62ef48a28d39117f7997be84348c9fa7f6132 languageName: node linkType: hard -"@algolia/requester-common@npm:4.17.0": - version: 4.17.0 - resolution: "@algolia/requester-common@npm:4.17.0" - checksum: 13ace23f53fc88677d896ae4506f04a5defd17f69b9611571e19dd45c91fda74a71acd27f799f55f88d550264b8f4477831d9ff546ffeb7257e35ec4ee983ca8 +"@algolia/requester-common@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/requester-common@npm:4.20.0" + checksum: 8580ffd2be146bbdb5d4a57668bba4a5014f406cb2e5c65f596db6babab46c48d30c6e4732034ee1f987970aa27dcdab567959d654fa5fa74c4bcaf98312a724 languageName: node linkType: hard -"@algolia/requester-node-http@npm:4.17.0": - version: 4.17.0 - resolution: "@algolia/requester-node-http@npm:4.17.0" +"@algolia/requester-node-http@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/requester-node-http@npm:4.20.0" dependencies: - "@algolia/requester-common": 4.17.0 - checksum: 9d5e9c90e300737620be2cb21dbdc3ffe9f37453893b62f3e1fce2678abb0e1bd8b95735ddffc25ab79692539ecf6dbcb7eb9e8f7cf405d73521d416ebfb39ca + "@algolia/requester-common": 4.20.0 + checksum: 7857114b59c67e0d22e8a7ff3f755d11534a1602a4fc80802d3b35802777880a4980420914ea4a6e3e21198f5bacb95906289ce1bb9372458bf6a60a723bee59 languageName: node linkType: hard -"@algolia/transporter@npm:4.17.0": - version: 4.17.0 - resolution: "@algolia/transporter@npm:4.17.0" +"@algolia/transporter@npm:4.20.0": + version: 4.20.0 + resolution: "@algolia/transporter@npm:4.20.0" dependencies: - "@algolia/cache-common": 4.17.0 - "@algolia/logger-common": 4.17.0 - "@algolia/requester-common": 4.17.0 - checksum: 1864bf9ccdf63f5090a89f44358c30317f549b4dc37dd8ce446383ca217c1a9737ab2749ca92394a320574690ea04134ae600c2a3f1f9d393549a5124079c2a6 + "@algolia/cache-common": 4.20.0 + "@algolia/logger-common": 4.20.0 + "@algolia/requester-common": 4.20.0 + checksum: f834d5c8fcb7dfa9b7044cb81e9fab44a32f9dd0c3868a0f85fe0de4f4d27ad11fdc9c3c78541bc944c2593f4be56517a8ce593309d062b8a46ca0d6fcb5dcbc languageName: node linkType: hard @@ -182,551 +197,357 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.18.6, @babel/code-frame@npm:^7.21.4, @babel/code-frame@npm:^7.8.3": - version: 7.21.4 - resolution: "@babel/code-frame@npm:7.21.4" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.8.3": + version: 7.22.13 + resolution: "@babel/code-frame@npm:7.22.13" dependencies: - "@babel/highlight": ^7.18.6 - checksum: e5390e6ec1ac58dcef01d4f18eaf1fd2f1325528661ff6d4a5de8979588b9f5a8e852a54a91b923846f7a5c681b217f0a45c2524eb9560553160cd963b7d592c + "@babel/highlight": ^7.22.13 + chalk: ^2.4.2 + checksum: 22e342c8077c8b77eeb11f554ecca2ba14153f707b85294fcf6070b6f6150aae88a7b7436dd88d8c9289970585f3fe5b9b941c5aa3aa26a6d5a8ef3f292da058 languageName: node linkType: hard -"@babel/compat-data@npm:^7.17.7, @babel/compat-data@npm:^7.20.5, @babel/compat-data@npm:^7.21.4": - version: 7.21.4 - resolution: "@babel/compat-data@npm:7.21.4" - checksum: 5f8b98c66f2ffba9f3c3a82c0cf354c52a0ec5ad4797b370dc32bdcd6e136ac4febe5e93d76ce76e175632e2dbf6ce9f46319aa689fcfafa41b6e49834fa4b66 +"@babel/compat-data@npm:^7.22.20, @babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.22.9": + version: 7.22.20 + resolution: "@babel/compat-data@npm:7.22.20" + checksum: efedd1d18878c10fde95e4d82b1236a9aba41395ef798cbb651f58dbf5632dbff475736c507b8d13d4c8f44809d41c0eb2ef0d694283af9ba5dd8339b6dab451 languageName: node linkType: hard -"@babel/core@npm:^7.19.6, @babel/core@npm:^7.20.12": - version: 7.21.4 - resolution: "@babel/core@npm:7.21.4" +"@babel/core@npm:^7.19.6, @babel/core@npm:^7.22.9": + version: 7.23.0 + resolution: "@babel/core@npm:7.23.0" dependencies: "@ampproject/remapping": ^2.2.0 - "@babel/code-frame": ^7.21.4 - "@babel/generator": ^7.21.4 - "@babel/helper-compilation-targets": ^7.21.4 - "@babel/helper-module-transforms": ^7.21.2 - "@babel/helpers": ^7.21.0 - "@babel/parser": ^7.21.4 - "@babel/template": ^7.20.7 - "@babel/traverse": ^7.21.4 - "@babel/types": ^7.21.4 - convert-source-map: ^1.7.0 + "@babel/code-frame": ^7.22.13 + "@babel/generator": ^7.23.0 + "@babel/helper-compilation-targets": ^7.22.15 + "@babel/helper-module-transforms": ^7.23.0 + "@babel/helpers": ^7.23.0 + "@babel/parser": ^7.23.0 + "@babel/template": ^7.22.15 + "@babel/traverse": ^7.23.0 + "@babel/types": ^7.23.0 + convert-source-map: ^2.0.0 debug: ^4.1.0 gensync: ^1.0.0-beta.2 - json5: ^2.2.2 - semver: ^6.3.0 - checksum: a3beebb2cc79908a02f27a07dc381bcb34e8ecc58fa99f568ad0934c49e12111fc977ee9c5b51eb7ea2da66f63155d37c4dd96b6472eaeecfc35843ccb56bf3d + json5: ^2.2.3 + semver: ^6.3.1 + checksum: cebd9b48dbc970a7548522f207f245c69567e5ea17ebb1a4e4de563823cf20a01177fe8d2fe19b6e1461361f92fa169fd0b29f8ee9d44eeec84842be1feee5f2 languageName: node linkType: hard -"@babel/generator@npm:^7.21.1, @babel/generator@npm:^7.21.4": - version: 7.21.4 - resolution: "@babel/generator@npm:7.21.4" +"@babel/generator@npm:^7.22.9, @babel/generator@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/generator@npm:7.23.0" dependencies: - "@babel/types": ^7.21.4 + "@babel/types": ^7.23.0 "@jridgewell/gen-mapping": ^0.3.2 "@jridgewell/trace-mapping": ^0.3.17 jsesc: ^2.5.1 - checksum: 9ffbb526a53bb8469b5402f7b5feac93809b09b2a9f82fcbfcdc5916268a65dae746a1f2479e03ba4fb0776facd7c892191f63baa61ab69b2cfdb24f7b92424d + checksum: 8efe24adad34300f1f8ea2add420b28171a646edc70f2a1b3e1683842f23b8b7ffa7e35ef0119294e1901f45bfea5b3dc70abe1f10a1917ccdfb41bed69be5f1 languageName: node linkType: hard -"@babel/helper-annotate-as-pure@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-annotate-as-pure@npm:7.18.6" +"@babel/helper-annotate-as-pure@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-annotate-as-pure@npm:7.22.5" dependencies: - "@babel/types": ^7.18.6 - checksum: 88ccd15ced475ef2243fdd3b2916a29ea54c5db3cd0cfabf9d1d29ff6e63b7f7cd1c27264137d7a40ac2e978b9b9a542c332e78f40eb72abe737a7400788fc1b + "@babel/types": ^7.22.5 + checksum: 53da330f1835c46f26b7bf4da31f7a496dee9fd8696cca12366b94ba19d97421ce519a74a837f687749318f94d1a37f8d1abcbf35e8ed22c32d16373b2f6198d languageName: node linkType: hard -"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.18.6": - version: 7.18.9 - resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.18.9" +"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.22.5": + version: 7.22.15 + resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.22.15" dependencies: - "@babel/helper-explode-assignable-expression": ^7.18.6 - "@babel/types": ^7.18.9 - checksum: b4bc214cb56329daff6cc18a7f7a26aeafb55a1242e5362f3d47fe3808421f8c7cd91fff95d6b9b7ccb67e14e5a67d944e49dbe026942bfcbfda19b1c72a8e72 + "@babel/types": ^7.22.15 + checksum: 639c697a1c729f9fafa2dd4c9af2e18568190299b5907bd4c2d0bc818fcbd1e83ffeecc2af24327a7faa7ac4c34edd9d7940510a5e66296c19bad17001cf5c7a languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.17.7, @babel/helper-compilation-targets@npm:^7.18.9, @babel/helper-compilation-targets@npm:^7.20.7, @babel/helper-compilation-targets@npm:^7.21.4": - version: 7.21.4 - resolution: "@babel/helper-compilation-targets@npm:7.21.4" +"@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: - "@babel/compat-data": ^7.21.4 - "@babel/helper-validator-option": ^7.21.0 - browserslist: ^4.21.3 + "@babel/compat-data": ^7.22.9 + "@babel/helper-validator-option": ^7.22.15 + browserslist: ^4.21.9 lru-cache: ^5.1.1 - semver: ^6.3.0 - peerDependencies: - "@babel/core": ^7.0.0 - checksum: bf9c7d3e7e6adff9222c05d898724cd4ee91d7eb9d52222c7ad2a22955620c2872cc2d9bdf0e047df8efdb79f4e3af2a06b53f509286145feccc4d10ddc318be + semver: ^6.3.1 + checksum: ce85196769e091ae54dd39e4a80c2a9df1793da8588e335c383d536d54f06baf648d0a08fc873044f226398c4ded15c4ae9120ee18e7dfd7c639a68e3cdc9980 languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.21.0": - version: 7.21.4 - resolution: "@babel/helper-create-class-features-plugin@npm:7.21.4" +"@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: - "@babel/helper-annotate-as-pure": ^7.18.6 - "@babel/helper-environment-visitor": ^7.18.9 - "@babel/helper-function-name": ^7.21.0 - "@babel/helper-member-expression-to-functions": ^7.21.0 - "@babel/helper-optimise-call-expression": ^7.18.6 - "@babel/helper-replace-supers": ^7.20.7 - "@babel/helper-skip-transparent-expression-wrappers": ^7.20.0 - "@babel/helper-split-export-declaration": ^7.18.6 + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-environment-visitor": ^7.22.5 + "@babel/helper-function-name": ^7.22.5 + "@babel/helper-member-expression-to-functions": ^7.22.15 + "@babel/helper-optimise-call-expression": ^7.22.5 + "@babel/helper-replace-supers": ^7.22.9 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0 - checksum: 9123ca80a4894aafdb1f0bc08e44f6be7b12ed1fbbe99c501b484f9b1a17ff296b6c90c18c222047d53c276f07f17b4de857946fa9d0aa207023b03e4cc716f2 + checksum: 52c500d8d164abb3a360b1b7c4b8fff77bc4a5920d3a2b41ae6e1d30617b0dc0b972c1f5db35b1752007e04a748908b4a99bc872b73549ae837e87dcdde005a3 languageName: node linkType: hard -"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.20.5": - version: 7.20.5 - resolution: "@babel/helper-create-regexp-features-plugin@npm:7.20.5" +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.22.5": + version: 7.22.15 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.15" dependencies: - "@babel/helper-annotate-as-pure": ^7.18.6 - regexpu-core: ^5.2.1 + "@babel/helper-annotate-as-pure": ^7.22.5 + regexpu-core: ^5.3.1 + semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0 - checksum: 7f29c3cb7447cca047b0d394f8ab98e4923d00e86a7afa56e5df9770c48ec107891505d2d1f06b720ecc94ed24bf58d90986cc35fe4a43b549eb7b7a5077b693 + checksum: 0243b8d4854f1dc8861b1029a46d3f6393ad72f366a5a08e36a4648aa682044f06da4c6e87a456260e1e1b33c999f898ba591a0760842c1387bcc93fbf2151a6 languageName: node linkType: hard -"@babel/helper-define-polyfill-provider@npm:^0.3.3": - version: 0.3.3 - resolution: "@babel/helper-define-polyfill-provider@npm:0.3.3" +"@babel/helper-define-polyfill-provider@npm:^0.4.2": + version: 0.4.2 + resolution: "@babel/helper-define-polyfill-provider@npm:0.4.2" dependencies: - "@babel/helper-compilation-targets": ^7.17.7 - "@babel/helper-plugin-utils": ^7.16.7 + "@babel/helper-compilation-targets": ^7.22.6 + "@babel/helper-plugin-utils": ^7.22.5 debug: ^4.1.1 lodash.debounce: ^4.0.8 resolve: ^1.14.2 - semver: ^6.1.2 peerDependencies: - "@babel/core": ^7.4.0-0 - checksum: 8e3fe75513302e34f6d92bd67b53890e8545e6c5bca8fe757b9979f09d68d7e259f6daea90dc9e01e332c4f8781bda31c5fe551c82a277f9bc0bec007aed497c + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 1f6dec0c5d0876d278fe15b71238eccc5f74c4e2efa2c78aaafa8bc2cc96336b8e68d94cd1a78497356c96e8b91b8c1f4452179820624d1702aee2f9832e6569 languageName: node linkType: hard -"@babel/helper-environment-visitor@npm:^7.18.9": - version: 7.18.9 - resolution: "@babel/helper-environment-visitor@npm:7.18.9" - checksum: b25101f6162ddca2d12da73942c08ad203d7668e06663df685634a8fde54a98bc015f6f62938e8554457a592a024108d45b8f3e651fd6dcdb877275b73cc4420 +"@babel/helper-environment-visitor@npm:^7.22.20, @babel/helper-environment-visitor@npm:^7.22.5": + version: 7.22.20 + resolution: "@babel/helper-environment-visitor@npm:7.22.20" + checksum: d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 languageName: node linkType: hard -"@babel/helper-explode-assignable-expression@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-explode-assignable-expression@npm:7.18.6" +"@babel/helper-function-name@npm:^7.22.5, @babel/helper-function-name@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-function-name@npm:7.23.0" dependencies: - "@babel/types": ^7.18.6 - checksum: 225cfcc3376a8799023d15dc95000609e9d4e7547b29528c7f7111a0e05493ffb12c15d70d379a0bb32d42752f340233c4115bded6d299bc0c3ab7a12be3d30f + "@babel/template": ^7.22.15 + "@babel/types": ^7.23.0 + checksum: e44542257b2d4634a1f979244eb2a4ad8e6d75eb6761b4cfceb56b562f7db150d134bc538c8e6adca3783e3bc31be949071527aa8e3aab7867d1ad2d84a26e10 languageName: node linkType: hard -"@babel/helper-function-name@npm:^7.18.9, @babel/helper-function-name@npm:^7.19.0, @babel/helper-function-name@npm:^7.21.0": - version: 7.21.0 - resolution: "@babel/helper-function-name@npm:7.21.0" +"@babel/helper-hoist-variables@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-hoist-variables@npm:7.22.5" dependencies: - "@babel/template": ^7.20.7 - "@babel/types": ^7.21.0 - checksum: d63e63c3e0e3e8b3138fa47b0cd321148a300ef12b8ee951196994dcd2a492cc708aeda94c2c53759a5c9177fffaac0fd8778791286746f72a000976968daf4e + "@babel/types": ^7.22.5 + checksum: 394ca191b4ac908a76e7c50ab52102669efe3a1c277033e49467913c7ed6f7c64d7eacbeabf3bed39ea1f41731e22993f763b1edce0f74ff8563fd1f380d92cc languageName: node linkType: hard -"@babel/helper-hoist-variables@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-hoist-variables@npm:7.18.6" +"@babel/helper-member-expression-to-functions@npm:^7.22.15": + version: 7.23.0 + resolution: "@babel/helper-member-expression-to-functions@npm:7.23.0" dependencies: - "@babel/types": ^7.18.6 - checksum: fd9c35bb435fda802bf9ff7b6f2df06308a21277c6dec2120a35b09f9de68f68a33972e2c15505c1a1a04b36ec64c9ace97d4a9e26d6097b76b4396b7c5fa20f + "@babel/types": ^7.23.0 + checksum: 494659361370c979ada711ca685e2efe9460683c36db1b283b446122596602c901e291e09f2f980ecedfe6e0f2bd5386cb59768285446530df10c14df1024e75 languageName: node linkType: hard -"@babel/helper-member-expression-to-functions@npm:^7.20.7, @babel/helper-member-expression-to-functions@npm:^7.21.0": - version: 7.21.0 - resolution: "@babel/helper-member-expression-to-functions@npm:7.21.0" +"@babel/helper-module-imports@npm:^7.22.15, @babel/helper-module-imports@npm:^7.22.5": + version: 7.22.15 + resolution: "@babel/helper-module-imports@npm:7.22.15" dependencies: - "@babel/types": ^7.21.0 - checksum: 49cbb865098195fe82ba22da3a8fe630cde30dcd8ebf8ad5f9a24a2b685150c6711419879cf9d99b94dad24cff9244d8c2a890d3d7ec75502cd01fe58cff5b5d + "@babel/types": ^7.22.15 + checksum: ecd7e457df0a46f889228f943ef9b4a47d485d82e030676767e6a2fdcbdaa63594d8124d4b55fd160b41c201025aec01fc27580352b1c87a37c9c6f33d116702 languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.18.6, @babel/helper-module-imports@npm:^7.21.4": - version: 7.21.4 - resolution: "@babel/helper-module-imports@npm:7.21.4" +"@babel/helper-module-transforms@npm:^7.22.5, @babel/helper-module-transforms@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-module-transforms@npm:7.23.0" dependencies: - "@babel/types": ^7.21.4 - checksum: bd330a2edaafeb281fbcd9357652f8d2666502567c0aad71db926e8499c773c9ea9c10dfaae30122452940326d90c8caff5c649ed8e1bf15b23f858758d3abc6 - languageName: node - linkType: hard - -"@babel/helper-module-transforms@npm:^7.18.6, @babel/helper-module-transforms@npm:^7.20.11, @babel/helper-module-transforms@npm:^7.21.2": - version: 7.21.2 - resolution: "@babel/helper-module-transforms@npm:7.21.2" - dependencies: - "@babel/helper-environment-visitor": ^7.18.9 - "@babel/helper-module-imports": ^7.18.6 - "@babel/helper-simple-access": ^7.20.2 - "@babel/helper-split-export-declaration": ^7.18.6 - "@babel/helper-validator-identifier": ^7.19.1 - "@babel/template": ^7.20.7 - "@babel/traverse": ^7.21.2 - "@babel/types": ^7.21.2 - checksum: 8a1c129a4f90bdf97d8b6e7861732c9580f48f877aaaafbc376ce2482febebcb8daaa1de8bc91676d12886487603f8c62a44f9e90ee76d6cac7f9225b26a49e1 - languageName: node - linkType: hard - -"@babel/helper-optimise-call-expression@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-optimise-call-expression@npm:7.18.6" - dependencies: - "@babel/types": ^7.18.6 - checksum: e518fe8418571405e21644cfb39cf694f30b6c47b10b006609a92469ae8b8775cbff56f0b19732343e2ea910641091c5a2dc73b56ceba04e116a33b0f8bd2fbd - 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.16.7, @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.20.2, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": - version: 7.20.2 - resolution: "@babel/helper-plugin-utils@npm:7.20.2" - checksum: f6cae53b7fdb1bf3abd50fa61b10b4470985b400cc794d92635da1e7077bb19729f626adc0741b69403d9b6e411cddddb9c0157a709cc7c4eeb41e663be5d74b - languageName: node - linkType: hard - -"@babel/helper-remap-async-to-generator@npm:^7.18.9": - version: 7.18.9 - resolution: "@babel/helper-remap-async-to-generator@npm:7.18.9" - dependencies: - "@babel/helper-annotate-as-pure": ^7.18.6 - "@babel/helper-environment-visitor": ^7.18.9 - "@babel/helper-wrap-function": ^7.18.9 - "@babel/types": ^7.18.9 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-module-imports": ^7.22.15 + "@babel/helper-simple-access": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + "@babel/helper-validator-identifier": ^7.22.20 peerDependencies: "@babel/core": ^7.0.0 - checksum: 4be6076192308671b046245899b703ba090dbe7ad03e0bea897bb2944ae5b88e5e85853c9d1f83f643474b54c578d8ac0800b80341a86e8538264a725fbbefec + checksum: 6e2afffb058cf3f8ce92f5116f710dda4341c81cfcd872f9a0197ea594f7ce0ab3cb940b0590af2fe99e60d2e5448bfba6bca8156ed70a2ed4be2adc8586c891 languageName: node linkType: hard -"@babel/helper-replace-supers@npm:^7.18.6, @babel/helper-replace-supers@npm:^7.20.7": - version: 7.20.7 - resolution: "@babel/helper-replace-supers@npm:7.20.7" +"@babel/helper-optimise-call-expression@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-optimise-call-expression@npm:7.22.5" dependencies: - "@babel/helper-environment-visitor": ^7.18.9 - "@babel/helper-member-expression-to-functions": ^7.20.7 - "@babel/helper-optimise-call-expression": ^7.18.6 - "@babel/template": ^7.20.7 - "@babel/traverse": ^7.20.7 - "@babel/types": ^7.20.7 - checksum: b8e0087c9b0c1446e3c6f3f72b73b7e03559c6b570e2cfbe62c738676d9ebd8c369a708cf1a564ef88113b4330750a50232ee1131d303d478b7a5e65e46fbc7c + "@babel/types": ^7.22.5 + checksum: c70ef6cc6b6ed32eeeec4482127e8be5451d0e5282d5495d5d569d39eb04d7f1d66ec99b327f45d1d5842a9ad8c22d48567e93fc502003a47de78d122e355f7c languageName: node linkType: hard -"@babel/helper-simple-access@npm:^7.20.2": - version: 7.20.2 - resolution: "@babel/helper-simple-access@npm:7.20.2" +"@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.20.2, @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 + languageName: node + linkType: hard + +"@babel/helper-remap-async-to-generator@npm:^7.22.5, @babel/helper-remap-async-to-generator@npm:^7.22.9": + version: 7.22.20 + resolution: "@babel/helper-remap-async-to-generator@npm:7.22.20" dependencies: - "@babel/types": ^7.20.2 - checksum: ad1e96ee2e5f654ffee2369a586e5e8d2722bf2d8b028a121b4c33ebae47253f64d420157b9f0a8927aea3a9e0f18c0103e74fdd531815cf3650a0a4adca11a1 + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-wrap-function": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 2fe6300a6f1b58211dffa0aed1b45d4958506d096543663dba83bd9251fe8d670fa909143a65b45e72acb49e7e20fbdb73eae315d9ddaced467948c3329986e7 languageName: node linkType: hard -"@babel/helper-skip-transparent-expression-wrappers@npm:^7.20.0": - version: 7.20.0 - resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.20.0" +"@babel/helper-replace-supers@npm:^7.22.5, @babel/helper-replace-supers@npm:^7.22.9": + version: 7.22.20 + resolution: "@babel/helper-replace-supers@npm:7.22.20" dependencies: - "@babel/types": ^7.20.0 - checksum: 34da8c832d1c8a546e45d5c1d59755459ffe43629436707079989599b91e8c19e50e73af7a4bd09c95402d389266731b0d9c5f69e372d8ebd3a709c05c80d7dd + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-member-expression-to-functions": ^7.22.15 + "@babel/helper-optimise-call-expression": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: a0008332e24daedea2e9498733e3c39b389d6d4512637e000f96f62b797e702ee24a407ccbcd7a236a551590a38f31282829a8ef35c50a3c0457d88218cae639 languageName: node linkType: hard -"@babel/helper-split-export-declaration@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/helper-split-export-declaration@npm:7.18.6" +"@babel/helper-simple-access@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-simple-access@npm:7.22.5" dependencies: - "@babel/types": ^7.18.6 - checksum: c6d3dede53878f6be1d869e03e9ffbbb36f4897c7cc1527dc96c56d127d834ffe4520a6f7e467f5b6f3c2843ea0e81a7819d66ae02f707f6ac057f3d57943a2b + "@babel/types": ^7.22.5 + checksum: fe9686714caf7d70aedb46c3cce090f8b915b206e09225f1e4dbc416786c2fdbbee40b38b23c268b7ccef749dd2db35f255338fb4f2444429874d900dede5ad2 languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.19.4": - version: 7.19.4 - resolution: "@babel/helper-string-parser@npm:7.19.4" - checksum: b2f8a3920b30dfac81ec282ac4ad9598ea170648f8254b10f475abe6d944808fb006aab325d3eb5a8ad3bea8dfa888cfa6ef471050dae5748497c110ec060943 - languageName: node - linkType: hard - -"@babel/helper-validator-identifier@npm:^7.18.6, @babel/helper-validator-identifier@npm:^7.19.1": - version: 7.19.1 - resolution: "@babel/helper-validator-identifier@npm:7.19.1" - checksum: 0eca5e86a729162af569b46c6c41a63e18b43dbe09fda1d2a3c8924f7d617116af39cac5e4cd5d431bb760b4dca3c0970e0c444789b1db42bcf1fa41fbad0a3a - languageName: node - linkType: hard - -"@babel/helper-validator-option@npm:^7.18.6, @babel/helper-validator-option@npm:^7.21.0": - version: 7.21.0 - resolution: "@babel/helper-validator-option@npm:7.21.0" - checksum: 8ece4c78ffa5461fd8ab6b6e57cc51afad59df08192ed5d84b475af4a7193fc1cb794b59e3e7be64f3cdc4df7ac78bf3dbb20c129d7757ae078e6279ff8c2f07 - languageName: node - linkType: hard - -"@babel/helper-wrap-function@npm:^7.18.9": - version: 7.20.5 - resolution: "@babel/helper-wrap-function@npm:7.20.5" +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.22.5" dependencies: - "@babel/helper-function-name": ^7.19.0 - "@babel/template": ^7.18.10 - "@babel/traverse": ^7.20.5 - "@babel/types": ^7.20.5 - checksum: 11a6fc28334368a193a9cb3ad16f29cd7603bab958433efc82ebe59fa6556c227faa24f07ce43983f7a85df826f71d441638442c4315e90a554fe0a70ca5005b + "@babel/types": ^7.22.5 + checksum: 1012ef2295eb12dc073f2b9edf3425661e9b8432a3387e62a8bc27c42963f1f216ab3124228015c748770b2257b4f1fda882ca8fa34c0bf485e929ae5bc45244 languageName: node linkType: hard -"@babel/helpers@npm:^7.21.0": - version: 7.21.0 - resolution: "@babel/helpers@npm:7.21.0" +"@babel/helper-split-export-declaration@npm:^7.22.6": + version: 7.22.6 + resolution: "@babel/helper-split-export-declaration@npm:7.22.6" dependencies: - "@babel/template": ^7.20.7 - "@babel/traverse": ^7.21.0 - "@babel/types": ^7.21.0 - checksum: 9370dad2bb665c551869a08ac87c8bdafad53dbcdce1f5c5d498f51811456a3c005d9857562715151a0f00b2e912ac8d89f56574f837b5689f5f5072221cdf54 + "@babel/types": ^7.22.5 + checksum: e141cace583b19d9195f9c2b8e17a3ae913b7ee9b8120246d0f9ca349ca6f03cb2c001fd5ec57488c544347c0bb584afec66c936511e447fd20a360e591ac921 languageName: node linkType: hard -"@babel/highlight@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/highlight@npm:7.18.6" +"@babel/helper-string-parser@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-string-parser@npm:7.22.5" + checksum: 836851ca5ec813077bbb303acc992d75a360267aa3b5de7134d220411c852a6f17de7c0d0b8c8dcc0f567f67874c00f4528672b2a4f1bc978a3ada64c8c78467 + languageName: node + linkType: hard + +"@babel/helper-validator-identifier@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-validator-identifier@npm:7.22.20" + checksum: 136412784d9428266bcdd4d91c32bcf9ff0e8d25534a9d94b044f77fe76bc50f941a90319b05aafd1ec04f7d127cd57a179a3716009ff7f3412ef835ada95bdc + languageName: node + linkType: hard + +"@babel/helper-validator-option@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-validator-option@npm:7.22.15" + checksum: 68da52b1e10002a543161494c4bc0f4d0398c8fdf361d5f7f4272e95c45d5b32d974896d44f6a0ea7378c9204988879d73613ca683e13bd1304e46d25ff67a8d + languageName: node + linkType: hard + +"@babel/helper-wrap-function@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-wrap-function@npm:7.22.20" dependencies: - "@babel/helper-validator-identifier": ^7.18.6 - chalk: ^2.0.0 + "@babel/helper-function-name": ^7.22.5 + "@babel/template": ^7.22.15 + "@babel/types": ^7.22.19 + checksum: 221ed9b5572612aeb571e4ce6a256f2dee85b3c9536f1dd5e611b0255e5f59a3d0ec392d8d46d4152149156a8109f92f20379b1d6d36abb613176e0e33f05fca + languageName: node + linkType: hard + +"@babel/helpers@npm:^7.23.0": + version: 7.23.1 + resolution: "@babel/helpers@npm:7.23.1" + dependencies: + "@babel/template": ^7.22.15 + "@babel/traverse": ^7.23.0 + "@babel/types": ^7.23.0 + checksum: acfc345102045c24ea2a4d60e00dcf8220e215af3add4520e2167700661338e6a80bd56baf44bb764af05ec6621101c9afc315dc107e18c61fa6da8acbdbb893 + languageName: node + linkType: hard + +"@babel/highlight@npm:^7.22.13": + version: 7.22.20 + resolution: "@babel/highlight@npm:7.22.20" + dependencies: + "@babel/helper-validator-identifier": ^7.22.20 + chalk: ^2.4.2 js-tokens: ^4.0.0 - checksum: 92d8ee61549de5ff5120e945e774728e5ccd57fd3b2ed6eace020ec744823d4a98e242be1453d21764a30a14769ecd62170fba28539b211799bbaf232bbb2789 + checksum: 84bd034dca309a5e680083cd827a766780ca63cef37308404f17653d32366ea76262bd2364b2d38776232f2d01b649f26721417d507e8b4b6da3e4e739f6d134 languageName: node linkType: hard -"@babel/parser@npm:^7.20.7, @babel/parser@npm:^7.21.2, @babel/parser@npm:^7.21.4": - version: 7.21.4 - resolution: "@babel/parser@npm:7.21.4" +"@babel/parser@npm:^7.22.15, @babel/parser@npm:^7.22.7, @babel/parser@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/parser@npm:7.23.0" bin: parser: ./bin/babel-parser.js - checksum: de610ecd1bff331766d0c058023ca11a4f242bfafefc42caf926becccfb6756637d167c001987ca830dd4b34b93c629a4cef63f8c8c864a8564cdfde1989ac77 + checksum: 453fdf8b9e2c2b7d7b02139e0ce003d1af21947bbc03eb350fb248ee335c9b85e4ab41697ddbdd97079698de825a265e45a0846bb2ed47a2c7c1df833f42a354 languageName: node linkType: hard -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.18.6" +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.22.15" dependencies: - "@babel/helper-plugin-utils": ^7.18.6 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0 - checksum: 845bd280c55a6a91d232cfa54eaf9708ec71e594676fe705794f494bb8b711d833b752b59d1a5c154695225880c23dbc9cab0e53af16fd57807976cd3ff41b8d + checksum: 8910ca21a7ec7c06f7b247d4b86c97c5aa15ef321518f44f6f490c5912fdf82c605aaa02b90892e375d82ccbedeadfdeadd922c1b836c9dd4c596871bf654753 languageName: node linkType: hard -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.20.7": - version: 7.20.7 - resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.20.7" +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.22.15" dependencies: - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/helper-skip-transparent-expression-wrappers": ^7.20.0 - "@babel/plugin-proposal-optional-chaining": ^7.20.7 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/plugin-transform-optional-chaining": ^7.22.15 peerDependencies: "@babel/core": ^7.13.0 - checksum: d610f532210bee5342f5b44a12395ccc6d904e675a297189bc1e401cc185beec09873da523466d7fec34ae1574f7a384235cba1ccc9fe7b89ba094167897c845 + checksum: fbefedc0da014c37f1a50a8094ce7dbbf2181ae93243f23d6ecba2499b5b20196c2124d6a4dfe3e9e0125798e80593103e456352a4beb4e5c6f7c75efb80fdac languageName: node linkType: hard -"@babel/plugin-proposal-async-generator-functions@npm:^7.20.7": - version: 7.20.7 - resolution: "@babel/plugin-proposal-async-generator-functions@npm:7.20.7" - dependencies: - "@babel/helper-environment-visitor": ^7.18.9 - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/helper-remap-async-to-generator": ^7.18.9 - "@babel/plugin-syntax-async-generators": ^7.8.4 +"@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" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 111109ee118c9e69982f08d5e119eab04190b36a0f40e22e873802d941956eee66d2aa5a15f5321e51e3f9aa70a91136451b987fe15185ef8cc547ac88937723 - languageName: node - linkType: hard - -"@babel/plugin-proposal-class-properties@npm:^7.18.6": - 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-class-static-block@npm:^7.21.0": - version: 7.21.0 - resolution: "@babel/plugin-proposal-class-static-block@npm:7.21.0" - dependencies: - "@babel/helper-create-class-features-plugin": ^7.21.0 - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/plugin-syntax-class-static-block": ^7.14.5 - peerDependencies: - "@babel/core": ^7.12.0 - checksum: 236c0ad089e7a7acab776cc1d355330193314bfcd62e94e78f2df35817c6144d7e0e0368976778afd6b7c13e70b5068fa84d7abbf967d4f182e60d03f9ef802b - languageName: node - linkType: hard - -"@babel/plugin-proposal-dynamic-import@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-proposal-dynamic-import@npm:7.18.6" - dependencies: - "@babel/helper-plugin-utils": ^7.18.6 - "@babel/plugin-syntax-dynamic-import": ^7.8.3 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 96b1c8a8ad8171d39e9ab106be33bde37ae09b22fb2c449afee9a5edf3c537933d79d963dcdc2694d10677cb96da739cdf1b53454e6a5deab9801f28a818bb2f - languageName: node - linkType: hard - -"@babel/plugin-proposal-export-namespace-from@npm:^7.18.9": - version: 7.18.9 - resolution: "@babel/plugin-proposal-export-namespace-from@npm:7.18.9" - dependencies: - "@babel/helper-plugin-utils": ^7.18.9 - "@babel/plugin-syntax-export-namespace-from": ^7.8.3 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 84ff22bacc5d30918a849bfb7e0e90ae4c5b8d8b65f2ac881803d1cf9068dffbe53bd657b0e4bc4c20b4db301b1c85f1e74183cf29a0dd31e964bd4e97c363ef - languageName: node - linkType: hard - -"@babel/plugin-proposal-json-strings@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-proposal-json-strings@npm:7.18.6" - dependencies: - "@babel/helper-plugin-utils": ^7.18.6 - "@babel/plugin-syntax-json-strings": ^7.8.3 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 25ba0e6b9d6115174f51f7c6787e96214c90dd4026e266976b248a2ed417fe50fddae72843ffb3cbe324014a18632ce5648dfac77f089da858022b49fd608cb3 - languageName: node - linkType: hard - -"@babel/plugin-proposal-logical-assignment-operators@npm:^7.20.7": - version: 7.20.7 - resolution: "@babel/plugin-proposal-logical-assignment-operators@npm:7.20.7" - dependencies: - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: cdd7b8136cc4db3f47714d5266f9e7b592a2ac5a94a5878787ce08890e97c8ab1ca8e94b27bfeba7b0f2b1549a026d9fc414ca2196de603df36fb32633bbdc19 - languageName: node - linkType: hard - -"@babel/plugin-proposal-nullish-coalescing-operator@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-proposal-nullish-coalescing-operator@npm:7.18.6" - dependencies: - "@babel/helper-plugin-utils": ^7.18.6 - "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 949c9ddcdecdaec766ee610ef98f965f928ccc0361dd87cf9f88cf4896a6ccd62fce063d4494778e50da99dea63d270a1be574a62d6ab81cbe9d85884bf55a7d - languageName: node - linkType: hard - -"@babel/plugin-proposal-numeric-separator@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-proposal-numeric-separator@npm:7.18.6" - dependencies: - "@babel/helper-plugin-utils": ^7.18.6 - "@babel/plugin-syntax-numeric-separator": ^7.10.4 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: f370ea584c55bf4040e1f78c80b4eeb1ce2e6aaa74f87d1a48266493c33931d0b6222d8cee3a082383d6bb648ab8d6b7147a06f974d3296ef3bc39c7851683ec - languageName: node - linkType: hard - -"@babel/plugin-proposal-object-rest-spread@npm:^7.20.7": - version: 7.20.7 - resolution: "@babel/plugin-proposal-object-rest-spread@npm:7.20.7" - dependencies: - "@babel/compat-data": ^7.20.5 - "@babel/helper-compilation-targets": ^7.20.7 - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/plugin-syntax-object-rest-spread": ^7.8.3 - "@babel/plugin-transform-parameters": ^7.20.7 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 1329db17009964bc644484c660eab717cb3ca63ac0ab0f67c651a028d1bc2ead51dc4064caea283e46994f1b7221670a35cbc0b4beb6273f55e915494b5aa0b2 - languageName: node - linkType: hard - -"@babel/plugin-proposal-optional-catch-binding@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-proposal-optional-catch-binding@npm:7.18.6" - dependencies: - "@babel/helper-plugin-utils": ^7.18.6 - "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 7b5b39fb5d8d6d14faad6cb68ece5eeb2fd550fb66b5af7d7582402f974f5bc3684641f7c192a5a57e0f59acfae4aada6786be1eba030881ddc590666eff4d1e - languageName: node - linkType: hard - -"@babel/plugin-proposal-optional-chaining@npm:^7.20.7, @babel/plugin-proposal-optional-chaining@npm:^7.21.0": - version: 7.21.0 - resolution: "@babel/plugin-proposal-optional-chaining@npm:7.21.0" - dependencies: - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/helper-skip-transparent-expression-wrappers": ^7.20.0 - "@babel/plugin-syntax-optional-chaining": ^7.8.3 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 11c5449e01b18bb8881e8e005a577fa7be2fe5688e2382c8822d51f8f7005342a301a46af7b273b1f5645f9a7b894c428eee8526342038a275ef6ba4c8d8d746 - languageName: node - linkType: hard - -"@babel/plugin-proposal-private-methods@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-proposal-private-methods@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: 22d8502ee96bca99ad2c8393e8493e2b8d4507576dd054490fd8201a36824373440106f5b098b6d821b026c7e72b0424ff4aeca69ed5f42e48f029d3a156d5ad - languageName: node - linkType: hard - -"@babel/plugin-proposal-private-property-in-object@npm:^7.21.0": - version: 7.21.0 - resolution: "@babel/plugin-proposal-private-property-in-object@npm:7.21.0" - dependencies: - "@babel/helper-annotate-as-pure": ^7.18.6 - "@babel/helper-create-class-features-plugin": ^7.21.0 - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/plugin-syntax-private-property-in-object": ^7.14.5 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: add881a6a836635c41d2710551fdf777e2c07c0b691bf2baacc5d658dd64107479df1038680d6e67c468bfc6f36fb8920025d6bac2a1df0a81b867537d40ae78 - languageName: node - linkType: hard - -"@babel/plugin-proposal-unicode-property-regex@npm:^7.18.6, @babel/plugin-proposal-unicode-property-regex@npm:^7.4.4": - version: 7.18.6 - resolution: "@babel/plugin-proposal-unicode-property-regex@npm:7.18.6" - dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.18.6 - "@babel/helper-plugin-utils": ^7.18.6 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: a8575ecb7ff24bf6c6e94808d5c84bb5a0c6dd7892b54f09f4646711ba0ee1e1668032b3c43e3e1dfec2c5716c302e851ac756c1645e15882d73df6ad21ae951 + checksum: d97745d098b835d55033ff3a7fb2b895b9c5295b08a5759e4f20df325aa385a3e0bc9bd5ad8f2ec554a44d4e6525acfc257b8c5848a1345cb40f26a30e277e91 languageName: node linkType: hard @@ -785,14 +606,36 @@ __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" +"@babel/plugin-syntax-import-assertions@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.19.0 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 6a86220e0aae40164cd3ffaf80e7c076a1be02a8f3480455dddbae05fda8140f429290027604df7a11b3f3f124866e8a6d69dbfa1dda61ee7377b920ad144d5b + checksum: 2b8b5572db04a7bef1e6cd20debf447e4eef7cb012616f5eceb8fa3e23ce469b8f76ee74fd6d1e158ba17a8f58b0aec579d092fb67c5a30e83ccfbc5754916c1 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-attributes@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.22.5" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 197b3c5ea2a9649347f033342cb222ab47f4645633695205c0250c6bf2af29e643753b8bb24a2db39948bef08e7c540babfd365591eb57fc110cb30b425ffc47 + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-meta@npm:^7.10.4": + version: 7.10.4 + resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" + dependencies: + "@babel/helper-plugin-utils": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 166ac1125d10b9c0c430e4156249a13858c0366d38844883d75d27389621ebe651115cb2ceb6dc011534d5055719fa1727b59f39e1ab3ca97820eef3dcab5b9b languageName: node linkType: hard @@ -807,14 +650,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:^7.18.6, @babel/plugin-syntax-jsx@npm:^7.21.4": - version: 7.21.4 - resolution: "@babel/plugin-syntax-jsx@npm:7.21.4" +"@babel/plugin-syntax-jsx@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-syntax-jsx@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: bb7309402a1d4e155f32aa0cf216e1fa8324d6c4cfd248b03280028a015a10e46b6efd6565f515f8913918a3602b39255999c06046f7d4b8a5106be2165d724a + checksum: 8829d30c2617ab31393d99cec2978e41f014f4ac6f01a1cecf4c4dd8320c3ec12fdc3ce121126b2d8d32f6887e99ca1a0bad53dedb1e6ad165640b92b24980ce languageName: node linkType: hard @@ -906,291 +749,480 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-typescript@npm:^7.20.0": - version: 7.20.0 - resolution: "@babel/plugin-syntax-typescript@npm:7.20.0" +"@babel/plugin-syntax-typescript@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-syntax-typescript@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.19.0 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 6189c0b5c32ba3c9a80a42338bd50719d783b20ef29b853d4f03929e971913d3cefd80184e924ae98ad6db09080be8fe6f1ffde9a6db8972523234f0274d36f7 + checksum: 8ab7718fbb026d64da93681a57797d60326097fd7cb930380c8bffd9eb101689e90142c760a14b51e8e69c88a73ba3da956cb4520a3b0c65743aee5c71ef360a languageName: node linkType: hard -"@babel/plugin-transform-arrow-functions@npm:^7.20.7": - version: 7.20.7 - resolution: "@babel/plugin-transform-arrow-functions@npm:7.20.7" - dependencies: - "@babel/helper-plugin-utils": ^7.20.2 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: b43cabe3790c2de7710abe32df9a30005eddb2050dadd5d122c6872f679e5710e410f1b90c8f99a2aff7b614cccfecf30e7fd310236686f60d3ed43fd80b9847 - languageName: node - linkType: hard - -"@babel/plugin-transform-async-to-generator@npm:^7.20.7": - version: 7.20.7 - resolution: "@babel/plugin-transform-async-to-generator@npm:7.20.7" - dependencies: - "@babel/helper-module-imports": ^7.18.6 - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/helper-remap-async-to-generator": ^7.18.9 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: fe9ee8a5471b4317c1b9ea92410ace8126b52a600d7cfbfe1920dcac6fb0fad647d2e08beb4fd03c630eb54430e6c72db11e283e3eddc49615c68abd39430904 - languageName: node - linkType: hard - -"@babel/plugin-transform-block-scoped-functions@npm:^7.18.6": +"@babel/plugin-syntax-unicode-sets-regex@npm:^7.18.6": version: 7.18.6 - resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.18.6" - dependencies: - "@babel/helper-plugin-utils": ^7.18.6 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 0a0df61f94601e3666bf39f2cc26f5f7b22a94450fb93081edbed967bd752ce3f81d1227fefd3799f5ee2722171b5e28db61379234d1bb85b6ec689589f99d7e - languageName: node - linkType: hard - -"@babel/plugin-transform-block-scoping@npm:^7.21.0": - version: 7.21.0 - resolution: "@babel/plugin-transform-block-scoping@npm:7.21.0" - dependencies: - "@babel/helper-plugin-utils": ^7.20.2 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 15aacaadbecf96b53a750db1be4990b0d89c7f5bc3e1794b63b49fb219638c1fd25d452d15566d7e5ddf5b5f4e1a0a0055c35c1c7aee323c7b114bf49f66f4b0 - languageName: node - linkType: hard - -"@babel/plugin-transform-classes@npm:^7.21.0": - version: 7.21.0 - resolution: "@babel/plugin-transform-classes@npm:7.21.0" - dependencies: - "@babel/helper-annotate-as-pure": ^7.18.6 - "@babel/helper-compilation-targets": ^7.20.7 - "@babel/helper-environment-visitor": ^7.18.9 - "@babel/helper-function-name": ^7.21.0 - "@babel/helper-optimise-call-expression": ^7.18.6 - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/helper-replace-supers": ^7.20.7 - "@babel/helper-split-export-declaration": ^7.18.6 - globals: ^11.1.0 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 088ae152074bd0e90f64659169255bfe50393e637ec8765cb2a518848b11b0299e66b91003728fd0a41563a6fdc6b8d548ece698a314fd5447f5489c22e466b7 - languageName: node - linkType: hard - -"@babel/plugin-transform-computed-properties@npm:^7.20.7": - version: 7.20.7 - resolution: "@babel/plugin-transform-computed-properties@npm:7.20.7" - dependencies: - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/template": ^7.20.7 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: be70e54bda8b469146459f429e5f2bd415023b87b2d5af8b10e48f465ffb02847a3ed162ca60378c004b82db848e4d62e90010d41ded7e7176b6d8d1c2911139 - languageName: node - linkType: hard - -"@babel/plugin-transform-destructuring@npm:^7.21.3": - version: 7.21.3 - resolution: "@babel/plugin-transform-destructuring@npm:7.21.3" - dependencies: - "@babel/helper-plugin-utils": ^7.20.2 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 43ebbe0bfa20287e34427be7c2200ce096c20913775ea75268fb47fe0e55f9510800587e6052c42fe6dffa0daaad95dd465c3e312fd1ef9785648384c45417ac - languageName: node - linkType: hard - -"@babel/plugin-transform-dotall-regex@npm:^7.18.6, @babel/plugin-transform-dotall-regex@npm:^7.4.4": - version: 7.18.6 - resolution: "@babel/plugin-transform-dotall-regex@npm:7.18.6" + resolution: "@babel/plugin-syntax-unicode-sets-regex@npm:7.18.6" dependencies: "@babel/helper-create-regexp-features-plugin": ^7.18.6 "@babel/helper-plugin-utils": ^7.18.6 peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: cbe5d7063eb8f8cca24cd4827bc97f5641166509e58781a5f8aa47fb3d2d786ce4506a30fca2e01f61f18792783a5cb5d96bf5434c3dd1ad0de8c9cc625a53da + "@babel/core": ^7.0.0 + checksum: a651d700fe63ff0ddfd7186f4ebc24447ca734f114433139e3c027bc94a900d013cf1ef2e2db8430425ba542e39ae160c3b05f06b59fd4656273a3df97679e9c languageName: node linkType: hard -"@babel/plugin-transform-duplicate-keys@npm:^7.18.9": - version: 7.18.9 - resolution: "@babel/plugin-transform-duplicate-keys@npm:7.18.9" +"@babel/plugin-transform-arrow-functions@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.18.9 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 220bf4a9fec5c4d4a7b1de38810350260e8ea08481bf78332a464a21256a95f0df8cd56025f346238f09b04f8e86d4158fafc9f4af57abaef31637e3b58bd4fe + checksum: 35abb6c57062802c7ce8bd96b2ef2883e3124370c688bbd67609f7d2453802fb73944df8808f893b6c67de978eb2bcf87bbfe325e46d6f39b5fcb09ece11d01a languageName: node linkType: hard -"@babel/plugin-transform-exponentiation-operator@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.18.6" +"@babel/plugin-transform-async-generator-functions@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.22.15" dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor": ^7.18.6 - "@babel/helper-plugin-utils": ^7.18.6 + "@babel/helper-environment-visitor": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-remap-async-to-generator": ^7.22.9 + "@babel/plugin-syntax-async-generators": ^7.8.4 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 7f70222f6829c82a36005508d34ddbe6fd0974ae190683a8670dd6ff08669aaf51fef2209d7403f9bd543cb2d12b18458016c99a6ed0332ccedb3ea127b01229 + checksum: fad98786b446ce63bde0d14a221e2617eef5a7bbca62b49d96f16ab5e1694521234cfba6145b830fbf9af16d60a8a3dbf148e8694830bd91796fe333b0599e73 languageName: node linkType: hard -"@babel/plugin-transform-for-of@npm:^7.21.0": - version: 7.21.0 - resolution: "@babel/plugin-transform-for-of@npm:7.21.0" +"@babel/plugin-transform-async-to-generator@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-module-imports": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-remap-async-to-generator": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 2f3f86ca1fab2929fcda6a87e4303d5c635b5f96dc9a45fd4ca083308a3020c79ac33b9543eb4640ef2b79f3586a00ab2d002a7081adb9e9d7440dce30781034 + checksum: b95f23f99dcb379a9f0a1c2a3bbea3f8dc0e1b16dc1ac8b484fe378370169290a7a63d520959a9ba1232837cf74a80e23f6facbe14fd42a3cda6d3c2d7168e62 languageName: node linkType: hard -"@babel/plugin-transform-function-name@npm:^7.18.9": - version: 7.18.9 - resolution: "@babel/plugin-transform-function-name@npm:7.18.9" +"@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: - "@babel/helper-compilation-targets": ^7.18.9 - "@babel/helper-function-name": ^7.18.9 - "@babel/helper-plugin-utils": ^7.18.9 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 62dd9c6cdc9714704efe15545e782ee52d74dc73916bf954b4d3bee088fb0ec9e3c8f52e751252433656c09f744b27b757fc06ed99bcde28e8a21600a1d8e597 + checksum: 416b1341858e8ca4e524dee66044735956ced5f478b2c3b9bc11ec2285b0c25d7dbb96d79887169eb938084c95d0a89338c8b2fe70d473bd9dc92e5d9db1732c languageName: node linkType: hard -"@babel/plugin-transform-literals@npm:^7.18.9": - version: 7.18.9 - resolution: "@babel/plugin-transform-literals@npm:7.18.9" +"@babel/plugin-transform-block-scoping@npm:^7.22.15": + version: 7.23.0 + resolution: "@babel/plugin-transform-block-scoping@npm:7.23.0" dependencies: - "@babel/helper-plugin-utils": ^7.18.9 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 3458dd2f1a47ac51d9d607aa18f3d321cbfa8560a985199185bed5a906bb0c61ba85575d386460bac9aed43fdd98940041fae5a67dff286f6f967707cff489f8 + checksum: 0cfe925cc3b5a3ad407e2253fab3ceeaa117a4b291c9cb245578880872999bca91bd83ffa0128ae9ca356330702e1ef1dcb26804f28d2cef678239caf629f73e languageName: node linkType: hard -"@babel/plugin-transform-member-expression-literals@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-member-expression-literals@npm:7.18.6" +"@babel/plugin-transform-class-properties@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-class-properties@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.18.6 + "@babel/helper-create-class-features-plugin": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 35a3d04f6693bc6b298c05453d85ee6e41cc806538acb6928427e0e97ae06059f97d2f07d21495fcf5f70d3c13a242e2ecbd09d5c1fcb1b1a73ff528dcb0b695 + checksum: b830152dfc2ff2f647f0abe76e6251babdfbef54d18c4b2c73a6bf76b1a00050a5d998dac80dc901a48514e95604324943a9dd39317073fe0928b559e0e0c579 languageName: node linkType: hard -"@babel/plugin-transform-modules-amd@npm:^7.20.11": - version: 7.20.11 - resolution: "@babel/plugin-transform-modules-amd@npm:7.20.11" +"@babel/plugin-transform-class-static-block@npm:^7.22.11": + version: 7.22.11 + resolution: "@babel/plugin-transform-class-static-block@npm:7.22.11" dependencies: - "@babel/helper-module-transforms": ^7.20.11 - "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-create-class-features-plugin": ^7.22.11 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-class-static-block": ^7.14.5 + peerDependencies: + "@babel/core": ^7.12.0 + checksum: 69f040506fad66f1c6918d288d0e0edbc5c8a07c8b4462c1184ad2f9f08995d68b057126c213871c0853ae0c72afc60ec87492049dfacb20902e32346a448bcb + languageName: node + linkType: hard + +"@babel/plugin-transform-classes@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/plugin-transform-classes@npm:7.22.15" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-compilation-targets": ^7.22.15 + "@babel/helper-environment-visitor": ^7.22.5 + "@babel/helper-function-name": ^7.22.5 + "@babel/helper-optimise-call-expression": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-replace-supers": ^7.22.9 + "@babel/helper-split-export-declaration": ^7.22.6 + globals: ^11.1.0 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 23665c1c20c8f11c89382b588fb9651c0756d130737a7625baeaadbd3b973bc5bfba1303bedffa8fb99db1e6d848afb01016e1df2b69b18303e946890c790001 + checksum: d3f4d0c107dd8a3557ea3575cc777fab27efa92958b41e4a9822f7499725c1f554beae58855de16ddec0a7b694e45f59a26cea8fbde4275563f72f09c6e039a0 languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.21.2": - version: 7.21.2 - resolution: "@babel/plugin-transform-modules-commonjs@npm:7.21.2" +"@babel/plugin-transform-computed-properties@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-computed-properties@npm:7.22.5" dependencies: - "@babel/helper-module-transforms": ^7.21.2 - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/helper-simple-access": ^7.20.2 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/template": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 65aa06e3e3792f39b99eb5f807034693ff0ecf80438580f7ae504f4c4448ef04147b1889ea5e6f60f3ad4a12ebbb57c6f1f979a249dadbd8d11fe22f4441918b + checksum: c2a77a0f94ec71efbc569109ec14ea2aa925b333289272ced8b33c6108bdbb02caf01830ffc7e49486b62dec51911924d13f3a76f1149f40daace1898009e131 languageName: node linkType: hard -"@babel/plugin-transform-modules-systemjs@npm:^7.20.11": - version: 7.20.11 - resolution: "@babel/plugin-transform-modules-systemjs@npm:7.20.11" +"@babel/plugin-transform-destructuring@npm:^7.22.15": + version: 7.23.0 + resolution: "@babel/plugin-transform-destructuring@npm:7.23.0" dependencies: - "@babel/helper-hoist-variables": ^7.18.6 - "@babel/helper-module-transforms": ^7.20.11 - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/helper-validator-identifier": ^7.19.1 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 4546c47587f88156d66c7eb7808e903cf4bb3f6ba6ac9bc8e3af2e29e92eb9f0b3f44d52043bfd24eb25fa7827fd7b6c8bfeac0cac7584e019b87e1ecbd0e673 + checksum: cd6dd454ccc2766be551e4f8a04b1acc2aa539fa19e5c7501c56cc2f8cc921dd41a7ffb78455b4c4b2f954fcab8ca4561ba7c9c7bd5af9f19465243603d18cc3 languageName: node linkType: hard -"@babel/plugin-transform-modules-umd@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-modules-umd@npm:7.18.6" +"@babel/plugin-transform-dotall-regex@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.22.5" dependencies: - "@babel/helper-module-transforms": ^7.18.6 - "@babel/helper-plugin-utils": ^7.18.6 + "@babel/helper-create-regexp-features-plugin": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: c3b6796c6f4579f1ba5ab0cdcc73910c1e9c8e1e773c507c8bb4da33072b3ae5df73c6d68f9126dab6e99c24ea8571e1563f8710d7c421fac1cde1e434c20153 + checksum: 409b658d11e3082c8f69e9cdef2d96e4d6d11256f005772425fb230cc48fd05945edbfbcb709dab293a1a2f01f9c8a5bb7b4131e632b23264039d9f95864b453 languageName: node linkType: hard -"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.20.5": - version: 7.20.5 - resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.20.5" +"@babel/plugin-transform-duplicate-keys@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.22.5" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.20.5 - "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: bb1280fbabaab6fab2ede585df34900712698210a3bd413f4df5bae6d8c24be36b496c92722ae676a7a67d060a4624f4d6c23b923485f906bfba8773c69f55b4 + languageName: node + linkType: hard + +"@babel/plugin-transform-dynamic-import@npm:^7.22.11": + version: 7.22.11 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.22.11" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-dynamic-import": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 78fc9c532210bf9e8f231747f542318568ac360ee6c27e80853962c984283c73da3f8f8aebe83c2096090a435b356b092ed85de617a156cbe0729d847632be45 + languageName: node + linkType: hard + +"@babel/plugin-transform-exponentiation-operator@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.22.5" + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f2d660c1b1d51ad5fec1cd5ad426a52187204068c4158f8c4aa977b31535c61b66898d532603eef21c15756827be8277f724c869b888d560f26d7fe848bb5eae + languageName: node + linkType: hard + +"@babel/plugin-transform-export-namespace-from@npm:^7.22.11": + version: 7.22.11 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.22.11" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-export-namespace-from": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 73af5883a321ed56a4bfd43c8a7de0164faebe619287706896fc6ee2f7a4e69042adaa1338c0b8b4bdb9f7e5fdceb016fb1d40694cb43ca3b8827429e8aac4bf + languageName: node + linkType: hard + +"@babel/plugin-transform-for-of@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/plugin-transform-for-of@npm:7.22.15" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f395ae7bce31e14961460f56cf751b5d6e37dd27d7df5b1f4e49fec1c11b6f9cf71991c7ffbe6549878591e87df0d66af798cf26edfa4bfa6b4c3dba1fb2f73a + languageName: node + linkType: hard + +"@babel/plugin-transform-function-name@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-function-name@npm:7.22.5" + dependencies: + "@babel/helper-compilation-targets": ^7.22.5 + "@babel/helper-function-name": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: cff3b876357999cb8ae30e439c3ec6b0491a53b0aa6f722920a4675a6dd5b53af97a833051df4b34791fe5b3dd326ccf769d5c8e45b322aa50ee11a660b17845 + languageName: node + linkType: hard + +"@babel/plugin-transform-json-strings@npm:^7.22.11": + version: 7.22.11 + resolution: "@babel/plugin-transform-json-strings@npm:7.22.11" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-json-strings": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 50665e5979e66358c50e90a26db53c55917f78175127ac2fa05c7888d156d418ffb930ec0a109353db0a7c5f57c756ce01bfc9825d24cbfd2b3ec453f2ed8cba + languageName: node + linkType: hard + +"@babel/plugin-transform-literals@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-literals@npm:7.22.5" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ec37cc2ffb32667af935ab32fe28f00920ec8a1eb999aa6dc6602f2bebd8ba205a558aeedcdccdebf334381d5c57106c61f52332045730393e73410892a9735b + languageName: node + linkType: hard + +"@babel/plugin-transform-logical-assignment-operators@npm:^7.22.11": + version: 7.22.11 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.22.11" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c664e9798e85afa7f92f07b867682dee7392046181d82f5d21bae6f2ca26dfe9c8375cdc52b7483c3fc09a983c1989f60eff9fbc4f373b0c0a74090553d05739 + languageName: node + linkType: hard + +"@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: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ec4b0e07915ddd4fda0142fd104ee61015c208608a84cfa13643a95d18760b1dc1ceb6c6e0548898b8c49e5959a994e46367260176dbabc4467f729b21868504 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-amd@npm:^7.22.5": + version: 7.23.0 + resolution: "@babel/plugin-transform-modules-amd@npm:7.23.0" + dependencies: + "@babel/helper-module-transforms": ^7.23.0 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 5d92875170a37b8282d4bcd805f55829b8fab0f9c8d08b53d32a7a0bfdc62b868e489b52d329ae768ecafc0c993eed0ad7a387baa673ac33211390a9f833ab5d + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-commonjs@npm:^7.22.15, @babel/plugin-transform-modules-commonjs@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.23.0" + dependencies: + "@babel/helper-module-transforms": ^7.23.0 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-simple-access": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7fb25997194053e167c4207c319ff05362392da841bd9f42ddb3caf9c8798a5d203bd926d23ddf5830fdf05eddc82c2810f40d1287e3a4f80b07eff13d1024b5 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-systemjs@npm:^7.22.11": + version: 7.23.0 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.23.0" + dependencies: + "@babel/helper-hoist-variables": ^7.22.5 + "@babel/helper-module-transforms": ^7.23.0 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-identifier": ^7.22.20 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 2d481458b22605046badea2317d5cc5c94ac3031c2293e34c96f02063f5b02af0979c4da6a8fbc67cc249541575dc9c6d710db6b919ede70b7337a22d9fd57a7 + languageName: node + linkType: hard + +"@babel/plugin-transform-modules-umd@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-modules-umd@npm:7.22.5" + dependencies: + "@babel/helper-module-transforms": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 46622834c54c551b231963b867adbc80854881b3e516ff29984a8da989bd81665bd70e8cba6710345248e97166689310f544aee1a5773e262845a8f1b3e5b8b4 + languageName: node + linkType: hard + +"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.22.5" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0 - checksum: 528c95fb1087e212f17e1c6456df041b28a83c772b9c93d2e407c9d03b72182b0d9d126770c1d6e0b23aab052599ceaf25ed6a2c0627f4249be34a83f6fae853 + checksum: 3ee564ddee620c035b928fdc942c5d17e9c4b98329b76f9cefac65c111135d925eb94ed324064cd7556d4f5123beec79abea1d4b97d1c8a2a5c748887a2eb623 languageName: node linkType: hard -"@babel/plugin-transform-new-target@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-new-target@npm:7.18.6" +"@babel/plugin-transform-new-target@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-new-target@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.18.6 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: bd780e14f46af55d0ae8503b3cb81ca86dcc73ed782f177e74f498fff934754f9e9911df1f8f3bd123777eed7c1c1af4d66abab87c8daae5403e7719a6b845d1 + checksum: 6b72112773487a881a1d6ffa680afde08bad699252020e86122180ee7a88854d5da3f15d9bca3331cf2e025df045604494a8208a2e63b486266b07c14e2ffbf3 languageName: node linkType: hard -"@babel/plugin-transform-object-super@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-object-super@npm:7.18.6" +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.22.11": + version: 7.22.11 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.22.11" dependencies: - "@babel/helper-plugin-utils": ^7.18.6 - "@babel/helper-replace-supers": ^7.18.6 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 0fcb04e15deea96ae047c21cb403607d49f06b23b4589055993365ebd7a7d7541334f06bf9642e90075e66efce6ebaf1eb0ef066fbbab802d21d714f1aac3aef + checksum: 167babecc8b8fe70796a7b7d34af667ebbf43da166c21689502e5e8cc93180b7a85979c77c9f64b7cce431b36718bd0a6df9e5e0ffea4ae22afb22cfef886372 languageName: node linkType: hard -"@babel/plugin-transform-parameters@npm:^7.20.7, @babel/plugin-transform-parameters@npm:^7.21.3": - version: 7.21.3 - resolution: "@babel/plugin-transform-parameters@npm:7.21.3" +"@babel/plugin-transform-numeric-separator@npm:^7.22.11": + version: 7.22.11 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.22.11" dependencies: - "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: c92128d7b1fcf54e2cab186c196bbbf55a9a6de11a83328dc2602649c9dc6d16ef73712beecd776cd49bfdc624b5f56740f4a53568d3deb9505ec666bc869da3 + checksum: af064d06a4a041767ec396a5f258103f64785df290e038bba9f0ef454e6c914f2ac45d862bbdad8fac2c7ad47fa4e95356f29053c60c100a0160b02a995fe2a3 languageName: node linkType: hard -"@babel/plugin-transform-property-literals@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-property-literals@npm:7.18.6" +"@babel/plugin-transform-object-rest-spread@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.22.15" dependencies: - "@babel/helper-plugin-utils": ^7.18.6 + "@babel/compat-data": ^7.22.9 + "@babel/helper-compilation-targets": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-object-rest-spread": ^7.8.3 + "@babel/plugin-transform-parameters": ^7.22.15 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 1c16e64de554703f4b547541de2edda6c01346dd3031d4d29e881aa7733785cd26d53611a4ccf5353f4d3e69097bb0111c0a93ace9e683edd94fea28c4484144 + checksum: 62197a6f12289c1c1bd57f3bed9f0f765ca32390bfe91e0b5561dd94dd9770f4480c4162dec98da094bc0ba99d2c2ebba68de47c019454041b0b7a68ba2ec66d + languageName: node + linkType: hard + +"@babel/plugin-transform-object-super@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-object-super@npm:7.22.5" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-replace-supers": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b71887877d74cb64dbccb5c0324fa67e31171e6a5311991f626650e44a4083e5436a1eaa89da78c0474fb095d4ec322d63ee778b202d33aa2e4194e1ed8e62d7 + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-catch-binding@npm:^7.22.11": + version: 7.22.11 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.22.11" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f17abd90e1de67c84d63afea29c8021c74abb2794d3a6eeafb0bbe7372d3db32aefca386e392116ec63884537a4a2815d090d26264d259bacc08f6e3ed05294c + languageName: node + linkType: hard + +"@babel/plugin-transform-optional-chaining@npm:^7.22.15": + version: 7.23.0 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.23.0" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 + "@babel/plugin-syntax-optional-chaining": ^7.8.3 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: f702634f2b97e5260dbec0d4bde05ccb6f4d96d7bfa946481aeacfa205ca846cb6e096a38312f9d51fdbdac1f258f211138c5f7075952e46a5bf8574de6a1329 + languageName: node + linkType: hard + +"@babel/plugin-transform-parameters@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/plugin-transform-parameters@npm:7.22.15" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 541188bb7d1876cad87687b5c7daf90f63d8208ae83df24acb1e2b05020ad1c78786b2723ca4054a83fcb74fb6509f30c4cacc5b538ee684224261ad5fb047c1 + languageName: node + linkType: hard + +"@babel/plugin-transform-private-methods@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-private-methods@npm:7.22.5" + dependencies: + "@babel/helper-create-class-features-plugin": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 321479b4fcb6d3b3ef622ab22fd24001e43d46e680e8e41324c033d5810c84646e470f81b44cbcbef5c22e99030784f7cac92f1829974da7a47a60a7139082c3 + languageName: node + linkType: hard + +"@babel/plugin-transform-private-property-in-object@npm:^7.22.11": + version: 7.22.11 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.22.11" + dependencies: + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-create-class-features-plugin": ^7.22.11 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 4d029d84901e53c46dead7a46e2990a7bc62470f4e4ca58a0d063394f86652fd58fe4eea1eb941da3669cd536b559b9d058b342b59300026346b7a2a51badac8 + languageName: node + linkType: hard + +"@babel/plugin-transform-property-literals@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-property-literals@npm:7.22.5" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 796176a3176106f77fcb8cd04eb34a8475ce82d6d03a88db089531b8f0453a2fb8b0c6ec9a52c27948bc0ea478becec449893741fc546dfc3930ab927e3f9f2e languageName: node linkType: hard @@ -1205,218 +1237,230 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-react-display-name@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-react-display-name@npm:7.18.6" +"@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: - "@babel/helper-plugin-utils": ^7.18.6 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 51c087ab9e41ef71a29335587da28417536c6f816c292e092ffc0e0985d2f032656801d4dd502213ce32481f4ba6c69402993ffa67f0818a07606ff811e4be49 + checksum: a12bfd1e4e93055efca3ace3c34722571bda59d9740dca364d225d9c6e3ca874f134694d21715c42cc63d79efd46db9665bd4a022998767f9245f1e29d5d204d languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-development@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-react-jsx-development@npm:7.18.6" +"@babel/plugin-transform-react-jsx-development@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-react-jsx-development@npm:7.22.5" dependencies: - "@babel/plugin-transform-react-jsx": ^7.18.6 + "@babel/plugin-transform-react-jsx": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ec9fa65db66f938b75c45e99584367779ac3e0af8afc589187262e1337c7c4205ea312877813ae4df9fb93d766627b8968d74ac2ba702e4883b1dbbe4953ecee + checksum: 36bc3ff0b96bb0ef4723070a50cfdf2e72cfd903a59eba448f9fe92fea47574d6f22efd99364413719e1f3fb3c51b6c9b2990b87af088f8486a84b2a5f9e4560 languageName: node linkType: hard -"@babel/plugin-transform-react-jsx@npm:^7.18.6": - version: 7.19.0 - resolution: "@babel/plugin-transform-react-jsx@npm:7.19.0" +"@babel/plugin-transform-react-jsx@npm:^7.22.15, @babel/plugin-transform-react-jsx@npm:^7.22.5": + version: 7.22.15 + resolution: "@babel/plugin-transform-react-jsx@npm:7.22.15" dependencies: - "@babel/helper-annotate-as-pure": ^7.18.6 - "@babel/helper-module-imports": ^7.18.6 - "@babel/helper-plugin-utils": ^7.19.0 - "@babel/plugin-syntax-jsx": ^7.18.6 - "@babel/types": ^7.19.0 + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-module-imports": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-jsx": ^7.22.5 + "@babel/types": ^7.22.15 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d7d6f0b8f24b1f6b7cf8062c4e91c59af82489a993e51859bd49c2d62a2d2b77fd40b02a9a1d0e6d874cf4ce56a05fa3564b964587d00c94ebc62593524052ec + checksum: 3899054e89550c3a0ef041af7c47ee266e2e934f498ee80fefeda778a6aa177b48aa8b4d2a8bf5848de977fec564571699ab952d9fa089c4c19b45ddb121df09 languageName: node linkType: hard -"@babel/plugin-transform-react-pure-annotations@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.18.6" +"@babel/plugin-transform-react-pure-annotations@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.22.5" dependencies: - "@babel/helper-annotate-as-pure": ^7.18.6 - "@babel/helper-plugin-utils": ^7.18.6 + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 97c4873d409088f437f9084d084615948198dd87fc6723ada0e7e29c5a03623c2f3e03df3f52e7e7d4d23be32a08ea00818bff302812e48713c706713bd06219 + checksum: 092021c4f404e267002099ec20b3f12dd730cb90b0d83c5feed3dc00dbe43b9c42c795a18e7c6c7d7bddea20c7dd56221b146aec81b37f2e7eb5137331c61120 languageName: node linkType: hard -"@babel/plugin-transform-regenerator@npm:^7.20.5": - version: 7.20.5 - resolution: "@babel/plugin-transform-regenerator@npm:7.20.5" +"@babel/plugin-transform-regenerator@npm:^7.22.10": + version: 7.22.10 + resolution: "@babel/plugin-transform-regenerator@npm:7.22.10" dependencies: - "@babel/helper-plugin-utils": ^7.20.2 - regenerator-transform: ^0.15.1 + "@babel/helper-plugin-utils": ^7.22.5 + regenerator-transform: ^0.15.2 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 13164861e71fb23d84c6270ef5330b03c54d5d661c2c7468f28e21c4f8598558ca0c8c3cb1d996219352946e849d270a61372bc93c8fbe9676e78e3ffd0dea07 + checksum: e13678d62d6fa96f11cb8b863f00e8693491e7adc88bfca3f2820f80cbac8336e7dec3a596eee6a1c4663b7ececc3564f2cd7fb44ed6d4ce84ac2bb7f39ecc6e languageName: node linkType: hard -"@babel/plugin-transform-reserved-words@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-reserved-words@npm:7.18.6" +"@babel/plugin-transform-reserved-words@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-reserved-words@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.18.6 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 0738cdc30abdae07c8ec4b233b30c31f68b3ff0eaa40eddb45ae607c066127f5fa99ddad3c0177d8e2832e3a7d3ad115775c62b431ebd6189c40a951b867a80c + checksum: 3ffd7dbc425fe8132bfec118b9817572799cab1473113a635d25ab606c1f5a2341a636c04cf6b22df3813320365ed5a965b5eeb3192320a10e4cc2c137bd8bfc languageName: node linkType: hard -"@babel/plugin-transform-runtime@npm:^7.21.0": - version: 7.21.4 - resolution: "@babel/plugin-transform-runtime@npm:7.21.4" +"@babel/plugin-transform-runtime@npm:^7.22.9": + version: 7.22.15 + resolution: "@babel/plugin-transform-runtime@npm:7.22.15" dependencies: - "@babel/helper-module-imports": ^7.21.4 - "@babel/helper-plugin-utils": ^7.20.2 - babel-plugin-polyfill-corejs2: ^0.3.3 - babel-plugin-polyfill-corejs3: ^0.6.0 - babel-plugin-polyfill-regenerator: ^0.4.1 - semver: ^6.3.0 + "@babel/helper-module-imports": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + babel-plugin-polyfill-corejs2: ^0.4.5 + babel-plugin-polyfill-corejs3: ^0.8.3 + babel-plugin-polyfill-regenerator: ^0.5.2 + semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 7e2e6b0d6f9762fde58738829e4d3b5e13dc88ccc1463e4eee83c8d8f50238eeb8e3699923f5ad4d7edf597515f74d67fbb14eb330225075fc7733b547e22145 + checksum: 7edf20b13d02f856276221624abf3b8084daa3f265a6e5c70ee0d0c63087fcf726dc8756a9c8bb3d25a1ce8697ab66ec8cdd15be992c21aed9971cb5bfe80a5b languageName: node linkType: hard -"@babel/plugin-transform-shorthand-properties@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-shorthand-properties@npm:7.18.6" +"@babel/plugin-transform-shorthand-properties@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.18.6 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b8e4e8acc2700d1e0d7d5dbfd4fdfb935651913de6be36e6afb7e739d8f9ca539a5150075a0f9b79c88be25ddf45abb912fe7abf525f0b80f5b9d9860de685d7 + checksum: a5ac902c56ea8effa99f681340ee61bac21094588f7aef0bc01dff98246651702e677552fa6d10e548c4ac22a3ffad047dd2f8c8f0540b68316c2c203e56818b languageName: node linkType: hard -"@babel/plugin-transform-spread@npm:^7.20.7": - version: 7.20.7 - resolution: "@babel/plugin-transform-spread@npm:7.20.7" +"@babel/plugin-transform-spread@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-spread@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/helper-skip-transparent-expression-wrappers": ^7.20.0 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-skip-transparent-expression-wrappers": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 8ea698a12da15718aac7489d4cde10beb8a3eea1f66167d11ab1e625033641e8b328157fd1a0b55dd6531933a160c01fc2e2e61132a385cece05f26429fd0cc2 + checksum: 5587f0deb60b3dfc9b274e269031cc45ec75facccf1933ea2ea71ced9fd3ce98ed91bb36d6cd26817c14474b90ed998c5078415f0eab531caf301496ce24c95c languageName: node linkType: hard -"@babel/plugin-transform-sticky-regex@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-sticky-regex@npm:7.18.6" +"@babel/plugin-transform-sticky-regex@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.18.6 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 68ea18884ae9723443ffa975eb736c8c0d751265859cd3955691253f7fee37d7a0f7efea96c8a062876af49a257a18ea0ed5fea0d95a7b3611ce40f7ee23aee3 + checksum: 63b2c575e3e7f96c32d52ed45ee098fb7d354b35c2223b8c8e76840b32cc529ee0c0ceb5742fd082e56e91e3d82842a367ce177e82b05039af3d602c9627a729 languageName: node linkType: hard -"@babel/plugin-transform-template-literals@npm:^7.18.9": - version: 7.18.9 - resolution: "@babel/plugin-transform-template-literals@npm:7.18.9" +"@babel/plugin-transform-template-literals@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-template-literals@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.18.9 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 3d2fcd79b7c345917f69b92a85bdc3ddd68ce2c87dc70c7d61a8373546ccd1f5cb8adc8540b49dfba08e1b82bb7b3bbe23a19efdb2b9c994db2db42906ca9fb2 + checksum: 27e9bb030654cb425381c69754be4abe6a7c75b45cd7f962cd8d604b841b2f0fb7b024f2efc1c25cc53f5b16d79d5e8cfc47cacbdaa983895b3aeefa3e7e24ff languageName: node linkType: hard -"@babel/plugin-transform-typeof-symbol@npm:^7.18.9": - version: 7.18.9 - resolution: "@babel/plugin-transform-typeof-symbol@npm:7.18.9" +"@babel/plugin-transform-typeof-symbol@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.18.9 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e754e0d8b8a028c52e10c148088606e3f7a9942c57bd648fc0438e5b4868db73c386a5ed47ab6d6f0594aae29ee5ffc2ffc0f7ebee7fae560a066d6dea811cd4 + checksum: 82a53a63ffc3010b689ca9a54e5f53b2718b9f4b4a9818f36f9b7dba234f38a01876680553d2716a645a61920b5e6e4aaf8d4a0064add379b27ca0b403049512 languageName: node linkType: hard -"@babel/plugin-transform-typescript@npm:^7.21.3": - version: 7.21.3 - resolution: "@babel/plugin-transform-typescript@npm:7.21.3" +"@babel/plugin-transform-typescript@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/plugin-transform-typescript@npm:7.22.15" dependencies: - "@babel/helper-annotate-as-pure": ^7.18.6 - "@babel/helper-create-class-features-plugin": ^7.21.0 - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/plugin-syntax-typescript": ^7.20.0 + "@babel/helper-annotate-as-pure": ^7.22.5 + "@babel/helper-create-class-features-plugin": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-typescript": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: c16fd577bf43f633deb76fca2a8527d8ae25968c8efdf327c1955472c3e0257e62992473d1ad7f9ee95379ce2404699af405ea03346055adadd3478ad0ecd117 + checksum: c5d96cdbf0e1512707aa1c1e3ac6b370a25fd9c545d26008ce44eb13a47bd7fd67a1eb799c98b5ccc82e33a345fda55c0055e1fe3ed97646ed405dd13020b226 languageName: node linkType: hard -"@babel/plugin-transform-unicode-escapes@npm:^7.18.10": - version: 7.18.10 - resolution: "@babel/plugin-transform-unicode-escapes@npm:7.18.10" +"@babel/plugin-transform-unicode-escapes@npm:^7.22.10": + version: 7.22.10 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.22.10" dependencies: - "@babel/helper-plugin-utils": ^7.18.9 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: f5baca55cb3c11bc08ec589f5f522d85c1ab509b4d11492437e45027d64ae0b22f0907bd1381e8d7f2a436384bb1f9ad89d19277314242c5c2671a0f91d0f9cd + checksum: 807f40ed1324c8cb107c45358f1903384ca3f0ef1d01c5a3c5c9b271c8d8eec66936a3dcc8d75ddfceea9421420368c2e77ae3adef0a50557e778dfe296bf382 languageName: node linkType: hard -"@babel/plugin-transform-unicode-regex@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-transform-unicode-regex@npm:7.18.6" +"@babel/plugin-transform-unicode-property-regex@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.22.5" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.18.6 - "@babel/helper-plugin-utils": ^7.18.6 + "@babel/helper-create-regexp-features-plugin": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d9e18d57536a2d317fb0b7c04f8f55347f3cfacb75e636b4c6fa2080ab13a3542771b5120e726b598b815891fc606d1472ac02b749c69fd527b03847f22dc25e + checksum: 2495e5f663cb388e3d888b4ba3df419ac436a5012144ac170b622ddfc221f9ea9bdba839fa2bc0185cb776b578030666406452ec7791cbf0e7a3d4c88ae9574c languageName: node linkType: hard -"@babel/preset-env@npm:^7.19.4, @babel/preset-env@npm:^7.20.2": - version: 7.21.4 - resolution: "@babel/preset-env@npm:7.21.4" +"@babel/plugin-transform-unicode-regex@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.22.5" dependencies: - "@babel/compat-data": ^7.21.4 - "@babel/helper-compilation-targets": ^7.21.4 - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/helper-validator-option": ^7.21.0 - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.18.6 - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ^7.20.7 - "@babel/plugin-proposal-async-generator-functions": ^7.20.7 - "@babel/plugin-proposal-class-properties": ^7.18.6 - "@babel/plugin-proposal-class-static-block": ^7.21.0 - "@babel/plugin-proposal-dynamic-import": ^7.18.6 - "@babel/plugin-proposal-export-namespace-from": ^7.18.9 - "@babel/plugin-proposal-json-strings": ^7.18.6 - "@babel/plugin-proposal-logical-assignment-operators": ^7.20.7 - "@babel/plugin-proposal-nullish-coalescing-operator": ^7.18.6 - "@babel/plugin-proposal-numeric-separator": ^7.18.6 - "@babel/plugin-proposal-object-rest-spread": ^7.20.7 - "@babel/plugin-proposal-optional-catch-binding": ^7.18.6 - "@babel/plugin-proposal-optional-chaining": ^7.21.0 - "@babel/plugin-proposal-private-methods": ^7.18.6 - "@babel/plugin-proposal-private-property-in-object": ^7.21.0 - "@babel/plugin-proposal-unicode-property-regex": ^7.18.6 + "@babel/helper-create-regexp-features-plugin": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 6b5d1404c8c623b0ec9bd436c00d885a17d6a34f3f2597996343ddb9d94f6379705b21582dfd4cec2c47fd34068872e74ab6b9580116c0566b3f9447e2a7fa06 + languageName: node + linkType: hard + +"@babel/plugin-transform-unicode-sets-regex@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.22.5" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.22.5 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: c042070f980b139547f8b0179efbc049ac5930abec7fc26ed7a41d89a048d8ab17d362200e204b6f71c3c20d6991a0e74415e1a412a49adc8131c2a40c04822e + languageName: node + linkType: hard + +"@babel/preset-env@npm:^7.19.4, @babel/preset-env@npm:^7.22.9": + version: 7.22.20 + resolution: "@babel/preset-env@npm:7.22.20" + dependencies: + "@babel/compat-data": ^7.22.20 + "@babel/helper-compilation-targets": ^7.22.15 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-option": ^7.22.15 + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.22.15 + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ^7.22.15 + "@babel/plugin-proposal-private-property-in-object": 7.21.0-placeholder-for-preset-env.2 "@babel/plugin-syntax-async-generators": ^7.8.4 "@babel/plugin-syntax-class-properties": ^7.12.13 "@babel/plugin-syntax-class-static-block": ^7.14.5 "@babel/plugin-syntax-dynamic-import": ^7.8.3 "@babel/plugin-syntax-export-namespace-from": ^7.8.3 - "@babel/plugin-syntax-import-assertions": ^7.20.0 + "@babel/plugin-syntax-import-assertions": ^7.22.5 + "@babel/plugin-syntax-import-attributes": ^7.22.5 + "@babel/plugin-syntax-import-meta": ^7.10.4 "@babel/plugin-syntax-json-strings": ^7.8.3 "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 @@ -1426,153 +1470,175 @@ __metadata: "@babel/plugin-syntax-optional-chaining": ^7.8.3 "@babel/plugin-syntax-private-property-in-object": ^7.14.5 "@babel/plugin-syntax-top-level-await": ^7.14.5 - "@babel/plugin-transform-arrow-functions": ^7.20.7 - "@babel/plugin-transform-async-to-generator": ^7.20.7 - "@babel/plugin-transform-block-scoped-functions": ^7.18.6 - "@babel/plugin-transform-block-scoping": ^7.21.0 - "@babel/plugin-transform-classes": ^7.21.0 - "@babel/plugin-transform-computed-properties": ^7.20.7 - "@babel/plugin-transform-destructuring": ^7.21.3 - "@babel/plugin-transform-dotall-regex": ^7.18.6 - "@babel/plugin-transform-duplicate-keys": ^7.18.9 - "@babel/plugin-transform-exponentiation-operator": ^7.18.6 - "@babel/plugin-transform-for-of": ^7.21.0 - "@babel/plugin-transform-function-name": ^7.18.9 - "@babel/plugin-transform-literals": ^7.18.9 - "@babel/plugin-transform-member-expression-literals": ^7.18.6 - "@babel/plugin-transform-modules-amd": ^7.20.11 - "@babel/plugin-transform-modules-commonjs": ^7.21.2 - "@babel/plugin-transform-modules-systemjs": ^7.20.11 - "@babel/plugin-transform-modules-umd": ^7.18.6 - "@babel/plugin-transform-named-capturing-groups-regex": ^7.20.5 - "@babel/plugin-transform-new-target": ^7.18.6 - "@babel/plugin-transform-object-super": ^7.18.6 - "@babel/plugin-transform-parameters": ^7.21.3 - "@babel/plugin-transform-property-literals": ^7.18.6 - "@babel/plugin-transform-regenerator": ^7.20.5 - "@babel/plugin-transform-reserved-words": ^7.18.6 - "@babel/plugin-transform-shorthand-properties": ^7.18.6 - "@babel/plugin-transform-spread": ^7.20.7 - "@babel/plugin-transform-sticky-regex": ^7.18.6 - "@babel/plugin-transform-template-literals": ^7.18.9 - "@babel/plugin-transform-typeof-symbol": ^7.18.9 - "@babel/plugin-transform-unicode-escapes": ^7.18.10 - "@babel/plugin-transform-unicode-regex": ^7.18.6 - "@babel/preset-modules": ^0.1.5 - "@babel/types": ^7.21.4 - babel-plugin-polyfill-corejs2: ^0.3.3 - babel-plugin-polyfill-corejs3: ^0.6.0 - babel-plugin-polyfill-regenerator: ^0.4.1 - core-js-compat: ^3.25.1 - semver: ^6.3.0 + "@babel/plugin-syntax-unicode-sets-regex": ^7.18.6 + "@babel/plugin-transform-arrow-functions": ^7.22.5 + "@babel/plugin-transform-async-generator-functions": ^7.22.15 + "@babel/plugin-transform-async-to-generator": ^7.22.5 + "@babel/plugin-transform-block-scoped-functions": ^7.22.5 + "@babel/plugin-transform-block-scoping": ^7.22.15 + "@babel/plugin-transform-class-properties": ^7.22.5 + "@babel/plugin-transform-class-static-block": ^7.22.11 + "@babel/plugin-transform-classes": ^7.22.15 + "@babel/plugin-transform-computed-properties": ^7.22.5 + "@babel/plugin-transform-destructuring": ^7.22.15 + "@babel/plugin-transform-dotall-regex": ^7.22.5 + "@babel/plugin-transform-duplicate-keys": ^7.22.5 + "@babel/plugin-transform-dynamic-import": ^7.22.11 + "@babel/plugin-transform-exponentiation-operator": ^7.22.5 + "@babel/plugin-transform-export-namespace-from": ^7.22.11 + "@babel/plugin-transform-for-of": ^7.22.15 + "@babel/plugin-transform-function-name": ^7.22.5 + "@babel/plugin-transform-json-strings": ^7.22.11 + "@babel/plugin-transform-literals": ^7.22.5 + "@babel/plugin-transform-logical-assignment-operators": ^7.22.11 + "@babel/plugin-transform-member-expression-literals": ^7.22.5 + "@babel/plugin-transform-modules-amd": ^7.22.5 + "@babel/plugin-transform-modules-commonjs": ^7.22.15 + "@babel/plugin-transform-modules-systemjs": ^7.22.11 + "@babel/plugin-transform-modules-umd": ^7.22.5 + "@babel/plugin-transform-named-capturing-groups-regex": ^7.22.5 + "@babel/plugin-transform-new-target": ^7.22.5 + "@babel/plugin-transform-nullish-coalescing-operator": ^7.22.11 + "@babel/plugin-transform-numeric-separator": ^7.22.11 + "@babel/plugin-transform-object-rest-spread": ^7.22.15 + "@babel/plugin-transform-object-super": ^7.22.5 + "@babel/plugin-transform-optional-catch-binding": ^7.22.11 + "@babel/plugin-transform-optional-chaining": ^7.22.15 + "@babel/plugin-transform-parameters": ^7.22.15 + "@babel/plugin-transform-private-methods": ^7.22.5 + "@babel/plugin-transform-private-property-in-object": ^7.22.11 + "@babel/plugin-transform-property-literals": ^7.22.5 + "@babel/plugin-transform-regenerator": ^7.22.10 + "@babel/plugin-transform-reserved-words": ^7.22.5 + "@babel/plugin-transform-shorthand-properties": ^7.22.5 + "@babel/plugin-transform-spread": ^7.22.5 + "@babel/plugin-transform-sticky-regex": ^7.22.5 + "@babel/plugin-transform-template-literals": ^7.22.5 + "@babel/plugin-transform-typeof-symbol": ^7.22.5 + "@babel/plugin-transform-unicode-escapes": ^7.22.10 + "@babel/plugin-transform-unicode-property-regex": ^7.22.5 + "@babel/plugin-transform-unicode-regex": ^7.22.5 + "@babel/plugin-transform-unicode-sets-regex": ^7.22.5 + "@babel/preset-modules": 0.1.6-no-external-plugins + "@babel/types": ^7.22.19 + babel-plugin-polyfill-corejs2: ^0.4.5 + babel-plugin-polyfill-corejs3: ^0.8.3 + babel-plugin-polyfill-regenerator: ^0.5.2 + core-js-compat: ^3.31.0 + semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 1e328674c4b39e985fa81e5a8eee9aaab353dea4ff1f28f454c5e27a6498c762e25d42e827f5bfc9d7acf6c9b8bc317b5283aa7c83d9fd03c1a89e5c08f334f9 + checksum: 99357a5cb30f53bacdc0d1cd6dff0f052ea6c2d1ba874d969bba69897ef716e87283e84a59dc52fb49aa31fd1b6f55ed756c64c04f5678380700239f6030b881 languageName: node linkType: hard -"@babel/preset-modules@npm:^0.1.5": - version: 0.1.5 - resolution: "@babel/preset-modules@npm:0.1.5" +"@babel/preset-modules@npm:0.1.6-no-external-plugins": + version: 0.1.6-no-external-plugins + resolution: "@babel/preset-modules@npm:0.1.6-no-external-plugins" dependencies: "@babel/helper-plugin-utils": ^7.0.0 - "@babel/plugin-proposal-unicode-property-regex": ^7.4.4 - "@babel/plugin-transform-dotall-regex": ^7.4.4 "@babel/types": ^7.4.4 esutils: ^2.0.2 peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 8430e0e9e9d520b53e22e8c4c6a5a080a12b63af6eabe559c2310b187bd62ae113f3da82ba33e9d1d0f3230930ca702843aae9dd226dec51f7d7114dc1f51c10 + "@babel/core": ^7.0.0-0 || ^8.0.0-0 <8.0.0 + checksum: 4855e799bc50f2449fb5210f78ea9e8fd46cf4f242243f1e2ed838e2bd702e25e73e822e7f8447722a5f4baa5e67a8f7a0e403f3e7ce04540ff743a9c411c375 languageName: node linkType: hard -"@babel/preset-react@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/preset-react@npm:7.18.6" +"@babel/preset-react@npm:^7.18.6, @babel/preset-react@npm:^7.22.5": + version: 7.22.15 + resolution: "@babel/preset-react@npm:7.22.15" dependencies: - "@babel/helper-plugin-utils": ^7.18.6 - "@babel/helper-validator-option": ^7.18.6 - "@babel/plugin-transform-react-display-name": ^7.18.6 - "@babel/plugin-transform-react-jsx": ^7.18.6 - "@babel/plugin-transform-react-jsx-development": ^7.18.6 - "@babel/plugin-transform-react-pure-annotations": ^7.18.6 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-option": ^7.22.15 + "@babel/plugin-transform-react-display-name": ^7.22.5 + "@babel/plugin-transform-react-jsx": ^7.22.15 + "@babel/plugin-transform-react-jsx-development": ^7.22.5 + "@babel/plugin-transform-react-pure-annotations": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 540d9cf0a0cc0bb07e6879994e6fb7152f87dafbac880b56b65e2f528134c7ba33e0cd140b58700c77b2ebf4c81fa6468fed0ba391462d75efc7f8c1699bb4c3 + checksum: c3ef99dfa2e9f57d2e08603e883aa20f47630a826c8e413888a93ae6e0084b5016871e463829be125329d40a1ba0a89f7c43d77b6dab52083c225cb43e63d10e languageName: node linkType: hard -"@babel/preset-typescript@npm:^7.18.6, @babel/preset-typescript@npm:^7.21.0": - version: 7.21.4 - resolution: "@babel/preset-typescript@npm:7.21.4" +"@babel/preset-typescript@npm:^7.18.6, @babel/preset-typescript@npm:^7.22.5": + version: 7.23.0 + resolution: "@babel/preset-typescript@npm:7.23.0" dependencies: - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/helper-validator-option": ^7.21.0 - "@babel/plugin-syntax-jsx": ^7.21.4 - "@babel/plugin-transform-modules-commonjs": ^7.21.2 - "@babel/plugin-transform-typescript": ^7.21.3 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-option": ^7.22.15 + "@babel/plugin-syntax-jsx": ^7.22.5 + "@babel/plugin-transform-modules-commonjs": ^7.23.0 + "@babel/plugin-transform-typescript": ^7.22.15 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 83b2f2bf7be3a970acd212177525f58bbb1f2e042b675a47d021a675ae27cf00b6b6babfaf3ae5c980592c9ed1b0712e5197796b691905d25c99f9006478ea06 + checksum: 3d5fce83e83f11c07e0ea13542bca181abb3b482b8981ec9c64e6add9d7beed3c54d063dc4bc9fd383165c71114a245abef89a289680833c5a8552fe3e7c4407 languageName: node linkType: hard -"@babel/runtime-corejs3@npm:^7.21.0": - version: 7.21.0 - resolution: "@babel/runtime-corejs3@npm:7.21.0" - dependencies: - core-js-pure: ^3.25.1 - regenerator-runtime: ^0.13.11 - checksum: a47927671672b1e1644771458f804e03802303eeffcafd55f85cb121d3d3ca33032cc2fe68e086e3de6923049343d0aa599fc3eb3ad5749e30646e2a2ef6f11d +"@babel/regjsgen@npm:^0.8.0": + version: 0.8.0 + resolution: "@babel/regjsgen@npm:0.8.0" + checksum: 89c338fee774770e5a487382170711014d49a68eb281e74f2b5eac88f38300a4ad545516a7786a8dd5702e9cf009c94c2f582d200f077ac5decd74c56b973730 languageName: node linkType: hard -"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.10.3, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.8.4": - version: 7.21.0 - resolution: "@babel/runtime@npm:7.21.0" +"@babel/runtime-corejs3@npm:^7.22.6": + version: 7.23.1 + resolution: "@babel/runtime-corejs3@npm:7.23.1" dependencies: - regenerator-runtime: ^0.13.11 - checksum: 7b33e25bfa9e0e1b9e8828bb61b2d32bdd46b41b07ba7cb43319ad08efc6fda8eb89445193e67d6541814627df0ca59122c0ea795e412b99c5183a0540d338ab + core-js-pure: ^3.30.2 + regenerator-runtime: ^0.14.0 + checksum: 5d52b0cc8b5d243e67cf29c584d15acdc0c89b64de4a3fe1cb8a83b84b64a5621802e36931f93ca696cb637884abd11c8514615d890a4edf057ec4464f73915d languageName: node linkType: hard -"@babel/template@npm:^7.18.10, @babel/template@npm:^7.20.7": - version: 7.20.7 - resolution: "@babel/template@npm:7.20.7" +"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.10.3, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.8.4": + version: 7.23.1 + resolution: "@babel/runtime@npm:7.23.1" dependencies: - "@babel/code-frame": ^7.18.6 - "@babel/parser": ^7.20.7 - "@babel/types": ^7.20.7 - checksum: 2eb1a0ab8d415078776bceb3473d07ab746e6bb4c2f6ca46ee70efb284d75c4a32bb0cd6f4f4946dec9711f9c0780e8e5d64b743208deac6f8e9858afadc349e + regenerator-runtime: ^0.14.0 + checksum: 0cd0d43e6e7dc7f9152fda8c8312b08321cda2f56ef53d6c22ebdd773abdc6f5d0a69008de90aa41908d00e2c1facb24715ff121274e689305c858355ff02c70 languageName: node linkType: hard -"@babel/traverse@npm:^7.20.5, @babel/traverse@npm:^7.20.7, @babel/traverse@npm:^7.21.0, @babel/traverse@npm:^7.21.2, @babel/traverse@npm:^7.21.4": - version: 7.21.4 - resolution: "@babel/traverse@npm:7.21.4" +"@babel/template@npm:^7.22.15, @babel/template@npm:^7.22.5": + version: 7.22.15 + resolution: "@babel/template@npm:7.22.15" dependencies: - "@babel/code-frame": ^7.21.4 - "@babel/generator": ^7.21.4 - "@babel/helper-environment-visitor": ^7.18.9 - "@babel/helper-function-name": ^7.21.0 - "@babel/helper-hoist-variables": ^7.18.6 - "@babel/helper-split-export-declaration": ^7.18.6 - "@babel/parser": ^7.21.4 - "@babel/types": ^7.21.4 + "@babel/code-frame": ^7.22.13 + "@babel/parser": ^7.22.15 + "@babel/types": ^7.22.15 + checksum: 1f3e7dcd6c44f5904c184b3f7fe280394b191f2fed819919ffa1e529c259d5b197da8981b6ca491c235aee8dbad4a50b7e31304aa531271cb823a4a24a0dd8fd + languageName: node + linkType: hard + +"@babel/traverse@npm:^7.22.8, @babel/traverse@npm:^7.23.0": + version: 7.23.2 + resolution: "@babel/traverse@npm:7.23.2" + dependencies: + "@babel/code-frame": ^7.22.13 + "@babel/generator": ^7.23.0 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-function-name": ^7.23.0 + "@babel/helper-hoist-variables": ^7.22.5 + "@babel/helper-split-export-declaration": ^7.22.6 + "@babel/parser": ^7.23.0 + "@babel/types": ^7.23.0 debug: ^4.1.0 globals: ^11.1.0 - checksum: f22f067c2d9b6497abf3d4e53ea71f3aa82a21f2ed434dd69b8c5767f11f2a4c24c8d2f517d2312c9e5248e5c69395fdca1c95a2b3286122c75f5783ddb6f53c + checksum: 26a1eea0dde41ab99dde8b9773a013a0dc50324e5110a049f5d634e721ff08afffd54940b3974a20308d7952085ac769689369e9127dea655f868c0f6e1ab35d languageName: node linkType: hard -"@babel/types@npm:^7.18.6, @babel/types@npm:^7.18.9, @babel/types@npm:^7.19.0, @babel/types@npm:^7.20.0, @babel/types@npm:^7.20.2, @babel/types@npm:^7.20.5, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.0, @babel/types@npm:^7.21.2, @babel/types@npm:^7.21.4, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": - version: 7.21.4 - resolution: "@babel/types@npm:7.21.4" +"@babel/types@npm:^7.20.0, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.23.0 + resolution: "@babel/types@npm:7.23.0" dependencies: - "@babel/helper-string-parser": ^7.19.4 - "@babel/helper-validator-identifier": ^7.19.1 + "@babel/helper-string-parser": ^7.22.5 + "@babel/helper-validator-identifier": ^7.22.20 to-fast-properties: ^2.0.0 - checksum: 587bc55a91ce003b0f8aa10d70070f8006560d7dc0360dc0406d306a2cb2a10154e2f9080b9c37abec76907a90b330a536406cb75e6bdc905484f37b75c73219 + checksum: 215fe04bd7feef79eeb4d33374b39909ce9cad1611c4135a4f7fdf41fe3280594105af6d7094354751514625ea92d0875aba355f53e86a92600f290e77b0e604 languageName: node linkType: hard @@ -1590,25 +1656,26 @@ __metadata: languageName: node linkType: hard -"@docsearch/css@npm:3.3.4": - version: 3.3.4 - resolution: "@docsearch/css@npm:3.3.4" - checksum: 56e3ae677423fa4cf508ffb964d0616862a4af22affad308f47edf5c1ad097a2b21187c53d240f83463c4e7add3cd60e3630022a68e2089bb3066bfbaded64a0 +"@docsearch/css@npm:3.5.2": + version: 3.5.2 + resolution: "@docsearch/css@npm:3.5.2" + checksum: d1d60dd230dd48f896755f21bd20b59583ba844212d7d336953ae48d389baaf868bdf83320fb734a4ed679c3f95b15d620cf3764cd538f6941cae239f8c9d35d languageName: node linkType: hard -"@docsearch/react@npm:^3.3.3": - version: 3.3.4 - resolution: "@docsearch/react@npm:3.3.4" +"@docsearch/react@npm:^3.5.2": + version: 3.5.2 + resolution: "@docsearch/react@npm:3.5.2" dependencies: - "@algolia/autocomplete-core": 1.8.2 - "@algolia/autocomplete-preset-algolia": 1.8.2 - "@docsearch/css": 3.3.4 - algoliasearch: ^4.0.0 + "@algolia/autocomplete-core": 1.9.3 + "@algolia/autocomplete-preset-algolia": 1.9.3 + "@docsearch/css": 3.5.2 + algoliasearch: ^4.19.1 peerDependencies: "@types/react": ">= 16.8.0 < 19.0.0" react: ">= 16.8.0 < 19.0.0" react-dom: ">= 16.8.0 < 19.0.0" + search-insights: ">= 1 < 3" peerDependenciesMeta: "@types/react": optional: true @@ -1616,35 +1683,37 @@ __metadata: optional: true react-dom: optional: true - checksum: 50f122f08c543711fffe8ba3b507311a01defef6db5d47401bd2b5c7759512357fa26d2a88a68b50916b9084fd922f7340ad03e479b4d60ac2e22b4a198dc06d + search-insights: + optional: true + checksum: 4b4584c2c73fc18cbd599047538896450974e134c2c74f19eb202db0ce8e6c3c49c6f65ed6ade61c796d476d3cbb55d6be58df62bc9568a0c72d88e42fca1d16 languageName: node linkType: hard -"@docusaurus/core@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/core@npm:0.0.0-5591" +"@docusaurus/core@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/core@npm:0.0.0-5703" dependencies: - "@babel/core": ^7.20.12 - "@babel/generator": ^7.21.1 + "@babel/core": ^7.22.9 + "@babel/generator": ^7.22.9 "@babel/plugin-syntax-dynamic-import": ^7.8.3 - "@babel/plugin-transform-runtime": ^7.21.0 - "@babel/preset-env": ^7.20.2 - "@babel/preset-react": ^7.18.6 - "@babel/preset-typescript": ^7.21.0 - "@babel/runtime": ^7.21.0 - "@babel/runtime-corejs3": ^7.21.0 - "@babel/traverse": ^7.21.2 - "@docusaurus/cssnano-preset": 0.0.0-5591 - "@docusaurus/logger": 0.0.0-5591 - "@docusaurus/mdx-loader": 0.0.0-5591 + "@babel/plugin-transform-runtime": ^7.22.9 + "@babel/preset-env": ^7.22.9 + "@babel/preset-react": ^7.22.5 + "@babel/preset-typescript": ^7.22.5 + "@babel/runtime": ^7.22.6 + "@babel/runtime-corejs3": ^7.22.6 + "@babel/traverse": ^7.22.8 + "@docusaurus/cssnano-preset": 0.0.0-5703 + "@docusaurus/logger": 0.0.0-5703 + "@docusaurus/mdx-loader": 0.0.0-5703 "@docusaurus/react-loadable": 5.5.2 - "@docusaurus/utils": 0.0.0-5591 - "@docusaurus/utils-common": 0.0.0-5591 - "@docusaurus/utils-validation": 0.0.0-5591 + "@docusaurus/utils": 0.0.0-5703 + "@docusaurus/utils-common": 0.0.0-5703 + "@docusaurus/utils-validation": 0.0.0-5703 "@slorber/static-site-generator-webpack-plugin": ^4.0.7 "@svgr/webpack": ^6.5.1 - autoprefixer: ^10.4.13 - babel-loader: ^9.1.2 + autoprefixer: ^10.4.14 + babel-loader: ^9.1.3 babel-plugin-dynamic-import-node: ^2.3.3 boxen: ^6.2.1 chalk: ^4.1.2 @@ -1654,25 +1723,25 @@ __metadata: combine-promises: ^1.1.0 commander: ^5.1.0 copy-webpack-plugin: ^11.0.0 - core-js: ^3.29.0 - css-loader: ^6.7.3 + core-js: ^3.31.1 + css-loader: ^6.8.1 css-minimizer-webpack-plugin: ^4.2.2 cssnano: ^5.1.15 del: ^6.1.1 detect-port: ^1.5.1 escape-html: ^1.0.3 - eta: ^2.0.1 + eta: ^2.2.0 file-loader: ^6.2.0 - fs-extra: ^11.1.0 - html-minifier-terser: ^7.1.0 - html-tags: ^3.2.0 - html-webpack-plugin: ^5.5.0 + fs-extra: ^11.1.1 + html-minifier-terser: ^7.2.0 + html-tags: ^3.3.1 + html-webpack-plugin: ^5.5.3 import-fresh: ^3.3.0 leven: ^3.1.0 lodash: ^4.17.21 - mini-css-extract-plugin: ^2.7.3 - postcss: ^8.4.21 - postcss-loader: ^7.0.2 + mini-css-extract-plugin: ^2.7.6 + postcss: ^8.4.26 + postcss-loader: ^7.3.3 prompts: ^2.4.2 react-dev-utils: ^12.0.1 react-helmet-async: ^1.3.0 @@ -1682,92 +1751,94 @@ __metadata: react-router-config: ^5.1.1 react-router-dom: ^5.3.4 rtl-detect: ^1.0.4 - semver: ^7.3.8 + semver: ^7.5.4 serve-handler: ^6.1.5 shelljs: ^0.8.5 - terser-webpack-plugin: ^5.3.7 - tslib: ^2.5.0 + terser-webpack-plugin: ^5.3.9 + tslib: ^2.6.0 update-notifier: ^6.0.2 url-loader: ^4.1.1 wait-on: ^7.0.1 - webpack: ^5.76.0 - webpack-bundle-analyzer: ^4.8.0 - webpack-dev-server: ^4.11.1 - webpack-merge: ^5.8.0 + webpack: ^5.88.1 + webpack-bundle-analyzer: ^4.9.0 + webpack-dev-server: ^4.15.1 + webpack-merge: ^5.9.0 webpackbar: ^5.0.2 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 + react: ^18.0.0 + react-dom: ^18.0.0 bin: docusaurus: bin/docusaurus.mjs - checksum: 95dc10c721c1ec9b4912b772fc21f7ed79a4d27e3ab50c5acf30a86609ac8c4b544639fa6590705a3fac82ed72d3ae9b4b197d2db432d1af45d55b21bace6994 + checksum: 0e2912a09964778db626dc190317badb074f2f5e09157b8070f281eff69ce2e89846529584ce9bf6e6898293409c353adc80572484aceda1d2136aa2b0b334ca languageName: node linkType: hard -"@docusaurus/cssnano-preset@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/cssnano-preset@npm:0.0.0-5591" +"@docusaurus/cssnano-preset@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/cssnano-preset@npm:0.0.0-5703" dependencies: cssnano-preset-advanced: ^5.3.10 - postcss: ^8.4.21 - postcss-sort-media-queries: ^4.3.0 - tslib: ^2.5.0 - checksum: 256397caffd2c3d993b8a1e37b9a4f02b8baf4d78ff86df368e47d8e61c5933fc1258e26edac5a1823db0472896196e6a88f16f85cc81834f6a5edb04dfb4bf9 + postcss: ^8.4.26 + postcss-sort-media-queries: ^4.4.1 + tslib: ^2.6.0 + checksum: 5f6e2a69765fb18de7d8f5e3037bf4f08695034762fca092229ae0ba9a40e9b76048914ffbf6b1d339d496e23580f47aa419f51f446c98fca0ba8d500a06e396 languageName: node linkType: hard -"@docusaurus/logger@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/logger@npm:0.0.0-5591" +"@docusaurus/logger@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/logger@npm:0.0.0-5703" dependencies: chalk: ^4.1.2 - tslib: ^2.5.0 - checksum: 0a59f232fec86170e9fbdca3f6bf7805ed0a38f1c83ff96aabdeb310c1de357c89db540e55d007086f76da701d0ffe89b283959856668894e8e2bae983f141b4 + tslib: ^2.6.0 + checksum: 9ee30b054388e5a618876316df50b73a7c4c8300ce205ace3c09f689a1a38b85d51891a1f0613341fd038a0d06290f0675d64c3e9e5b87f1eee3cb76fd45b55c languageName: node linkType: hard -"@docusaurus/mdx-loader@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/mdx-loader@npm:0.0.0-5591" +"@docusaurus/mdx-loader@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/mdx-loader@npm:0.0.0-5703" dependencies: - "@babel/parser": ^7.21.2 - "@babel/traverse": ^7.21.2 - "@docusaurus/logger": 0.0.0-5591 - "@docusaurus/utils": 0.0.0-5591 - "@docusaurus/utils-validation": 0.0.0-5591 + "@babel/parser": ^7.22.7 + "@babel/traverse": ^7.22.8 + "@docusaurus/logger": 0.0.0-5703 + "@docusaurus/utils": 0.0.0-5703 + "@docusaurus/utils-validation": 0.0.0-5703 "@mdx-js/mdx": ^2.1.5 + "@slorber/remark-comment": ^1.0.0 escape-html: ^1.0.3 estree-util-value-to-estree: ^2.1.0 file-loader: ^6.2.0 - fs-extra: ^11.1.0 + fs-extra: ^11.1.1 hastscript: ^7.1.0 image-size: ^1.0.2 mdast-util-mdx: ^2.0.0 - mdast-util-to-string: ^3.0.0 + mdast-util-to-string: ^3.2.0 rehype-raw: ^6.1.1 - remark-comment: ^1.0.0 remark-directive: ^2.0.1 remark-emoji: ^2.2.0 + remark-frontmatter: ^5.0.0 remark-gfm: ^3.0.1 stringify-object: ^3.3.0 - tslib: ^2.5.0 + tslib: ^2.6.0 unified: ^10.1.2 unist-util-visit: ^2.0.3 url-loader: ^4.1.1 - webpack: ^5.76.0 + vfile: ^5.3.7 + webpack: ^5.88.1 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 919c5f0a0d815674bbf8777ba4ce758d26bb13f046e772d11b7f688b183a31d58bb9ba55d8a484f181996ea16f9f967529337ab98bc62b9d6c806d4dde374d15 + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: d57b08d7d676b9246be129af06a803fc55162359578e486456cb96a2372809c2093ef4115c926cf8e8be35e285b35d3ea444d808d46afb78edf66b49f58474fb languageName: node linkType: hard -"@docusaurus/module-type-aliases@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/module-type-aliases@npm:0.0.0-5591" +"@docusaurus/module-type-aliases@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/module-type-aliases@npm:0.0.0-5703" dependencies: "@docusaurus/react-loadable": 5.5.2 - "@docusaurus/types": 0.0.0-5591 + "@docusaurus/types": 0.0.0-5703 "@types/history": ^4.7.11 "@types/react": "*" "@types/react-router-config": "*" @@ -1777,207 +1848,208 @@ __metadata: peerDependencies: react: "*" react-dom: "*" - checksum: 9009e4f6edbfd274b42f5a0c2821c90606103404ec7df9e916940799ee8e810605549178d6a3e7ad6531554402d60a3db822268c88ddbff119a5c10f85f833d4 + checksum: b0dbf719f3c6510b6706f36310b185bdf8a8a2ab5d3b0b76f8962b08d3b1a86783c3f4c23455c03d528500871f0a18ede4e03a0df8c7a44096b91097a5ffda7d languageName: node linkType: hard -"@docusaurus/plugin-client-redirects@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/plugin-client-redirects@npm:0.0.0-5591" +"@docusaurus/plugin-client-redirects@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/plugin-client-redirects@npm:0.0.0-5703" dependencies: - "@docusaurus/core": 0.0.0-5591 - "@docusaurus/logger": 0.0.0-5591 - "@docusaurus/utils": 0.0.0-5591 - "@docusaurus/utils-common": 0.0.0-5591 - "@docusaurus/utils-validation": 0.0.0-5591 - eta: ^2.0.1 - fs-extra: ^11.1.0 + "@docusaurus/core": 0.0.0-5703 + "@docusaurus/logger": 0.0.0-5703 + "@docusaurus/utils": 0.0.0-5703 + "@docusaurus/utils-common": 0.0.0-5703 + "@docusaurus/utils-validation": 0.0.0-5703 + eta: ^2.2.0 + fs-extra: ^11.1.1 lodash: ^4.17.21 - tslib: ^2.5.0 + tslib: ^2.6.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 9e06448d280e3642fbe6ae02586c430c1245410e225a6f14f35c815d9cf13734b8793266267777b0f49eef968cd30d8247542b4521f3bdde0d5bebbfdd4a757c + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: ac246eeb75028acd6a1d8804572fb89bac5575facf82c35ca3c8441d916980c183f5342a768d31cccc95f2034657bd25cfda24d480a2b8b4abdd693a51d9754e languageName: node linkType: hard -"@docusaurus/plugin-content-blog@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/plugin-content-blog@npm:0.0.0-5591" +"@docusaurus/plugin-content-blog@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/plugin-content-blog@npm:0.0.0-5703" dependencies: - "@docusaurus/core": 0.0.0-5591 - "@docusaurus/logger": 0.0.0-5591 - "@docusaurus/mdx-loader": 0.0.0-5591 - "@docusaurus/types": 0.0.0-5591 - "@docusaurus/utils": 0.0.0-5591 - "@docusaurus/utils-common": 0.0.0-5591 - "@docusaurus/utils-validation": 0.0.0-5591 + "@docusaurus/core": 0.0.0-5703 + "@docusaurus/logger": 0.0.0-5703 + "@docusaurus/mdx-loader": 0.0.0-5703 + "@docusaurus/types": 0.0.0-5703 + "@docusaurus/utils": 0.0.0-5703 + "@docusaurus/utils-common": 0.0.0-5703 + "@docusaurus/utils-validation": 0.0.0-5703 cheerio: ^1.0.0-rc.12 feed: ^4.2.2 - fs-extra: ^11.1.0 + fs-extra: ^11.1.1 lodash: ^4.17.21 reading-time: ^1.5.0 - tslib: ^2.5.0 + srcset: ^4.0.0 + tslib: ^2.6.0 unist-util-visit: ^2.0.3 utility-types: ^3.10.0 - webpack: ^5.76.0 + webpack: ^5.88.1 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 61014344725c5bb003b1ef0e460d9287501f69d7a475b1650ddaffdd5a1609db244f766b1b0a2188f4db1a68f0ddd4dfd3ac6abcd20ed17446fa6294e35bea96 + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 46e4a4fac407a8014ce0918933a476b03adca3d3b7e76b27a87bf0eeeb446f20e25db60b292f743652f3ad88232824f7a1541fcb7d27bcdbf9cb6d1c94e9a1b5 languageName: node linkType: hard -"@docusaurus/plugin-content-docs@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/plugin-content-docs@npm:0.0.0-5591" +"@docusaurus/plugin-content-docs@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/plugin-content-docs@npm:0.0.0-5703" dependencies: - "@docusaurus/core": 0.0.0-5591 - "@docusaurus/logger": 0.0.0-5591 - "@docusaurus/mdx-loader": 0.0.0-5591 - "@docusaurus/module-type-aliases": 0.0.0-5591 - "@docusaurus/types": 0.0.0-5591 - "@docusaurus/utils": 0.0.0-5591 - "@docusaurus/utils-validation": 0.0.0-5591 - "@types/react-router-config": ^5.0.6 + "@docusaurus/core": 0.0.0-5703 + "@docusaurus/logger": 0.0.0-5703 + "@docusaurus/mdx-loader": 0.0.0-5703 + "@docusaurus/module-type-aliases": 0.0.0-5703 + "@docusaurus/types": 0.0.0-5703 + "@docusaurus/utils": 0.0.0-5703 + "@docusaurus/utils-validation": 0.0.0-5703 + "@types/react-router-config": ^5.0.7 combine-promises: ^1.1.0 - fs-extra: ^11.1.0 + fs-extra: ^11.1.1 import-fresh: ^3.3.0 js-yaml: ^4.1.0 lodash: ^4.17.21 - tslib: ^2.5.0 + tslib: ^2.6.0 utility-types: ^3.10.0 - webpack: ^5.76.0 + webpack: ^5.88.1 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 837fa1d6a0e5238ec8d9422a7de2da19380059edfd50946243bbc93f43f813336cd220a2f521e1efc99261218ab3cccaaf64c0977bdbaa14ed09f95924347476 + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: b08fbbac78f76ca68fc4a8ba488f41709733727e073d5f2d1e671dab484c4d37729a657305b315052369292ec7ae83c32992e551eda1d0990c035aa84fecbac6 languageName: node linkType: hard -"@docusaurus/plugin-content-pages@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/plugin-content-pages@npm:0.0.0-5591" +"@docusaurus/plugin-content-pages@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/plugin-content-pages@npm:0.0.0-5703" dependencies: - "@docusaurus/core": 0.0.0-5591 - "@docusaurus/mdx-loader": 0.0.0-5591 - "@docusaurus/types": 0.0.0-5591 - "@docusaurus/utils": 0.0.0-5591 - "@docusaurus/utils-validation": 0.0.0-5591 - fs-extra: ^11.1.0 - tslib: ^2.5.0 - webpack: ^5.76.0 + "@docusaurus/core": 0.0.0-5703 + "@docusaurus/mdx-loader": 0.0.0-5703 + "@docusaurus/types": 0.0.0-5703 + "@docusaurus/utils": 0.0.0-5703 + "@docusaurus/utils-validation": 0.0.0-5703 + fs-extra: ^11.1.1 + tslib: ^2.6.0 + webpack: ^5.88.1 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 74bfbc522fc60d0830b47a0100a0afd66d21d290047432414e9bd94db21d61805b883fc155f6c9ee965023f6153d7fb09b9219386f9140cda52540c40028942f + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 9d0b904259c625d82175fa3fdeae89de8503f409a7dc47c9077f35d25f72fcf76a0a6392f5e790c3bf2604896e1aa0fced00386b9df553f6ba01247ccadd6503 languageName: node linkType: hard -"@docusaurus/plugin-debug@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/plugin-debug@npm:0.0.0-5591" +"@docusaurus/plugin-debug@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/plugin-debug@npm:0.0.0-5703" dependencies: - "@docusaurus/core": 0.0.0-5591 - "@docusaurus/types": 0.0.0-5591 - "@docusaurus/utils": 0.0.0-5591 - fs-extra: ^11.1.0 - react-json-view: ^1.21.3 - tslib: ^2.5.0 + "@docusaurus/core": 0.0.0-5703 + "@docusaurus/types": 0.0.0-5703 + "@docusaurus/utils": 0.0.0-5703 + "@microlink/react-json-view": ^1.22.2 + fs-extra: ^11.1.1 + tslib: ^2.6.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: f42bc6e5139e9aff99eab24a506f74fd9b0ef3baecf46fadb0596ead8167d58c4ba92b86a9e665d00bedaccbfeb7c483c02ef4f1c5de49cc966e457e624c0b45 + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: b9bf04c27144dc797fa25cae6df95f5a8b15c888993194bf1b0fae06ce6ae55cf338270b7a914ef07d6551addd6261e628a465c4f277a4e13753c207e533557d languageName: node linkType: hard -"@docusaurus/plugin-google-analytics@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/plugin-google-analytics@npm:0.0.0-5591" +"@docusaurus/plugin-google-analytics@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/plugin-google-analytics@npm:0.0.0-5703" dependencies: - "@docusaurus/core": 0.0.0-5591 - "@docusaurus/types": 0.0.0-5591 - "@docusaurus/utils-validation": 0.0.0-5591 - tslib: ^2.5.0 + "@docusaurus/core": 0.0.0-5703 + "@docusaurus/types": 0.0.0-5703 + "@docusaurus/utils-validation": 0.0.0-5703 + tslib: ^2.6.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 7c8b9bdb182b0eff01d6f85eb01cc6ffeb3325cb0c154187230328484669f346fa998dfa25bc474f9b03551c6351a2da76f31d68f2c7ce742382d579a32e89e7 + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: ad98ea301caa4908197a3c460ae88dd5598c1485d8643708e8fb3f757ae3bf854efc1b5a1ab9c8ba15371c3a989704d7f9fdb55dd25d1d1b81936526068a877b languageName: node linkType: hard -"@docusaurus/plugin-google-gtag@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/plugin-google-gtag@npm:0.0.0-5591" +"@docusaurus/plugin-google-gtag@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/plugin-google-gtag@npm:0.0.0-5703" dependencies: - "@docusaurus/core": 0.0.0-5591 - "@docusaurus/types": 0.0.0-5591 - "@docusaurus/utils-validation": 0.0.0-5591 + "@docusaurus/core": 0.0.0-5703 + "@docusaurus/types": 0.0.0-5703 + "@docusaurus/utils-validation": 0.0.0-5703 "@types/gtag.js": ^0.0.12 - tslib: ^2.5.0 + tslib: ^2.6.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 38daa81f7d499c819bf6221a9ba36d71e10f98f2c2e6b5adbcfcfbfc3f54e32df8315c98f381c9107f40ebe7aa9f7074dd16de6f925501f712dae73de3272133 + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 9fbdbc0569f1ff634c357d197c1442da17c4a09c03163640db1d1bde0be8612dd432e494a4f02eb43ac58dd7df2cbd335911fdb7fa315a9de95e173090daf5dc languageName: node linkType: hard -"@docusaurus/plugin-google-tag-manager@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/plugin-google-tag-manager@npm:0.0.0-5591" +"@docusaurus/plugin-google-tag-manager@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/plugin-google-tag-manager@npm:0.0.0-5703" dependencies: - "@docusaurus/core": 0.0.0-5591 - "@docusaurus/types": 0.0.0-5591 - "@docusaurus/utils-validation": 0.0.0-5591 - tslib: ^2.5.0 + "@docusaurus/core": 0.0.0-5703 + "@docusaurus/types": 0.0.0-5703 + "@docusaurus/utils-validation": 0.0.0-5703 + tslib: ^2.6.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: afc7e93de44fbee69183e285fc429cc406c184e28a8b8f3f774ee33d88a1edf6c12449bf3ad731d36b475b3915b5692925bd2cb48127ab92402cde6ff4442584 + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 3ed2c6eb05087db3877ffe98cc6eca59be80889411e3cdbd981ac4d951a5efa269a1011a39a94c997d93474fd916e3634905a6537e10575e5d5a954a9bb00c5d languageName: node linkType: hard -"@docusaurus/plugin-sitemap@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/plugin-sitemap@npm:0.0.0-5591" +"@docusaurus/plugin-sitemap@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/plugin-sitemap@npm:0.0.0-5703" dependencies: - "@docusaurus/core": 0.0.0-5591 - "@docusaurus/logger": 0.0.0-5591 - "@docusaurus/types": 0.0.0-5591 - "@docusaurus/utils": 0.0.0-5591 - "@docusaurus/utils-common": 0.0.0-5591 - "@docusaurus/utils-validation": 0.0.0-5591 - fs-extra: ^11.1.0 + "@docusaurus/core": 0.0.0-5703 + "@docusaurus/logger": 0.0.0-5703 + "@docusaurus/types": 0.0.0-5703 + "@docusaurus/utils": 0.0.0-5703 + "@docusaurus/utils-common": 0.0.0-5703 + "@docusaurus/utils-validation": 0.0.0-5703 + fs-extra: ^11.1.1 sitemap: ^7.1.1 - tslib: ^2.5.0 + tslib: ^2.6.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: cf9b5397699e3f7ff4d3fef175dfdfa66820ffd40a4892991634423331d19849da8f0d78bc453b5e964ff25a9705d4ad1e9dd0dcdc27b8520c6108594c491fc1 + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 1afbd2e3575ae09428fb4c53a2563e313c3e1a2323c79bdc256779c56f8d796c2c94473d055d6d7a97d477f06e35f0922bed441f7c3e1467feeb5329e1f7761b languageName: node linkType: hard -"@docusaurus/preset-classic@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/preset-classic@npm:0.0.0-5591" +"@docusaurus/preset-classic@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/preset-classic@npm:0.0.0-5703" dependencies: - "@docusaurus/core": 0.0.0-5591 - "@docusaurus/plugin-content-blog": 0.0.0-5591 - "@docusaurus/plugin-content-docs": 0.0.0-5591 - "@docusaurus/plugin-content-pages": 0.0.0-5591 - "@docusaurus/plugin-debug": 0.0.0-5591 - "@docusaurus/plugin-google-analytics": 0.0.0-5591 - "@docusaurus/plugin-google-gtag": 0.0.0-5591 - "@docusaurus/plugin-google-tag-manager": 0.0.0-5591 - "@docusaurus/plugin-sitemap": 0.0.0-5591 - "@docusaurus/theme-classic": 0.0.0-5591 - "@docusaurus/theme-common": 0.0.0-5591 - "@docusaurus/theme-search-algolia": 0.0.0-5591 - "@docusaurus/types": 0.0.0-5591 + "@docusaurus/core": 0.0.0-5703 + "@docusaurus/plugin-content-blog": 0.0.0-5703 + "@docusaurus/plugin-content-docs": 0.0.0-5703 + "@docusaurus/plugin-content-pages": 0.0.0-5703 + "@docusaurus/plugin-debug": 0.0.0-5703 + "@docusaurus/plugin-google-analytics": 0.0.0-5703 + "@docusaurus/plugin-google-gtag": 0.0.0-5703 + "@docusaurus/plugin-google-tag-manager": 0.0.0-5703 + "@docusaurus/plugin-sitemap": 0.0.0-5703 + "@docusaurus/theme-classic": 0.0.0-5703 + "@docusaurus/theme-common": 0.0.0-5703 + "@docusaurus/theme-search-algolia": 0.0.0-5703 + "@docusaurus/types": 0.0.0-5703 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 3e613a95622482510f3fdad017ceabcdf0d25d82560af665b536803d4fb746cd4e849fbe02304f60099a3e09845003bb433bedeb1b3fcde13b93522e775350f1 + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: d4c2e6e02b828b248351819410fe03e94a4b4fd8489e398b60d128ba8f173548f8353a3875ff0347179ee59e84df7e3e9e1e5b0be24b84f015c8c02b650eb80c languageName: node linkType: hard @@ -1993,161 +2065,160 @@ __metadata: languageName: node linkType: hard -"@docusaurus/theme-classic@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/theme-classic@npm:0.0.0-5591" +"@docusaurus/theme-classic@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/theme-classic@npm:0.0.0-5703" dependencies: - "@docusaurus/core": 0.0.0-5591 - "@docusaurus/mdx-loader": 0.0.0-5591 - "@docusaurus/module-type-aliases": 0.0.0-5591 - "@docusaurus/plugin-content-blog": 0.0.0-5591 - "@docusaurus/plugin-content-docs": 0.0.0-5591 - "@docusaurus/plugin-content-pages": 0.0.0-5591 - "@docusaurus/theme-common": 0.0.0-5591 - "@docusaurus/theme-translations": 0.0.0-5591 - "@docusaurus/types": 0.0.0-5591 - "@docusaurus/utils": 0.0.0-5591 - "@docusaurus/utils-common": 0.0.0-5591 - "@docusaurus/utils-validation": 0.0.0-5591 + "@docusaurus/core": 0.0.0-5703 + "@docusaurus/mdx-loader": 0.0.0-5703 + "@docusaurus/module-type-aliases": 0.0.0-5703 + "@docusaurus/plugin-content-blog": 0.0.0-5703 + "@docusaurus/plugin-content-docs": 0.0.0-5703 + "@docusaurus/plugin-content-pages": 0.0.0-5703 + "@docusaurus/theme-common": 0.0.0-5703 + "@docusaurus/theme-translations": 0.0.0-5703 + "@docusaurus/types": 0.0.0-5703 + "@docusaurus/utils": 0.0.0-5703 + "@docusaurus/utils-common": 0.0.0-5703 + "@docusaurus/utils-validation": 0.0.0-5703 "@mdx-js/react": ^2.1.5 clsx: ^1.2.1 - copy-text-to-clipboard: ^3.0.1 + copy-text-to-clipboard: ^3.2.0 infima: 0.2.0-alpha.43 lodash: ^4.17.21 nprogress: ^0.2.0 - postcss: ^8.4.21 - prism-react-renderer: ^1.3.5 + postcss: ^8.4.26 + prism-react-renderer: ^2.1.0 prismjs: ^1.29.0 react-router-dom: ^5.3.4 - rtlcss: ^4.0.0 - tslib: ^2.5.0 + rtlcss: ^4.1.0 + tslib: ^2.6.0 utility-types: ^3.10.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 1bcfdb13c932e02dbd292b9a3215fff039dbf317f0cedf3d88aa365e15d5a2653f23c3e284930d33263bc6bf2887578140affa752c146a2395acb75818db64bf + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: ba078e06a07bbcc4a474f67938760852146e0cb612e44bc81b22879d374372eeea076de6e46e9f955dd351f37dadd98ced2e70b6b8a476b88684fae40855ecb9 languageName: node linkType: hard -"@docusaurus/theme-common@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/theme-common@npm:0.0.0-5591" +"@docusaurus/theme-common@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/theme-common@npm:0.0.0-5703" dependencies: - "@docusaurus/mdx-loader": 0.0.0-5591 - "@docusaurus/module-type-aliases": 0.0.0-5591 - "@docusaurus/plugin-content-blog": 0.0.0-5591 - "@docusaurus/plugin-content-docs": 0.0.0-5591 - "@docusaurus/plugin-content-pages": 0.0.0-5591 - "@docusaurus/utils": 0.0.0-5591 - "@docusaurus/utils-common": 0.0.0-5591 + "@docusaurus/mdx-loader": 0.0.0-5703 + "@docusaurus/module-type-aliases": 0.0.0-5703 + "@docusaurus/plugin-content-blog": 0.0.0-5703 + "@docusaurus/plugin-content-docs": 0.0.0-5703 + "@docusaurus/plugin-content-pages": 0.0.0-5703 + "@docusaurus/utils": 0.0.0-5703 + "@docusaurus/utils-common": 0.0.0-5703 "@types/history": ^4.7.11 "@types/react": "*" "@types/react-router-config": "*" clsx: ^1.2.1 parse-numeric-range: ^1.3.0 - prism-react-renderer: ^1.3.5 - tslib: ^2.5.0 - use-sync-external-store: ^1.2.0 + prism-react-renderer: ^2.1.0 + tslib: ^2.6.0 utility-types: ^3.10.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: bd941e6eac23310748aa70a35c41ad6e9123ea93ed0b872d6beb3313df847827dc5490000cc443d83d31157841cbf4d58fc2f844c743b3cf2fe6ccc7d1507deb + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: f9b23318dbb504bcce0992de475f1ab32860620523dfe749bfdb00ac8e7fc75be705fd5177db2ce893ed269de40cef7f6a7290d44a12c6a160d9461bbca05552 languageName: node linkType: hard -"@docusaurus/theme-search-algolia@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/theme-search-algolia@npm:0.0.0-5591" +"@docusaurus/theme-search-algolia@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/theme-search-algolia@npm:0.0.0-5703" dependencies: - "@docsearch/react": ^3.3.3 - "@docusaurus/core": 0.0.0-5591 - "@docusaurus/logger": 0.0.0-5591 - "@docusaurus/plugin-content-docs": 0.0.0-5591 - "@docusaurus/theme-common": 0.0.0-5591 - "@docusaurus/theme-translations": 0.0.0-5591 - "@docusaurus/utils": 0.0.0-5591 - "@docusaurus/utils-validation": 0.0.0-5591 - algoliasearch: ^4.15.0 - algoliasearch-helper: ^3.12.0 + "@docsearch/react": ^3.5.2 + "@docusaurus/core": 0.0.0-5703 + "@docusaurus/logger": 0.0.0-5703 + "@docusaurus/plugin-content-docs": 0.0.0-5703 + "@docusaurus/theme-common": 0.0.0-5703 + "@docusaurus/theme-translations": 0.0.0-5703 + "@docusaurus/utils": 0.0.0-5703 + "@docusaurus/utils-validation": 0.0.0-5703 + algoliasearch: ^4.18.0 + algoliasearch-helper: ^3.13.3 clsx: ^1.2.1 - eta: ^2.0.1 - fs-extra: ^11.1.0 + eta: ^2.2.0 + fs-extra: ^11.1.1 lodash: ^4.17.21 - tslib: ^2.5.0 + tslib: ^2.6.0 utility-types: ^3.10.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 7493eb67c7ba056aee42880006cd0587d81e05f81177f93d6f57f43f9af12cd2c9e6bed7b804c19a66fa6f192c5b6ccbbf9e16f923a48abe6c6a6a72d65bd5c1 + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 2e8ccc603126634488332ae108f9ac9ad3d2e1e46b5abef48720f2a25ae5cfc93850301d4ea30a6dc66034877b6abedd31229f622c6fd181347c3c14f7ba3c66 languageName: node linkType: hard -"@docusaurus/theme-translations@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/theme-translations@npm:0.0.0-5591" +"@docusaurus/theme-translations@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/theme-translations@npm:0.0.0-5703" dependencies: - fs-extra: ^11.1.0 - tslib: ^2.5.0 - checksum: 6dd8647d1db2a97c77f3aa0d5f6935bad21df97f26d20d0a08916717335f50e72193c2bd7417043c9fb5fb4d9c19140f1408c854df5ef92ff6210bcc8e55f917 + fs-extra: ^11.1.1 + tslib: ^2.6.0 + checksum: 1f952386982008e2e7b07d6b95b1a902a57891321ae2670f13f391a541944ec2c82f5e03d3ed2c459a17113387a51cb5efe824d03037a3cc0b25251451287d1d languageName: node linkType: hard -"@docusaurus/types@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/types@npm:0.0.0-5591" +"@docusaurus/types@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/types@npm:0.0.0-5703" dependencies: "@types/history": ^4.7.11 "@types/react": "*" commander: ^5.1.0 - joi: ^17.8.3 + joi: ^17.9.2 react-helmet-async: ^1.3.0 utility-types: ^3.10.0 - webpack: ^5.76.0 - webpack-merge: ^5.8.0 + webpack: ^5.88.1 + webpack-merge: ^5.9.0 peerDependencies: - react: ^16.8.4 || ^17.0.0 - react-dom: ^16.8.4 || ^17.0.0 - checksum: 6ea7a688f7cef509e0f3b5ab2a9bb9fb0841ffd033d82438b989a70344655a7420b456f5172be9aa13740316212970e4d9d3bc355eb5fd4c9b27c635baeb149a + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 46ca6a27c8a0d1b69f744375ee2c24be2deed20c2801231a462b2e37b7a6e1f73ab17b6a5506e05f628957be8be74e4cd960780b9986c8fa4ac1757bd8c74231 languageName: node linkType: hard -"@docusaurus/utils-common@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/utils-common@npm:0.0.0-5591" +"@docusaurus/utils-common@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/utils-common@npm:0.0.0-5703" dependencies: - tslib: ^2.5.0 + tslib: ^2.6.0 peerDependencies: "@docusaurus/types": "*" peerDependenciesMeta: "@docusaurus/types": optional: true - checksum: 6c21dac13338854bfaebef0a98b1c76a95f29cc16ae6cd43fac0734dbc16cec0df058339af7ebb6ca3dc3cd2ad2a21f4bbff221c9cf7ae5012a88bfc4b28f4d9 + checksum: 8f70f176a99bcbbde22abd759621087ad555e7967cddf85662402f6d55c84d5f44cc1a90bf4e64670fc75b6db646dca4f573b3656a1718d1596d60e0e6c2d23a languageName: node linkType: hard -"@docusaurus/utils-validation@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/utils-validation@npm:0.0.0-5591" +"@docusaurus/utils-validation@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/utils-validation@npm:0.0.0-5703" dependencies: - "@docusaurus/logger": 0.0.0-5591 - "@docusaurus/utils": 0.0.0-5591 - joi: ^17.8.3 + "@docusaurus/logger": 0.0.0-5703 + "@docusaurus/utils": 0.0.0-5703 + joi: ^17.9.2 js-yaml: ^4.1.0 - tslib: ^2.5.0 - checksum: 987acdce5ae5ce4c5bd78258201809889209d7293b063eb38888637452c80ecff72d12d84a7ce7fc49f52d61ca2a79c61006f3562b4180e379a1777b9d76493a + tslib: ^2.6.0 + checksum: e0d6df549644d8e732daf5407ce110dbccba17dcf84fe1a80091119675d2ce515e26bf6612fefa60b7df2c65dbaeee7ceb1a9f2b947a3705fe1efc7c229794e2 languageName: node linkType: hard -"@docusaurus/utils@npm:0.0.0-5591": - version: 0.0.0-5591 - resolution: "@docusaurus/utils@npm:0.0.0-5591" +"@docusaurus/utils@npm:0.0.0-5703": + version: 0.0.0-5703 + resolution: "@docusaurus/utils@npm:0.0.0-5703" dependencies: - "@docusaurus/logger": 0.0.0-5591 + "@docusaurus/logger": 0.0.0-5703 "@svgr/webpack": ^6.5.1 escape-string-regexp: ^4.0.0 file-loader: ^6.2.0 - fs-extra: ^11.1.0 + fs-extra: ^11.1.1 github-slugger: ^1.5.0 globby: ^11.1.0 gray-matter: ^4.0.3 @@ -2156,15 +2227,15 @@ __metadata: micromatch: ^4.0.5 resolve-pathname: ^3.0.0 shelljs: ^0.8.5 - tslib: ^2.5.0 + tslib: ^2.6.0 url-loader: ^4.1.1 - webpack: ^5.76.0 + webpack: ^5.88.1 peerDependencies: "@docusaurus/types": "*" peerDependenciesMeta: "@docusaurus/types": optional: true - checksum: 287d991f7a1924df744ed3a5c0d505a5b903b8bd43df39aac3c45fcc139639fb5b7827d12e4e00787126ad216006483723390141eb283ab733e4b6de819f5cd5 + checksum: 91f53b17393e29fadb01c039f5394fc257c54bd7d80068f3a3e8a5e52d635d2e3de9fe781340de2ff4eaf691a2d4104865291c05c22ffc8b48a0894f588f3a9e languageName: node linkType: hard @@ -2239,13 +2310,13 @@ __metadata: languageName: node linkType: hard -"@jridgewell/source-map@npm:^0.3.2": - version: 0.3.2 - resolution: "@jridgewell/source-map@npm:0.3.2" +"@jridgewell/source-map@npm:^0.3.3": + version: 0.3.5 + resolution: "@jridgewell/source-map@npm:0.3.5" dependencies: "@jridgewell/gen-mapping": ^0.3.0 "@jridgewell/trace-mapping": ^0.3.9 - checksum: 1b83f0eb944e77b70559a394d5d3b3f98a81fcc186946aceb3ef42d036762b52ef71493c6c0a3b7c1d2f08785f53ba2df1277fe629a06e6109588ff4cdcf7482 + checksum: 1ad4dec0bdafbade57920a50acec6634f88a0eb735851e0dda906fa9894e7f0549c492678aad1a10f8e144bfe87f238307bf2a914a1bc85b7781d345417e9f6f languageName: node linkType: hard @@ -2310,6 +2381,21 @@ __metadata: languageName: node linkType: hard +"@microlink/react-json-view@npm:^1.22.2": + version: 1.22.2 + resolution: "@microlink/react-json-view@npm:1.22.2" + dependencies: + flux: ~4.0.1 + react-base16-styling: ~0.6.0 + react-lifecycles-compat: ~3.0.4 + react-textarea-autosize: ~8.3.2 + peerDependencies: + react: ">= 15" + react-dom: ">= 15" + checksum: 7cc31fcc06f6bac2062aedda565e55a03e1275f5b810f0efee27de8ea60967713f3a13859a16ba775b9b3e8782c044928cf3faee48902a19ce1c58d7ecc6e8d0 + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -2428,6 +2514,17 @@ __metadata: languageName: node linkType: hard +"@slorber/remark-comment@npm:^1.0.0": + version: 1.0.0 + resolution: "@slorber/remark-comment@npm:1.0.0" + dependencies: + micromark-factory-space: ^1.0.0 + micromark-util-character: ^1.1.0 + micromark-util-symbol: ^1.0.1 + checksum: c96f1533d09913c57381859966f10a706afd8eb680923924af1c451f3b72f22c31e394028d7535131c10f8682d3c60206da95c50fb4f016fbbd04218c853cc88 + languageName: node + linkType: hard + "@slorber/static-site-generator-webpack-plugin@npm:^4.0.7": version: 4.0.7 resolution: "@slorber/static-site-generator-webpack-plugin@npm:4.0.7" @@ -2973,6 +3070,15 @@ __metadata: languageName: node linkType: hard +"@types/mdast@npm:^4.0.0": + version: 4.0.1 + resolution: "@types/mdast@npm:4.0.1" + dependencies: + "@types/unist": "*" + checksum: 3d8fe54a6fb747376c4cc2f05c319730a5737b77844d8ea58d2d696417fa933cd270c20e197f531fc1b4be5e340dc416129f8b4f5fa2f0d2d0cf51850928340a + languageName: node + linkType: hard + "@types/mdx@npm:^2.0.0": version: 2.0.5 resolution: "@types/mdx@npm:2.0.5" @@ -3022,6 +3128,13 @@ __metadata: languageName: node linkType: hard +"@types/prismjs@npm:^1.26.0": + version: 1.26.1 + resolution: "@types/prismjs@npm:1.26.1" + checksum: ef34b2f47e34645760a48fc351e5926c330810a724c64838bfc30b7317c6038ea66abd19fe9c713002679d6f2faa97d90d432869e512dcb660d9a791c150595a + languageName: node + linkType: hard + "@types/prop-types@npm:*": version: 15.7.5 resolution: "@types/prop-types@npm:15.7.5" @@ -3043,14 +3156,14 @@ __metadata: languageName: node linkType: hard -"@types/react-router-config@npm:*, @types/react-router-config@npm:^5.0.6": - version: 5.0.6 - resolution: "@types/react-router-config@npm:5.0.6" +"@types/react-router-config@npm:*, @types/react-router-config@npm:^5.0.7": + version: 5.0.8 + resolution: "@types/react-router-config@npm:5.0.8" dependencies: "@types/history": ^4.7.11 "@types/react": "*" - "@types/react-router": "*" - checksum: e32a7b19d14c1c07e2c06630207bc4ecf86a01585b832bf3c0756c9eaca312b5839bc8d50e8d744738ea50e7bbde0be3b1fd14a6a9398159d36bce33aff7f280 + "@types/react-router": ^5.1.0 + checksum: afbd96e526fcdd19a3c8604912496a5a7ecfdcd848632a003ef8af69701ca74f14451e4fac93d265b678ca07c82ec4a103126f64c040a4aefa1a8172619be2bd languageName: node linkType: hard @@ -3065,13 +3178,13 @@ __metadata: languageName: node linkType: hard -"@types/react-router@npm:*": - version: 5.1.19 - resolution: "@types/react-router@npm:5.1.19" +"@types/react-router@npm:*, @types/react-router@npm:^5.1.0": + version: 5.1.20 + resolution: "@types/react-router@npm:5.1.20" dependencies: "@types/history": ^4.7.11 "@types/react": "*" - checksum: 3536c3dec7af1f12fed2bea246eb143bd893ee66d4e58c1d3fe734cbd67d8a0aedac0bba9255c58fc69dbd32ae17ad280d6866916aee32653a705178e4a544dc + checksum: 128764143473a5e9457ddc715436b5d49814b1c214dde48939b9bef23f0e77f52ffcdfa97eb8d3cc27e2c229869c0cdd90f637d887b62f2c9f065a87d6425419 languageName: node linkType: hard @@ -3137,7 +3250,14 @@ __metadata: languageName: node linkType: hard -"@types/unist@npm:*, @types/unist@npm:^2.0.0": +"@types/unist@npm:*, @types/unist@npm:^3.0.0": + version: 3.0.0 + resolution: "@types/unist@npm:3.0.0" + checksum: e9d21a8fb5e332be0acef29192d82632875b2ef3e700f1bc64fdfc1520189542de85c3d4f3bcfbc2f4afdb210f4c23f68061f3fbf10744e920d4f18430d19f49 + languageName: node + linkType: hard + +"@types/unist@npm:^2.0.0": version: 2.0.6 resolution: "@types/unist@npm:2.0.6" checksum: 25cb860ff10dde48b54622d58b23e66214211a61c84c0f15f88d38b61aa1b53d4d46e42b557924a93178c501c166aa37e28d7f6d994aba13d24685326272d5db @@ -3151,12 +3271,12 @@ __metadata: languageName: node linkType: hard -"@types/ws@npm:^8.5.1": - version: 8.5.3 - resolution: "@types/ws@npm:8.5.3" +"@types/ws@npm:^8.5.5": + version: 8.5.6 + resolution: "@types/ws@npm:8.5.6" dependencies: "@types/node": "*" - checksum: 0ce46f850d41383fcdc2149bcacc86d7232fa7a233f903d2246dff86e31701a02f8566f40af5f8b56d1834779255c04ec6ec78660fe0f9b2a69cf3d71937e4ae + checksum: 7addb0c5fa4e7713d5209afb8a90f1852b12c02cb537395adf7a05fbaf21205dc5f7c110fd5ad6f3dbf147112cbff33fb11d8633059cb344f0c14f595b1ea1fb languageName: node linkType: hard @@ -3358,12 +3478,12 @@ __metadata: languageName: node linkType: hard -"acorn-import-assertions@npm:^1.7.6": - version: 1.8.0 - resolution: "acorn-import-assertions@npm:1.8.0" +"acorn-import-assertions@npm:^1.9.0": + version: 1.9.0 + resolution: "acorn-import-assertions@npm:1.9.0" peerDependencies: acorn: ^8 - checksum: 5c4cf7c850102ba7ae0eeae0deb40fb3158c8ca5ff15c0bca43b5c47e307a1de3d8ef761788f881343680ea374631ae9e9615ba8876fee5268dbe068c98bcba6 + checksum: 944fb2659d0845c467066bdcda2e20c05abe3aaf11972116df457ce2627628a81764d800dd55031ba19de513ee0d43bb771bc679cc0eda66dc8b4fade143bc0c languageName: node linkType: hard @@ -3383,12 +3503,12 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.0.0, acorn@npm:^8.0.4, acorn@npm:^8.5.0, acorn@npm:^8.7.1": - version: 8.8.2 - resolution: "acorn@npm:8.8.2" +"acorn@npm:^8.0.0, acorn@npm:^8.0.4, acorn@npm:^8.7.1, acorn@npm:^8.8.2": + version: 8.10.0 + resolution: "acorn@npm:8.10.0" bin: acorn: bin/acorn - checksum: f790b99a1bf63ef160c967e23c46feea7787e531292bb827126334612c234ed489a0dc2c7ba33156416f0ffa8d25bf2b0fdb7f35c2ba60eb3e960572bece4001 + checksum: 538ba38af0cc9e5ef983aee196c4b8b4d87c0c94532334fa7e065b2c8a1f85863467bb774231aae91613fcda5e68740c15d97b1967ae3394d20faddddd8af61d languageName: node linkType: hard @@ -3487,36 +3607,36 @@ __metadata: languageName: node linkType: hard -"algoliasearch-helper@npm:^3.12.0": - version: 3.12.0 - resolution: "algoliasearch-helper@npm:3.12.0" +"algoliasearch-helper@npm:^3.13.3": + version: 3.14.2 + resolution: "algoliasearch-helper@npm:3.14.2" dependencies: "@algolia/events": ^4.0.1 peerDependencies: algoliasearch: ">= 3.1 < 6" - checksum: 177ead2a04c60f1005a9ccac4096714cd992f0f158b91791deb719765f9a94ea67efc782f29cf5182e9a8ce75bcf7461bb8bf8bab9846b5fa1b9ed1f8a2b902f + checksum: d66444b25fe8ee64675bb660ff1980870751818cb4a29c57bda6ca410372f2bfa031a455dcd5981941736db89d8294187c5b3bc1ce2a2567c6e43657ccd208b8 languageName: node linkType: hard -"algoliasearch@npm:^4.0.0, algoliasearch@npm:^4.15.0": - version: 4.17.0 - resolution: "algoliasearch@npm:4.17.0" +"algoliasearch@npm:^4.18.0, algoliasearch@npm:^4.19.1": + version: 4.20.0 + resolution: "algoliasearch@npm:4.20.0" dependencies: - "@algolia/cache-browser-local-storage": 4.17.0 - "@algolia/cache-common": 4.17.0 - "@algolia/cache-in-memory": 4.17.0 - "@algolia/client-account": 4.17.0 - "@algolia/client-analytics": 4.17.0 - "@algolia/client-common": 4.17.0 - "@algolia/client-personalization": 4.17.0 - "@algolia/client-search": 4.17.0 - "@algolia/logger-common": 4.17.0 - "@algolia/logger-console": 4.17.0 - "@algolia/requester-browser-xhr": 4.17.0 - "@algolia/requester-common": 4.17.0 - "@algolia/requester-node-http": 4.17.0 - "@algolia/transporter": 4.17.0 - checksum: 982fd46519283ea769142aebb24eb15a0f8090a8211159c60772d0333bbb7f4dec1edcc72fc79223aa87ebf2a970d9d12b5735236f47fc3b5c5b07dd2eb24e35 + "@algolia/cache-browser-local-storage": 4.20.0 + "@algolia/cache-common": 4.20.0 + "@algolia/cache-in-memory": 4.20.0 + "@algolia/client-account": 4.20.0 + "@algolia/client-analytics": 4.20.0 + "@algolia/client-common": 4.20.0 + "@algolia/client-personalization": 4.20.0 + "@algolia/client-search": 4.20.0 + "@algolia/logger-common": 4.20.0 + "@algolia/logger-console": 4.20.0 + "@algolia/requester-browser-xhr": 4.20.0 + "@algolia/requester-common": 4.20.0 + "@algolia/requester-node-http": 4.20.0 + "@algolia/transporter": 4.20.0 + checksum: 078954944452f57d2e3b47c6ed4905caf797814324a4d5068a8b6685d434a885977a3e607714c5fb6eb29c7c3e717b3ee9cb01c8b2320e2c7bd73bcd8d42e70f languageName: node linkType: hard @@ -3678,13 +3798,13 @@ __metadata: languageName: node linkType: hard -"autoprefixer@npm:^10.4.12, autoprefixer@npm:^10.4.13": - version: 10.4.14 - resolution: "autoprefixer@npm:10.4.14" +"autoprefixer@npm:^10.4.12, autoprefixer@npm:^10.4.14": + version: 10.4.16 + resolution: "autoprefixer@npm:10.4.16" dependencies: - browserslist: ^4.21.5 - caniuse-lite: ^1.0.30001464 - fraction.js: ^4.2.0 + browserslist: ^4.21.10 + caniuse-lite: ^1.0.30001538 + fraction.js: ^4.3.6 normalize-range: ^0.1.2 picocolors: ^1.0.0 postcss-value-parser: ^4.2.0 @@ -3692,7 +3812,7 @@ __metadata: postcss: ^8.1.0 bin: autoprefixer: bin/autoprefixer - checksum: e9f18e664a4e4a54a8f4ec5f6b49ed228ec45afaa76efcae361c93721795dc5ab644f36d2fdfc0dea446b02a8067b9372f91542ea431994399e972781ed46d95 + checksum: 45fad7086495048dacb14bb7b00313e70e135b5d8e8751dcc60548889400763705ab16fc2d99ea628b44c3472698fb0e39598f595ba28409c965ab159035afde languageName: node linkType: hard @@ -3706,16 +3826,16 @@ __metadata: languageName: node linkType: hard -"babel-loader@npm:^9.1.2": - version: 9.1.2 - resolution: "babel-loader@npm:9.1.2" +"babel-loader@npm:^9.1.3": + version: 9.1.3 + resolution: "babel-loader@npm:9.1.3" dependencies: - find-cache-dir: ^3.3.2 + find-cache-dir: ^4.0.0 schema-utils: ^4.0.0 peerDependencies: "@babel/core": ^7.12.0 webpack: ">=5" - checksum: f0edb8e157f9806b810ba3f2c8ca8fa489d377ae5c2b7b00c2ace900a6925641ce4ec520b9c12f70e37b94aa5366e7003e0f6271b26821643e109966ce741cb7 + checksum: b168dde5b8cf11206513371a79f86bb3faa7c714e6ec9fffd420876b61f3d7f5f4b976431095ef6a14bc4d324505126deb91045fd41e312ba49f4deaa166fe28 languageName: node linkType: hard @@ -3728,39 +3848,39 @@ __metadata: languageName: node linkType: hard -"babel-plugin-polyfill-corejs2@npm:^0.3.3": - version: 0.3.3 - resolution: "babel-plugin-polyfill-corejs2@npm:0.3.3" +"babel-plugin-polyfill-corejs2@npm:^0.4.5": + version: 0.4.5 + resolution: "babel-plugin-polyfill-corejs2@npm:0.4.5" dependencies: - "@babel/compat-data": ^7.17.7 - "@babel/helper-define-polyfill-provider": ^0.3.3 - semver: ^6.1.1 + "@babel/compat-data": ^7.22.6 + "@babel/helper-define-polyfill-provider": ^0.4.2 + semver: ^6.3.1 peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 7db3044993f3dddb3cc3d407bc82e640964a3bfe22de05d90e1f8f7a5cb71460011ab136d3c03c6c1ba428359ebf635688cd6205e28d0469bba221985f5c6179 + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 33a8e06aa54e2858d211c743d179f0487b03222f9ca1bfd7c4865bca243fca942a3358cb75f6bb894ed476cbddede834811fbd6903ff589f055821146f053e1a languageName: node linkType: hard -"babel-plugin-polyfill-corejs3@npm:^0.6.0": - version: 0.6.0 - resolution: "babel-plugin-polyfill-corejs3@npm:0.6.0" +"babel-plugin-polyfill-corejs3@npm:^0.8.3": + version: 0.8.4 + resolution: "babel-plugin-polyfill-corejs3@npm:0.8.4" dependencies: - "@babel/helper-define-polyfill-provider": ^0.3.3 - core-js-compat: ^3.25.1 + "@babel/helper-define-polyfill-provider": ^0.4.2 + core-js-compat: ^3.32.2 peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 470bb8c59f7c0912bd77fe1b5a2e72f349b3f65bbdee1d60d6eb7e1f4a085c6f24b2dd5ab4ac6c2df6444a96b070ef6790eccc9edb6a2668c60d33133bfb62c6 + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: 7243241a5b978b1335d51bcbd1248d6c4df88f6b3726706e71e0392f111c59bbf01118c85bb0ed42dce65e90e8fc768d19eda0a81a321cbe54abd3df9a285dc8 languageName: node linkType: hard -"babel-plugin-polyfill-regenerator@npm:^0.4.1": - version: 0.4.1 - resolution: "babel-plugin-polyfill-regenerator@npm:0.4.1" +"babel-plugin-polyfill-regenerator@npm:^0.5.2": + version: 0.5.2 + resolution: "babel-plugin-polyfill-regenerator@npm:0.5.2" dependencies: - "@babel/helper-define-polyfill-provider": ^0.3.3 + "@babel/helper-define-polyfill-provider": ^0.4.2 peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: ab0355efbad17d29492503230387679dfb780b63b25408990d2e4cf421012dae61d6199ddc309f4d2409ce4e9d3002d187702700dd8f4f8770ebbba651ed066c + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + checksum: d962200f604016a9a09bc9b4aaf60a3db7af876bb65bcefaeac04d44ac9d9ec4037cf24ce117760cc141d7046b6394c7eb0320ba9665cb4a2ee64df2be187c93 languageName: node linkType: hard @@ -3768,10 +3888,10 @@ __metadata: version: 0.0.0-use.local resolution: "backstage-microsite@workspace:." dependencies: - "@docusaurus/core": 0.0.0-5591 - "@docusaurus/module-type-aliases": 0.0.0-5591 - "@docusaurus/plugin-client-redirects": 0.0.0-5591 - "@docusaurus/preset-classic": 0.0.0-5591 + "@docusaurus/core": 0.0.0-5703 + "@docusaurus/module-type-aliases": 0.0.0-5703 + "@docusaurus/plugin-client-redirects": 0.0.0-5703 + "@docusaurus/preset-classic": 0.0.0-5703 "@spotify/prettier-config": ^14.0.0 "@swc/core": ^1.3.46 "@tsconfig/docusaurus": ^1.0.6 @@ -3783,11 +3903,11 @@ __metadata: luxon: ^3.0.0 prettier: ^2.6.2 prism-react-renderer: ^1.3.5 - react: ^17.0.2 - react-dom: ^17.0.2 + react: ^18.0.0 + react-dom: ^18.0.0 sass: ^1.57.1 swc-loader: ^0.2.3 - typescript: ^4.9.4 + typescript: ~5.0.0 yaml-loader: ^0.8.0 languageName: unknown linkType: soft @@ -3933,17 +4053,17 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.14.5, browserslist@npm:^4.18.1, browserslist@npm:^4.21.3, browserslist@npm:^4.21.4, browserslist@npm:^4.21.5": - version: 4.21.5 - resolution: "browserslist@npm:4.21.5" +"browserslist@npm:^4.0.0, browserslist@npm:^4.14.5, browserslist@npm:^4.18.1, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.21.9, browserslist@npm:^4.22.1": + version: 4.22.1 + resolution: "browserslist@npm:4.22.1" dependencies: - caniuse-lite: ^1.0.30001449 - electron-to-chromium: ^1.4.284 - node-releases: ^2.0.8 - update-browserslist-db: ^1.0.10 + caniuse-lite: ^1.0.30001541 + electron-to-chromium: ^1.4.535 + node-releases: ^2.0.13 + update-browserslist-db: ^1.0.13 bin: browserslist: cli.js - checksum: 9755986b22e73a6a1497fd8797aedd88e04270be33ce66ed5d85a1c8a798292a65e222b0f251bafa1c2522261e237d73b08b58689d4920a607e5a53d56dc4706 + checksum: 7e6b10c53f7dd5d83fd2b95b00518889096382539fed6403829d447e05df4744088de46a571071afb447046abc3c66ad06fbc790e70234ec2517452e32ffd862 languageName: node linkType: hard @@ -4069,10 +4189,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001449, caniuse-lite@npm:^1.0.30001464": - version: 1.0.30001481 - resolution: "caniuse-lite@npm:1.0.30001481" - checksum: 8200a043c191b4fd4fe0beda37a58fd61869c895ab93f87bdd0420e5927453f48434d716ce9da8552ff6c3ecc4dcd1366354cda3a134f3cc844af741574a7cab +"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001538, caniuse-lite@npm:^1.0.30001541": + version: 1.0.30001546 + resolution: "caniuse-lite@npm:1.0.30001546" + checksum: d3ef82f5ee94743002c5b2dd61c84342debcc94b2d5907b64ade3514ecfc4f20bbe86a6bc453fd6436d5fbcf6582e07405d7c2077565675a71c83adc238a11fa languageName: node linkType: hard @@ -4083,7 +4203,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^2.0.0": +"chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" dependencies: @@ -4375,10 +4495,10 @@ __metadata: languageName: node linkType: hard -"commondir@npm:^1.0.1": - version: 1.0.1 - resolution: "commondir@npm:1.0.1" - checksum: 59715f2fc456a73f68826285718503340b9f0dd89bfffc42749906c5cf3d4277ef11ef1cca0350d0e79204f00f1f6d83851ececc9095dc88512a697ac0b9bdcb +"common-path-prefix@npm:^3.0.0": + version: 3.0.0 + resolution: "common-path-prefix@npm:3.0.0" + checksum: fdb3c4f54e51e70d417ccd950c07f757582de800c0678ca388aedefefc84982039f346f9fd9a1252d08d2da9e9ef4019f580a1d1d3a10da031e4bb3c924c5818 languageName: node linkType: hard @@ -4480,10 +4600,10 @@ __metadata: languageName: node linkType: hard -"convert-source-map@npm:^1.7.0": - version: 1.9.0 - resolution: "convert-source-map@npm:1.9.0" - checksum: dc55a1f28ddd0e9485ef13565f8f756b342f9a46c4ae18b843fe3c30c675d058d6a4823eff86d472f187b176f0adf51ea7b69ea38be34be4a63cbbf91b0593c8 +"convert-source-map@npm:^2.0.0": + version: 2.0.0 + resolution: "convert-source-map@npm:2.0.0" + checksum: 63ae9933be5a2b8d4509daca5124e20c14d023c820258e484e32dc324d34c2754e71297c94a05784064ad27615037ef677e3f0c00469fb55f409d2bb21261035 languageName: node linkType: hard @@ -4501,10 +4621,10 @@ __metadata: languageName: node linkType: hard -"copy-text-to-clipboard@npm:^3.0.1": - version: 3.0.1 - resolution: "copy-text-to-clipboard@npm:3.0.1" - checksum: 4c301b9a65c8bf337e26a74d28849096651697fac829a364c463df81ba5ddfeea0741214f9f1232832fffd229ebd5659d3abcccea3fe54d7010a22e515cc38bc +"copy-text-to-clipboard@npm:^3.2.0": + version: 3.2.0 + resolution: "copy-text-to-clipboard@npm:3.2.0" + checksum: df7115c197a166d51f59e4e20ab2a68a855ae8746d25ff149b5465c694d9a405c7e6684b73a9f87ba8d653070164e229c15dfdb9fd77c30be1ff0da569661060 languageName: node linkType: hard @@ -4524,26 +4644,26 @@ __metadata: languageName: node linkType: hard -"core-js-compat@npm:^3.25.1": - version: 3.26.1 - resolution: "core-js-compat@npm:3.26.1" +"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.32.2": + version: 3.33.0 + resolution: "core-js-compat@npm:3.33.0" dependencies: - browserslist: ^4.21.4 - checksum: f222bce0002eae405327d68286e1d566037e8ac21906a47d7ecd15858adca7b12e82140db11dc43c8cc1fc066c5306120f3c27bfb2d7dbc2d20a72a2d90d38dc + browserslist: ^4.22.1 + checksum: 83ae54008c09b8e0ae3c59457039866c342c7e28b0d30eebb638a5b51c01432e63fe97695c90645cbc6a8b073a4f9a8b0e75f0818bbf8b4b054e01f4c17d3181 languageName: node linkType: hard -"core-js-pure@npm:^3.25.1": - version: 3.26.1 - resolution: "core-js-pure@npm:3.26.1" - checksum: d88c40e5e29e413c11d1ef991a8d5b6a63f00bd94707af0f649d3fc18b3524108b202f4ae75ce77620a1557d1ba340bc3362b4f25d590eccc37cf80fc75f7cd4 +"core-js-pure@npm:^3.30.2": + version: 3.33.0 + resolution: "core-js-pure@npm:3.33.0" + checksum: d47084a4de9a0cef9779eccd3ac9f435cf9fd7aa71794150cd4c6b305036bcc392d94766d4a7b6456bdd08faba7752d55c2ec40185bda161c3563081c9fa1e17 languageName: node linkType: hard -"core-js@npm:^3.29.0": - version: 3.30.1 - resolution: "core-js@npm:3.30.1" - checksum: 6d4a00b488694d4c715c424e15dfef31433ac7aa395c39c518a0cfacec918ada1c716fed74682033197e0164e23bbf38bfd598ee9a239c4aaa590ab1ba862ac8 +"core-js@npm:^3.31.1": + version: 3.33.0 + resolution: "core-js@npm:3.33.0" + checksum: dd62217935ac281faf6f833bb306fb891162919fcf9c1f0c975b1b91e82ac09a940f5deb5950bbb582739ceef716e8bd7e4f9eab8328932fb029d3bc2ecb2881 languageName: node linkType: hard @@ -4554,18 +4674,6 @@ __metadata: languageName: node linkType: hard -"cosmiconfig-typescript-loader@npm:^4.3.0": - version: 4.3.0 - resolution: "cosmiconfig-typescript-loader@npm:4.3.0" - peerDependencies: - "@types/node": "*" - cosmiconfig: ">=7" - ts-node: ">=10" - typescript: ">=3" - checksum: ea61dfd8e112cf2bb18df0ef89280bd3ae3dd5b997b4a9fc22bbabdc02513aadfbc6d4e15e922b6a9a5d987e9dad42286fa38caf77a9b8dcdbe7d4ce1c9db4fb - languageName: node - linkType: hard - "cosmiconfig@npm:^6.0.0": version: 6.0.0 resolution: "cosmiconfig@npm:6.0.0" @@ -4592,15 +4700,20 @@ __metadata: languageName: node linkType: hard -"cosmiconfig@npm:^8.1.3": - version: 8.1.3 - resolution: "cosmiconfig@npm:8.1.3" +"cosmiconfig@npm:^8.2.0": + version: 8.3.6 + resolution: "cosmiconfig@npm:8.3.6" dependencies: - import-fresh: ^3.2.1 + import-fresh: ^3.3.0 js-yaml: ^4.1.0 - parse-json: ^5.0.0 + parse-json: ^5.2.0 path-type: ^4.0.0 - checksum: b3d277bc3a8a9e649bf4c3fc9740f4c52bf07387481302aa79839f595045368903bf26ea24a8f7f7b8b180bf46037b027c5cb63b1391ab099f3f78814a147b2b + peerDependencies: + typescript: ">=4.9.5" + peerDependenciesMeta: + typescript: + optional: true + checksum: dc339ebea427898c9e03bf01b56ba7afbac07fc7d2a2d5a15d6e9c14de98275a9565da949375aee1809591c152c0a3877bb86dbeaf74d5bd5aaa79955ad9e7a0 languageName: node linkType: hard @@ -4642,21 +4755,21 @@ __metadata: languageName: node linkType: hard -"css-loader@npm:^6.7.3": - version: 6.7.3 - resolution: "css-loader@npm:6.7.3" +"css-loader@npm:^6.8.1": + version: 6.8.1 + resolution: "css-loader@npm:6.8.1" dependencies: icss-utils: ^5.1.0 - postcss: ^8.4.19 + postcss: ^8.4.21 postcss-modules-extract-imports: ^3.0.0 - postcss-modules-local-by-default: ^4.0.0 + postcss-modules-local-by-default: ^4.0.3 postcss-modules-scope: ^3.0.0 postcss-modules-values: ^4.0.0 postcss-value-parser: ^4.2.0 semver: ^7.3.8 peerDependencies: webpack: ^5.0.0 - checksum: 473cc32b6c837c2848e2051ad1ba331c1457449f47442e75a8c480d9891451434ada241f7e3de2347e57de17fcd84610b3bcfc4a9da41102cdaedd1e17902d31 + checksum: 7c1784247bdbe76dc5c55fb1ac84f1d4177a74c47259942c9cfdb7a8e6baef11967a0bc85ac285f26bd26d5059decb848af8154a03fdb4f4894f41212f45eef3 languageName: node linkType: hard @@ -5011,6 +5124,15 @@ __metadata: languageName: node linkType: hard +"devlop@npm:^1.0.0": + version: 1.1.0 + resolution: "devlop@npm:1.1.0" + dependencies: + dequal: ^2.0.0 + checksum: d2ff650bac0bb6ef08c48f3ba98640bb5fec5cce81e9957eb620408d1bab1204d382a45b785c6b3314dc867bb0684936b84c6867820da6db97cbb5d3c15dd185 + languageName: node + linkType: hard + "diff@npm:^5.0.0": version: 5.1.0 resolution: "diff@npm:5.1.0" @@ -5173,10 +5295,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.284": - version: 1.4.374 - resolution: "electron-to-chromium@npm:1.4.374" - checksum: baa53f70401a8fdd3dbf2396d5dfff2f0a8be12c6fefe362ed8608ff045db4e78322cc5b8acac0bd2d94de7850eba83509b3bfda38b4b67e575273b4c4824e5b +"electron-to-chromium@npm:^1.4.535": + version: 1.4.544 + resolution: "electron-to-chromium@npm:1.4.544" + checksum: 78e88e4c56fc4faaa9a405de5e0b51305531e9cdf2c71bcc9296c2c59fb68001472e5b924f8701c873bc855ab5174cf0340642712d7af05c1d8e92356529397e languageName: node linkType: hard @@ -5224,13 +5346,13 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.13.0": - version: 5.13.0 - resolution: "enhanced-resolve@npm:5.13.0" +"enhanced-resolve@npm:^5.15.0": + version: 5.15.0 + resolution: "enhanced-resolve@npm:5.15.0" dependencies: graceful-fs: ^4.2.4 tapable: ^2.2.0 - checksum: 76d6844c4393d76beed5b3ce6cf5a98dee3ad5c84a9887f49ccde1224e3b7af201dfbd5a57ebf2b49f623b74883df262d50ff480d3cc02fc2881fc58b84e1bbe + checksum: fbd8cdc9263be71cc737aa8a7d6c57b43d6aa38f6cc75dde6fcd3598a130cc465f979d2f4d01bb3bf475acb43817749c79f8eef9be048683602ca91ab52e4f11 languageName: node linkType: hard @@ -5437,10 +5559,10 @@ __metadata: languageName: node linkType: hard -"eta@npm:^2.0.1": - version: 2.0.1 - resolution: "eta@npm:2.0.1" - checksum: 595e18e762925561929a43d06493c8b46ef66dfa967dfcde7050acb016182d0bad87a19177384c93f04ffc87e918429688e07fc428c8691ff50cdfcb197f938a +"eta@npm:^2.2.0": + version: 2.2.0 + resolution: "eta@npm:2.2.0" + checksum: 6a09631481d4f26a9662a1eb736a65cc1cbc48e24935e6ff5d83a83b0cb509ea56d588d66d7c087d590601dc59bdabdac2356936b1b789d020eb0cf2d8304d54 languageName: node linkType: hard @@ -5592,6 +5714,15 @@ __metadata: languageName: node linkType: hard +"fault@npm:^2.0.0": + version: 2.0.1 + resolution: "fault@npm:2.0.1" + dependencies: + format: ^0.2.0 + checksum: c9b30f47d95769177130a9409976a899ed31eb598450fbad5b0d39f2f5f56d5f4a9ff9257e0bee8407cb0fc3ce37165657888c6aa6d78472e403893104329b72 + languageName: node + linkType: hard + "faye-websocket@npm:^0.11.3": version: 0.11.4 resolution: "faye-websocket@npm:0.11.4" @@ -5684,14 +5815,13 @@ __metadata: languageName: node linkType: hard -"find-cache-dir@npm:^3.3.2": - version: 3.3.2 - resolution: "find-cache-dir@npm:3.3.2" +"find-cache-dir@npm:^4.0.0": + version: 4.0.0 + resolution: "find-cache-dir@npm:4.0.0" dependencies: - commondir: ^1.0.1 - make-dir: ^3.0.2 - pkg-dir: ^4.1.0 - checksum: 1e61c2e64f5c0b1c535bd85939ae73b0e5773142713273818cc0b393ee3555fb0fd44e1a5b161b8b6c3e03e98c2fcc9c227d784850a13a90a8ab576869576817 + common-path-prefix: ^3.0.0 + pkg-dir: ^7.0.0 + checksum: 52a456a80deeb27daa3af6e06059b63bdb9cc4af4d845fc6d6229887e505ba913cd56000349caa60bc3aa59dacdb5b4c37903d4ba34c75102d83cab330b70d2f languageName: node linkType: hard @@ -5704,16 +5834,6 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^4.0.0": - version: 4.1.0 - resolution: "find-up@npm:4.1.0" - dependencies: - locate-path: ^5.0.0 - path-exists: ^4.0.0 - checksum: 4c172680e8f8c1f78839486e14a43ef82e9decd0e74145f40707cc42e7420506d5ec92d9a11c22bd2c48fb0c384ea05dd30e10dd152fefeec6f2f75282a8b844 - languageName: node - linkType: hard - "find-up@npm:^5.0.0": version: 5.0.0 resolution: "find-up@npm:5.0.0" @@ -5724,15 +5844,25 @@ __metadata: languageName: node linkType: hard -"flux@npm:^4.0.1": - version: 4.0.3 - resolution: "flux@npm:4.0.3" +"find-up@npm:^6.3.0": + version: 6.3.0 + resolution: "find-up@npm:6.3.0" + dependencies: + locate-path: ^7.1.0 + path-exists: ^5.0.0 + checksum: 9a21b7f9244a420e54c6df95b4f6fc3941efd3c3e5476f8274eb452f6a85706e7a6a90de71353ee4f091fcb4593271a6f92810a324ec542650398f928783c280 + languageName: node + linkType: hard + +"flux@npm:~4.0.1": + version: 4.0.4 + resolution: "flux@npm:4.0.4" dependencies: fbemitter: ^3.0.0 fbjs: ^3.0.1 peerDependencies: react: ^15.0.2 || ^16.0.0 || ^17.0.0 - checksum: 6b3f5150bcce481ce5bc09e54dbe4bf2a052f9fbc04c1de64f8d816adc4f90ad7955d9aed0022c7b6a2ed11b809ac40527bb50c2cd89c23d42f56694abe20748 + checksum: 8fa5c2f9322258de3e331f67c6f1078a7f91c4dec9dbe8a54c4b8a80eed19a4f91889028b768668af4a796e8f2ee75e461e1571b8615432a3920ae95cc4ff794 languageName: node linkType: hard @@ -5795,6 +5925,13 @@ __metadata: languageName: node linkType: hard +"format@npm:^0.2.0": + version: 0.2.2 + resolution: "format@npm:0.2.2" + checksum: 646a60e1336250d802509cf24fb801e43bd4a70a07510c816fa133aa42cdbc9c21e66e9cc0801bb183c5b031c9d68be62e7fbb6877756e52357850f92aa28799 + languageName: node + linkType: hard + "forwarded@npm:0.2.0": version: 0.2.0 resolution: "forwarded@npm:0.2.0" @@ -5802,10 +5939,10 @@ __metadata: languageName: node linkType: hard -"fraction.js@npm:^4.2.0": - version: 4.2.0 - resolution: "fraction.js@npm:4.2.0" - checksum: 8c76a6e21dedea87109d6171a0ac77afa14205794a565d71cb10d2925f629a3922da61bf45ea52dbc30bce4d8636dc0a27213a88cbd600eab047d82f9a3a94c5 +"fraction.js@npm:^4.3.6": + version: 4.3.6 + resolution: "fraction.js@npm:4.3.6" + checksum: e96ae77e64ebfd442d3a5a01a3f0637b0663fc2440bcf2841b3ad9341ba24c81fb2e3e7142e43ef7d088558c6b3f8609df135b201adc7a1c674aea6a71384162 languageName: node linkType: hard @@ -5816,7 +5953,7 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^11.1.0": +"fs-extra@npm:^11.1.1": version: 11.1.1 resolution: "fs-extra@npm:11.1.1" dependencies: @@ -6333,7 +6470,7 @@ __metadata: languageName: node linkType: hard -"html-minifier-terser@npm:^7.1.0": +"html-minifier-terser@npm:^7.2.0": version: 7.2.0 resolution: "html-minifier-terser@npm:7.2.0" dependencies: @@ -6350,10 +6487,10 @@ __metadata: languageName: node linkType: hard -"html-tags@npm:^3.2.0": - version: 3.2.0 - resolution: "html-tags@npm:3.2.0" - checksum: a0c9e96ac26c84adad9cc66d15d6711a17f60acda8d987218f1d4cbaacd52864939b230e635cce5a1179f3ddab2a12b9231355617dfbae7945fcfec5e96d2041 +"html-tags@npm:^3.3.1": + version: 3.3.1 + resolution: "html-tags@npm:3.3.1" + checksum: b4ef1d5a76b678e43cce46e3783d563607b1d550cab30b4f511211564574770aa8c658a400b100e588bc60b8234e59b35ff72c7851cc28f3b5403b13a2c6cbce languageName: node linkType: hard @@ -6364,9 +6501,9 @@ __metadata: languageName: node linkType: hard -"html-webpack-plugin@npm:^5.5.0": - version: 5.5.0 - resolution: "html-webpack-plugin@npm:5.5.0" +"html-webpack-plugin@npm:^5.5.3": + version: 5.5.3 + resolution: "html-webpack-plugin@npm:5.5.3" dependencies: "@types/html-minifier-terser": ^6.0.0 html-minifier-terser: ^6.0.2 @@ -6375,7 +6512,7 @@ __metadata: tapable: ^2.0.0 peerDependencies: webpack: ^5.20.0 - checksum: f3d84d0df71fe2f5bac533cc74dce41ab058558cdcc6ff767d166a2abf1cf6fb8491d54d60ddbb34e95c00394e379ba52e0468e0284d1d0cc6a42987056e8219 + checksum: ccf685195739c372ad641bbd0c9100a847904f34eedc7aff3ece7856cd6c78fd3746d2d615af1bb71e5727993fe711b89e9b744f033ed3fde646540bf5d5e954 languageName: node linkType: hard @@ -6906,6 +7043,13 @@ __metadata: languageName: node linkType: hard +"is-plain-object@npm:^5.0.0": + version: 5.0.0 + resolution: "is-plain-object@npm:5.0.0" + checksum: e32d27061eef62c0847d303125440a38660517e586f2f3db7c9d179ae5b6674ab0f469d519b2e25c147a1a3bc87156d0d5f4d8821e0ce4a9ee7fe1fcf11ce45c + languageName: node + linkType: hard + "is-reference@npm:^3.0.0": version: 3.0.1 resolution: "is-reference@npm:3.0.1" @@ -7031,16 +7175,25 @@ __metadata: languageName: node linkType: hard -"joi@npm:^17.7.0, joi@npm:^17.8.3": - version: 17.9.2 - resolution: "joi@npm:17.9.2" +"jiti@npm:^1.18.2": + version: 1.20.0 + resolution: "jiti@npm:1.20.0" + bin: + jiti: bin/jiti.js + checksum: 7924062b5675142e3e272a27735be84b7bfc0a0eb73217fc2dcafa034f37c4f7b4b9ffc07dd98bcff0f739a8811ce1544db205ae7e97b1c86f0df92c65ce3c72 + languageName: node + linkType: hard + +"joi@npm:^17.7.0, joi@npm:^17.9.2": + version: 17.11.0 + resolution: "joi@npm:17.11.0" dependencies: "@hapi/hoek": ^9.0.0 "@hapi/topo": ^5.0.0 "@sideway/address": ^4.1.3 "@sideway/formula": ^3.0.1 "@sideway/pinpoint": ^2.0.0 - checksum: 8c3709849293411c524e5a679dba7b42598a29a663478941767b8d5b06288611dece58803c468a2c7320cc2429a3e71e3d94337fe47aefcf6c22174dbd90b601 + checksum: 3a4e9ecba345cdafe585e7ed8270a44b39718e11dff3749aa27e0001a63d578b75100c062be28e6f48f960b594864034e7a13833f33fbd7ad56d5ce6b617f9bf languageName: node linkType: hard @@ -7120,7 +7273,7 @@ __metadata: languageName: node linkType: hard -"json5@npm:^2.1.2, json5@npm:^2.2.2": +"json5@npm:^2.1.2, json5@npm:^2.2.3": version: 2.2.3 resolution: "json5@npm:2.2.3" bin: @@ -7172,7 +7325,7 @@ __metadata: languageName: node linkType: hard -"klona@npm:^2.0.4, klona@npm:^2.0.6": +"klona@npm:^2.0.4": version: 2.0.6 resolution: "klona@npm:2.0.6" checksum: ac9ee3732e42b96feb67faae4d27cf49494e8a3bf3fa7115ce242fe04786788e0aff4741a07a45a2462e2079aa983d73d38519c85d65b70ef11447bbc3c58ce7 @@ -7254,15 +7407,6 @@ __metadata: languageName: node linkType: hard -"locate-path@npm:^5.0.0": - version: 5.0.0 - resolution: "locate-path@npm:5.0.0" - dependencies: - p-locate: ^4.1.0 - checksum: 83e51725e67517287d73e1ded92b28602e3ae5580b301fe54bfb76c0c723e3f285b19252e375712316774cf52006cb236aed5704692c32db0d5d089b69696e30 - languageName: node - linkType: hard - "locate-path@npm:^6.0.0": version: 6.0.0 resolution: "locate-path@npm:6.0.0" @@ -7272,6 +7416,15 @@ __metadata: languageName: node linkType: hard +"locate-path@npm:^7.1.0": + version: 7.2.0 + resolution: "locate-path@npm:7.2.0" + dependencies: + p-locate: ^6.0.0 + checksum: c1b653bdf29beaecb3d307dfb7c44d98a2a98a02ebe353c9ad055d1ac45d6ed4e1142563d222df9b9efebc2bcb7d4c792b507fad9e7150a04c29530b7db570f8 + languageName: node + linkType: hard + "lodash.curry@npm:^4.0.1": version: 4.1.1 resolution: "lodash.curry@npm:4.1.1" @@ -7286,6 +7439,20 @@ __metadata: languageName: node linkType: hard +"lodash.escape@npm:^4.0.1": + version: 4.0.1 + resolution: "lodash.escape@npm:4.0.1" + checksum: fcb54f457497256964d619d5cccbd80a961916fca60df3fe0fa3e7f052715c2944c0ed5aefb4f9e047d127d44aa2d55555f3350cb42c6549e9e293fb30b41e7f + languageName: node + linkType: hard + +"lodash.flatten@npm:^4.4.0": + version: 4.4.0 + resolution: "lodash.flatten@npm:4.4.0" + checksum: 0ac34a393d4b795d4b7421153d27c13ae67e08786c9cbb60ff5b732210d46f833598eee3fb3844bb10070e8488efe390ea53bb567377e0cb47e9e630bf0811cb + languageName: node + linkType: hard + "lodash.flow@npm:^3.3.0": version: 3.5.0 resolution: "lodash.flow@npm:3.5.0" @@ -7293,6 +7460,13 @@ __metadata: languageName: node linkType: hard +"lodash.invokemap@npm:^4.6.0": + version: 4.6.0 + resolution: "lodash.invokemap@npm:4.6.0" + checksum: 646ceebbefbcb6da301f8c2868254680fd0bcdc6ada470495d9ae49c9c32938829c1b38a38c95d0258409a9655f85db404b16e648381c7450b7ed3d9c52d8808 + languageName: node + linkType: hard + "lodash.memoize@npm:^4.1.2": version: 4.1.2 resolution: "lodash.memoize@npm:4.1.2" @@ -7300,6 +7474,13 @@ __metadata: languageName: node linkType: hard +"lodash.pullall@npm:^4.2.0": + version: 4.2.0 + resolution: "lodash.pullall@npm:4.2.0" + checksum: 7a5fbaedf186ec197ce1e0b9ba1d88a89773ebaf6a8291c7d273838cac59cb3b339cf36ef00e94172862ee84d2304c38face161846f08f5581d0553dcbdcd090 + languageName: node + linkType: hard + "lodash.uniq@npm:^4.5.0": version: 4.5.0 resolution: "lodash.uniq@npm:4.5.0" @@ -7307,6 +7488,13 @@ __metadata: languageName: node linkType: hard +"lodash.uniqby@npm:^4.7.0": + version: 4.7.0 + resolution: "lodash.uniqby@npm:4.7.0" + checksum: 659264545a95726d1493123345aad8cbf56e17810fa9a0b029852c6d42bc80517696af09d99b23bef1845d10d95e01b8b4a1da578f22aeba7a30d3e0022a4938 + languageName: node + linkType: hard + "lodash@npm:^4.17.20, lodash@npm:^4.17.21": version: 4.17.21 resolution: "lodash@npm:4.17.21" @@ -7380,15 +7568,6 @@ __metadata: languageName: node linkType: hard -"make-dir@npm:^3.0.2": - version: 3.1.0 - resolution: "make-dir@npm:3.1.0" - dependencies: - semver: ^6.0.0 - checksum: 484200020ab5a1fdf12f393fe5f385fc8e4378824c940fba1729dcd198ae4ff24867bc7a5646331e50cead8abff5d9270c456314386e629acec6dff4b8016b78 - languageName: node - linkType: hard - "make-fetch-happen@npm:^10.0.3": version: 10.2.1 resolution: "make-fetch-happen@npm:10.2.1" @@ -7485,6 +7664,40 @@ __metadata: languageName: node linkType: hard +"mdast-util-from-markdown@npm:^2.0.0": + version: 2.0.0 + resolution: "mdast-util-from-markdown@npm:2.0.0" + dependencies: + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + mdast-util-to-string: ^4.0.0 + micromark: ^4.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-decode-string: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + unist-util-stringify-position: ^4.0.0 + checksum: 4e8d8a46b4b588486c41b80c39da333a91593bc8d60cd7421c6cd3c22003b8e5a62478292fb7bc97b9255b6301a2250cca32340ef43c309156e215453c5b92be + languageName: node + linkType: hard + +"mdast-util-frontmatter@npm:^2.0.0": + version: 2.0.1 + resolution: "mdast-util-frontmatter@npm:2.0.1" + dependencies: + "@types/mdast": ^4.0.0 + devlop: ^1.0.0 + escape-string-regexp: ^5.0.0 + mdast-util-from-markdown: ^2.0.0 + mdast-util-to-markdown: ^2.0.0 + micromark-extension-frontmatter: ^2.0.0 + checksum: 86a7c8d9eb183be2621d6d9134b9d33df2a3647e3255f68a9796e2425e25643ffae00a501e36c57d9c10973087b94aa5a2ffd865d33cdd274cc9b88cd2d90a2e + languageName: node + linkType: hard + "mdast-util-gfm-autolink-literal@npm:^1.0.0": version: 1.0.3 resolution: "mdast-util-gfm-autolink-literal@npm:1.0.3" @@ -7624,6 +7837,16 @@ __metadata: languageName: node linkType: hard +"mdast-util-phrasing@npm:^4.0.0": + version: 4.0.0 + resolution: "mdast-util-phrasing@npm:4.0.0" + dependencies: + "@types/mdast": ^4.0.0 + unist-util-is: ^6.0.0 + checksum: 95d5d8e18d5ea6dbfe2ee4ed1045961372efae9077e5c98e10bfef7025ee3fd9449f9a82840068ff50aa98fa43af0a0a14898ae10b5e46e96edde01e2797df34 + languageName: node + linkType: hard + "mdast-util-to-hast@npm:^12.1.0": version: 12.3.0 resolution: "mdast-util-to-hast@npm:12.3.0" @@ -7656,7 +7879,23 @@ __metadata: languageName: node linkType: hard -"mdast-util-to-string@npm:^3.0.0, mdast-util-to-string@npm:^3.1.0": +"mdast-util-to-markdown@npm:^2.0.0": + version: 2.1.0 + resolution: "mdast-util-to-markdown@npm:2.1.0" + dependencies: + "@types/mdast": ^4.0.0 + "@types/unist": ^3.0.0 + longest-streak: ^3.0.0 + mdast-util-phrasing: ^4.0.0 + mdast-util-to-string: ^4.0.0 + micromark-util-decode-string: ^2.0.0 + unist-util-visit: ^5.0.0 + zwitch: ^2.0.0 + checksum: 3a2cf3957e23b34e2e092e6e76ae72ee0b8745955bd811baba6814cf3a3d916c3fd52264b4b58f3bb3d512a428f84a1e998b6fc7e28434e388a9ae8fb6a9c173 + languageName: node + linkType: hard + +"mdast-util-to-string@npm:^3.0.0, mdast-util-to-string@npm:^3.1.0, mdast-util-to-string@npm:^3.2.0": version: 3.2.0 resolution: "mdast-util-to-string@npm:3.2.0" dependencies: @@ -7665,6 +7904,15 @@ __metadata: languageName: node linkType: hard +"mdast-util-to-string@npm:^4.0.0": + version: 4.0.0 + resolution: "mdast-util-to-string@npm:4.0.0" + dependencies: + "@types/mdast": ^4.0.0 + checksum: 35489fb5710d58cbc2d6c8b6547df161a3f81e0f28f320dfb3548a9393555daf07c310c0c497708e67ed4dfea4a06e5655799e7d631ca91420c288b4525d6c29 + languageName: node + linkType: hard + "mdn-data@npm:2.0.14": version: 2.0.14 resolution: "mdn-data@npm:2.0.14" @@ -7740,6 +7988,30 @@ __metadata: languageName: node linkType: hard +"micromark-core-commonmark@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-core-commonmark@npm:2.0.0" + dependencies: + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + micromark-factory-destination: ^2.0.0 + micromark-factory-label: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-factory-title: ^2.0.0 + micromark-factory-whitespace: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-classify-character: ^2.0.0 + micromark-util-html-tag-name: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-resolve-all: ^2.0.0 + micromark-util-subtokenize: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 9c12fb580cf4ce71f60872043bd2794efe129f44d7b2b73afa155bbc0a66b7bc35655ba8cef438a6bd068441837ed3b6dc6ad7e5a18f815462c1750793e03a42 + languageName: node + linkType: hard + "micromark-extension-directive@npm:^2.0.0": version: 2.2.0 resolution: "micromark-extension-directive@npm:2.2.0" @@ -7755,6 +8027,18 @@ __metadata: languageName: node linkType: hard +"micromark-extension-frontmatter@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-extension-frontmatter@npm:2.0.0" + dependencies: + fault: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: f68032df38c00ae47de15b63bcd72515bfcce39de4a9262a3a1ac9c5990f253f8e41bdc65fd17ec4bb3d144c32529ce0829571331e4901a9a413f1a53785d1e8 + languageName: node + linkType: hard + "micromark-extension-gfm-autolink-literal@npm:^1.0.0": version: 1.0.3 resolution: "micromark-extension-gfm-autolink-literal@npm:1.0.3" @@ -7933,6 +8217,17 @@ __metadata: languageName: node linkType: hard +"micromark-factory-destination@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-destination@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: d36e65ed1c072ff4148b016783148ba7c68a078991154625723e24bda3945160268fb91079fb28618e1613c2b6e70390a8ddc544c45410288aa27b413593071a + languageName: node + linkType: hard + "micromark-factory-label@npm:^1.0.0": version: 1.0.2 resolution: "micromark-factory-label@npm:1.0.2" @@ -7945,6 +8240,18 @@ __metadata: languageName: node linkType: hard +"micromark-factory-label@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-label@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: c021dbd0ed367610d35f2bae21209bc804d1a6d1286ffce458fd6a717f4d7fe581a7cba7d5c2d7a63757c44eb927c80d6a571d6ea7969fae1b48ab6461d109c4 + languageName: node + linkType: hard + "micromark-factory-mdx-expression@npm:^1.0.0": version: 1.0.7 resolution: "micromark-factory-mdx-expression@npm:1.0.7" @@ -7971,6 +8278,16 @@ __metadata: languageName: node linkType: hard +"micromark-factory-space@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-space@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 4ffdcdc2f759887bbb356500cb460b3915ecddcb5d85c3618d7df68ad05d13ed02b1153ee1845677b7d8126df8f388288b84fcf0d943bd9c92bcc71cd7222e37 + languageName: node + linkType: hard + "micromark-factory-title@npm:^1.0.0": version: 1.0.2 resolution: "micromark-factory-title@npm:1.0.2" @@ -7984,6 +8301,18 @@ __metadata: languageName: node linkType: hard +"micromark-factory-title@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-title@npm:2.0.0" + dependencies: + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 39e1ac23af3554e6e652e56065579bc7faf21ade7b8704b29c175871b4152b7109b790bb3cae0f7e088381139c6bac9553b8400772c3d322e4fa635f813a3578 + languageName: node + linkType: hard + "micromark-factory-whitespace@npm:^1.0.0": version: 1.0.0 resolution: "micromark-factory-whitespace@npm:1.0.0" @@ -7996,6 +8325,18 @@ __metadata: languageName: node linkType: hard +"micromark-factory-whitespace@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-factory-whitespace@npm:2.0.0" + dependencies: + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 9587c2546d1a58b4d5472b42adf05463f6212d0449455285662d63cd8eaed89c6b159ac82713fcee5f9dd88628c24307d9533cccd8971a2f3f4d48702f8f850a + languageName: node + linkType: hard + "micromark-util-character@npm:^1.0.0, micromark-util-character@npm:^1.1.0": version: 1.1.0 resolution: "micromark-util-character@npm:1.1.0" @@ -8006,6 +8347,16 @@ __metadata: languageName: node linkType: hard +"micromark-util-character@npm:^2.0.0": + version: 2.0.1 + resolution: "micromark-util-character@npm:2.0.1" + dependencies: + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 318d6e16fdcbe9d89e18b8e7796568d986abbb10a9f3037b7ac9b92a236bcc962f3cd380e26a7c49df40fd1d9ca33eb546268956345b662f4c4ca4962c7695f2 + languageName: node + linkType: hard + "micromark-util-chunked@npm:^1.0.0": version: 1.0.0 resolution: "micromark-util-chunked@npm:1.0.0" @@ -8015,6 +8366,15 @@ __metadata: languageName: node linkType: hard +"micromark-util-chunked@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-chunked@npm:2.0.0" + dependencies: + micromark-util-symbol: ^2.0.0 + checksum: 324f95cccdae061332a8241936eaba6ef0782a1e355bac5c607ad2564fd3744929be7dc81651315a2921535747a33243e6a5606bcb64b7a56d49b6d74ea1a3d4 + languageName: node + linkType: hard + "micromark-util-classify-character@npm:^1.0.0": version: 1.0.0 resolution: "micromark-util-classify-character@npm:1.0.0" @@ -8026,6 +8386,17 @@ __metadata: languageName: node linkType: hard +"micromark-util-classify-character@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-classify-character@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 086e52904deffebb793fb1c08c94aabb8901f76958142dfc3a6282890ebaa983b285e69bd602b9d507f1b758ed38e75a994d2ad9fbbefa7de2584f67a16af405 + languageName: node + linkType: hard + "micromark-util-combine-extensions@npm:^1.0.0": version: 1.0.0 resolution: "micromark-util-combine-extensions@npm:1.0.0" @@ -8036,6 +8407,16 @@ __metadata: languageName: node linkType: hard +"micromark-util-combine-extensions@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-combine-extensions@npm:2.0.0" + dependencies: + micromark-util-chunked: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 107c47700343f365b4ed81551e18bc3458b573c500e56ac052b2490bd548adc475216e41d2271633a8867fac66fc22ba3e0a2d74a31ed79b9870ca947eb4e3ba + languageName: node + linkType: hard + "micromark-util-decode-numeric-character-reference@npm:^1.0.0": version: 1.0.0 resolution: "micromark-util-decode-numeric-character-reference@npm:1.0.0" @@ -8045,6 +8426,15 @@ __metadata: languageName: node linkType: hard +"micromark-util-decode-numeric-character-reference@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-decode-numeric-character-reference@npm:2.0.0" + dependencies: + micromark-util-symbol: ^2.0.0 + checksum: 705715a2dd6f10d85c69371b4176a0b2fec5811a14f7d26f66f358ac5adebb12975f79597b1a1a184a6dcf6799319f7cf8eb91398e47c1faa2cab2c84f155b78 + languageName: node + linkType: hard + "micromark-util-decode-string@npm:^1.0.0": version: 1.0.2 resolution: "micromark-util-decode-string@npm:1.0.2" @@ -8057,6 +8447,18 @@ __metadata: languageName: node linkType: hard +"micromark-util-decode-string@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-decode-string@npm:2.0.0" + dependencies: + decode-named-character-reference: ^1.0.0 + micromark-util-character: ^2.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-symbol: ^2.0.0 + checksum: a75daf32a4a6b549e9f19b4d833ebfeb09a32a9a1f9ce50f35dec6b6a3e4f9f121f49024ba7f9c91c55ebe792f7c7a332fc9604795181b6a612637df0df5b959 + languageName: node + linkType: hard + "micromark-util-encode@npm:^1.0.0": version: 1.0.1 resolution: "micromark-util-encode@npm:1.0.1" @@ -8064,6 +8466,13 @@ __metadata: languageName: node linkType: hard +"micromark-util-encode@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-encode@npm:2.0.0" + checksum: 853a3f33fce72aaf4ffa60b7f2b6fcfca40b270b3466e1b96561b02185d2bd8c01dd7948bc31a24ac014f4cc854e545ca9a8e9cf7ea46262f9d24c9e88551c66 + languageName: node + linkType: hard + "micromark-util-events-to-acorn@npm:^1.0.0": version: 1.2.1 resolution: "micromark-util-events-to-acorn@npm:1.2.1" @@ -8086,6 +8495,13 @@ __metadata: languageName: node linkType: hard +"micromark-util-html-tag-name@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-html-tag-name@npm:2.0.0" + checksum: d786d4486f93eb0ac5b628779809ca97c5dc60f3c9fc03eb565809831db181cf8cb7f05f9ac76852f3eb35461af0f89fa407b46f3a03f4f97a96754d8dc540d8 + languageName: node + linkType: hard + "micromark-util-normalize-identifier@npm:^1.0.0": version: 1.0.0 resolution: "micromark-util-normalize-identifier@npm:1.0.0" @@ -8095,6 +8511,15 @@ __metadata: languageName: node linkType: hard +"micromark-util-normalize-identifier@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-normalize-identifier@npm:2.0.0" + dependencies: + micromark-util-symbol: ^2.0.0 + checksum: b36da2d3fd102053dadd953ce5c558328df12a63a8ac0e5aad13d4dda8e43b6a5d4a661baafe0a1cd8a260bead4b4a8e6e0e74193dd651e8484225bd4f4e68aa + languageName: node + linkType: hard + "micromark-util-resolve-all@npm:^1.0.0": version: 1.0.0 resolution: "micromark-util-resolve-all@npm:1.0.0" @@ -8104,6 +8529,15 @@ __metadata: languageName: node linkType: hard +"micromark-util-resolve-all@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-resolve-all@npm:2.0.0" + dependencies: + micromark-util-types: ^2.0.0 + checksum: 31fe703b85572cb3f598ebe32750e59516925c7ff1f66cfe6afaebe0771a395a9eaa770787f2523d3c46082ea80e6c14f83643303740b3d650af7c96ebd30ccc + languageName: node + linkType: hard + "micromark-util-sanitize-uri@npm:^1.0.0, micromark-util-sanitize-uri@npm:^1.1.0": version: 1.1.0 resolution: "micromark-util-sanitize-uri@npm:1.1.0" @@ -8115,6 +8549,17 @@ __metadata: languageName: node linkType: hard +"micromark-util-sanitize-uri@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-sanitize-uri@npm:2.0.0" + dependencies: + micromark-util-character: ^2.0.0 + micromark-util-encode: ^2.0.0 + micromark-util-symbol: ^2.0.0 + checksum: ea4c28bbffcf2430e9aff2d18554296789a8b0a1f54ac24020d1dde76624a7f93e8f2a83e88cd5a846b6d2c4287b71b1142d1b89fa7f1b0363a9b33711a141fe + languageName: node + linkType: hard + "micromark-util-subtokenize@npm:^1.0.0": version: 1.0.2 resolution: "micromark-util-subtokenize@npm:1.0.2" @@ -8127,6 +8572,18 @@ __metadata: languageName: node linkType: hard +"micromark-util-subtokenize@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-subtokenize@npm:2.0.0" + dependencies: + devlop: ^1.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: 77d9c7d59c05a20468d49ce2a3640e9cb268c083ccad02322f26c84e1094c25b44f4b8139ef0a247ca11a4fef7620c5bf82fbffd98acdb2989e79cbe7bd8f1db + languageName: node + linkType: hard + "micromark-util-symbol@npm:^1.0.0, micromark-util-symbol@npm:^1.0.1": version: 1.0.1 resolution: "micromark-util-symbol@npm:1.0.1" @@ -8134,6 +8591,13 @@ __metadata: languageName: node linkType: hard +"micromark-util-symbol@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-symbol@npm:2.0.0" + checksum: fa4a05bff575d9fbf0ad96a1013003e3bb6087ed6b34b609a141b6c0d2137b57df594aca409a95f4c5fda199f227b56a7d8b1f82cea0768df161d8a3a3660764 + languageName: node + linkType: hard + "micromark-util-types@npm:^1.0.0, micromark-util-types@npm:^1.0.1": version: 1.0.2 resolution: "micromark-util-types@npm:1.0.2" @@ -8141,6 +8605,13 @@ __metadata: languageName: node linkType: hard +"micromark-util-types@npm:^2.0.0": + version: 2.0.0 + resolution: "micromark-util-types@npm:2.0.0" + checksum: 819fef3ab5770c37893d2a60381fb2694396c8d22803b6e103c830c3a1bc1490363c2b0470bb2acaaddad776dfbc2fc1fcfde39cb63c4f54d95121611672e3d0 + languageName: node + linkType: hard + "micromark@npm:^3.0.0": version: 3.1.0 resolution: "micromark@npm:3.1.0" @@ -8166,6 +8637,31 @@ __metadata: languageName: node linkType: hard +"micromark@npm:^4.0.0": + version: 4.0.0 + resolution: "micromark@npm:4.0.0" + dependencies: + "@types/debug": ^4.0.0 + debug: ^4.0.0 + decode-named-character-reference: ^1.0.0 + devlop: ^1.0.0 + micromark-core-commonmark: ^2.0.0 + micromark-factory-space: ^2.0.0 + micromark-util-character: ^2.0.0 + micromark-util-chunked: ^2.0.0 + micromark-util-combine-extensions: ^2.0.0 + micromark-util-decode-numeric-character-reference: ^2.0.0 + micromark-util-encode: ^2.0.0 + micromark-util-normalize-identifier: ^2.0.0 + micromark-util-resolve-all: ^2.0.0 + micromark-util-sanitize-uri: ^2.0.0 + micromark-util-subtokenize: ^2.0.0 + micromark-util-symbol: ^2.0.0 + micromark-util-types: ^2.0.0 + checksum: b84ab5ab1a0b28c063c52e9c2c9d7d44b954507235c10c9492d66e0b38f7de24bf298f914a1fbdf109f2a57a88cf0412de217c84cfac5fd60e3e42a74dbac085 + languageName: node + linkType: hard + "micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": version: 4.0.5 resolution: "micromatch@npm:4.0.5" @@ -8238,14 +8734,14 @@ __metadata: languageName: node linkType: hard -"mini-css-extract-plugin@npm:^2.7.3": - version: 2.7.5 - resolution: "mini-css-extract-plugin@npm:2.7.5" +"mini-css-extract-plugin@npm:^2.7.6": + version: 2.7.6 + resolution: "mini-css-extract-plugin@npm:2.7.6" dependencies: schema-utils: ^4.0.0 peerDependencies: webpack: ^5.0.0 - checksum: afc37cdfb765e8826a1babbab3cd8a99ffc4eaeabb6c013a6b3c80801e44ebc37d930b98c6f66168bb8cd545fcb2e8fc2630d72b4501a1bb8add1547c2534a53 + checksum: be6f7cefc6275168eb0a6b8fe977083a18c743c9612c9f00e6c1a62c3393ca7960e93fba1a7ebb09b75f36a0204ad087d772c1ef574bc29c90c0e8175a3c0b83 languageName: node linkType: hard @@ -8499,10 +8995,10 @@ __metadata: languageName: node linkType: hard -"node-releases@npm:^2.0.8": - version: 2.0.10 - resolution: "node-releases@npm:2.0.10" - checksum: d784ecde25696a15d449c4433077f5cce620ed30a1656c4abf31282bfc691a70d9618bae6868d247a67914d1be5cc4fde22f65a05f4398cdfb92e0fc83cadfbc +"node-releases@npm:^2.0.13": + version: 2.0.13 + resolution: "node-releases@npm:2.0.13" + checksum: 17ec8f315dba62710cae71a8dad3cd0288ba943d2ece43504b3b1aa8625bf138637798ab470b1d9035b0545996f63000a8a926e0f6d35d0996424f8b6d36dda3 languageName: node linkType: hard @@ -8683,7 +9179,7 @@ __metadata: languageName: node linkType: hard -"p-limit@npm:^2.0.0, p-limit@npm:^2.2.0": +"p-limit@npm:^2.0.0": version: 2.3.0 resolution: "p-limit@npm:2.3.0" dependencies: @@ -8701,6 +9197,15 @@ __metadata: languageName: node linkType: hard +"p-limit@npm:^4.0.0": + version: 4.0.0 + resolution: "p-limit@npm:4.0.0" + dependencies: + yocto-queue: ^1.0.0 + checksum: 01d9d70695187788f984226e16c903475ec6a947ee7b21948d6f597bed788e3112cc7ec2e171c1d37125057a5f45f3da21d8653e04a3a793589e12e9e80e756b + languageName: node + linkType: hard + "p-locate@npm:^3.0.0": version: 3.0.0 resolution: "p-locate@npm:3.0.0" @@ -8710,15 +9215,6 @@ __metadata: languageName: node linkType: hard -"p-locate@npm:^4.1.0": - version: 4.1.0 - resolution: "p-locate@npm:4.1.0" - dependencies: - p-limit: ^2.2.0 - checksum: 513bd14a455f5da4ebfcb819ef706c54adb09097703de6aeaa5d26fe5ea16df92b48d1ac45e01e3944ce1e6aa2a66f7f8894742b8c9d6e276e16cd2049a2b870 - languageName: node - linkType: hard - "p-locate@npm:^5.0.0": version: 5.0.0 resolution: "p-locate@npm:5.0.0" @@ -8728,6 +9224,15 @@ __metadata: languageName: node linkType: hard +"p-locate@npm:^6.0.0": + version: 6.0.0 + resolution: "p-locate@npm:6.0.0" + dependencies: + p-limit: ^4.0.0 + checksum: 2bfe5234efa5e7a4e74b30a5479a193fdd9236f8f6b4d2f3f69e3d286d9a7d7ab0c118a2a50142efcf4e41625def635bd9332d6cbf9cc65d85eb0718c579ab38 + languageName: node + linkType: hard + "p-map@npm:^4.0.0": version: 4.0.0 resolution: "p-map@npm:4.0.0" @@ -8801,7 +9306,7 @@ __metadata: languageName: node linkType: hard -"parse-json@npm:^5.0.0": +"parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" dependencies: @@ -8877,6 +9382,13 @@ __metadata: languageName: node linkType: hard +"path-exists@npm:^5.0.0": + version: 5.0.0 + resolution: "path-exists@npm:5.0.0" + checksum: 8ca842868cab09423994596eb2c5ec2a971c17d1a3cb36dbf060592c730c725cd524b9067d7d2a1e031fef9ba7bd2ac6dc5ec9fb92aa693265f7be3987045254 + languageName: node + linkType: hard + "path-is-absolute@npm:^1.0.0": version: 1.0.1 resolution: "path-is-absolute@npm:1.0.1" @@ -8960,12 +9472,12 @@ __metadata: languageName: node linkType: hard -"pkg-dir@npm:^4.1.0": - version: 4.2.0 - resolution: "pkg-dir@npm:4.2.0" +"pkg-dir@npm:^7.0.0": + version: 7.0.0 + resolution: "pkg-dir@npm:7.0.0" dependencies: - find-up: ^4.0.0 - checksum: 9863e3f35132bf99ae1636d31ff1e1e3501251d480336edb1c211133c8d58906bed80f154a1d723652df1fda91e01c7442c2eeaf9dc83157c7ae89087e43c8d6 + find-up: ^6.3.0 + checksum: 94298b20a446bfbbd66604474de8a0cdd3b8d251225170970f15d9646f633e056c80520dd5b4c1d1050c9fed8f6a9e5054b141c93806439452efe72e57562c03 languageName: node linkType: hard @@ -9063,25 +9575,17 @@ __metadata: languageName: node linkType: hard -"postcss-loader@npm:^7.0.2": - version: 7.2.4 - resolution: "postcss-loader@npm:7.2.4" +"postcss-loader@npm:^7.3.3": + version: 7.3.3 + resolution: "postcss-loader@npm:7.3.3" dependencies: - cosmiconfig: ^8.1.3 - cosmiconfig-typescript-loader: ^4.3.0 - klona: ^2.0.6 + cosmiconfig: ^8.2.0 + jiti: ^1.18.2 semver: ^7.3.8 peerDependencies: postcss: ^7.0.0 || ^8.0.1 - ts-node: ">=10" - typescript: ">=4" webpack: ^5.0.0 - peerDependenciesMeta: - ts-node: - optional: true - typescript: - optional: true - checksum: d75de64f6629a2d76b1c1e9ad5022cae9b589472d8d091e21105d93a0f09a4c80f08fe10323d41ddf2fbda157910a03df3c538ce8fccf974b179d0762b408fa3 + checksum: c724044d6ae56334535c26bb4efc9c151431d44d60bc8300157c760747281a242757d8dab32db72738434531175b38a408cb0b270bb96207c07584dcfcd899ff languageName: node linkType: hard @@ -9180,16 +9684,16 @@ __metadata: languageName: node linkType: hard -"postcss-modules-local-by-default@npm:^4.0.0": - version: 4.0.0 - resolution: "postcss-modules-local-by-default@npm:4.0.0" +"postcss-modules-local-by-default@npm:^4.0.3": + version: 4.0.3 + resolution: "postcss-modules-local-by-default@npm:4.0.3" dependencies: icss-utils: ^5.0.0 postcss-selector-parser: ^6.0.2 postcss-value-parser: ^4.1.0 peerDependencies: postcss: ^8.1.0 - checksum: 6cf570badc7bc26c265e073f3ff9596b69bb954bc6ac9c5c1b8cba2995b80834226b60e0a3cbb87d5f399dbb52e6466bba8aa1d244f6218f99d834aec431a69d + checksum: 2f8083687f3d6067885f8863dd32dbbb4f779cfcc7e52c17abede9311d84faf6d3ed8760e7c54c6380281732ae1f78e5e56a28baf3c271b33f450a11c9e30485 languageName: node linkType: hard @@ -9370,7 +9874,7 @@ __metadata: languageName: node linkType: hard -"postcss-sort-media-queries@npm:^4.3.0": +"postcss-sort-media-queries@npm:^4.4.1": version: 4.4.1 resolution: "postcss-sort-media-queries@npm:4.4.1" dependencies: @@ -9420,7 +9924,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.4.17, postcss@npm:^8.4.19, postcss@npm:^8.4.21": +"postcss@npm:^8.4.17, postcss@npm:^8.4.21, postcss@npm:^8.4.26": version: 8.4.31 resolution: "postcss@npm:8.4.31" dependencies: @@ -9466,6 +9970,18 @@ __metadata: languageName: node linkType: hard +"prism-react-renderer@npm:^2.1.0": + version: 2.1.0 + resolution: "prism-react-renderer@npm:2.1.0" + dependencies: + "@types/prismjs": ^1.26.0 + clsx: ^1.2.1 + peerDependencies: + react: ">=16.0.0" + checksum: 61b4eb22bdbf01005a0d7ec2a24a27b69e28f124a1fbbfc2adb4d7d41a7929ea94d5ce506a361dd5a230728402f02595d521d9a5286d74ec9b34be0896c513a5 + languageName: node + linkType: hard + "prismjs@npm:^1.29.0": version: 1.29.0 resolution: "prismjs@npm:1.29.0" @@ -9662,7 +10178,7 @@ __metadata: languageName: node linkType: hard -"react-base16-styling@npm:^0.6.0": +"react-base16-styling@npm:~0.6.0": version: 0.6.0 resolution: "react-base16-styling@npm:0.6.0" dependencies: @@ -9706,16 +10222,15 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^17.0.2": - version: 17.0.2 - resolution: "react-dom@npm:17.0.2" +"react-dom@npm:^18.0.0": + version: 18.2.0 + resolution: "react-dom@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - scheduler: ^0.20.2 + scheduler: ^0.23.0 peerDependencies: - react: 17.0.2 - checksum: 1c1eaa3bca7c7228d24b70932e3d7c99e70d1d04e13bb0843bbf321582bc25d7961d6b8a6978a58a598af2af496d1cedcfb1bf65f6b0960a0a8161cb8dab743c + react: ^18.2.0 + checksum: 7d323310bea3a91be2965f9468d552f201b1c27891e45ddc2d6b8f717680c95a75ae0bc1e3f5cf41472446a2589a75aed4483aee8169287909fcd59ad149e8cc languageName: node linkType: hard @@ -9756,22 +10271,7 @@ __metadata: languageName: node linkType: hard -"react-json-view@npm:^1.21.3": - version: 1.21.3 - resolution: "react-json-view@npm:1.21.3" - dependencies: - flux: ^4.0.1 - react-base16-styling: ^0.6.0 - react-lifecycles-compat: ^3.0.4 - react-textarea-autosize: ^8.3.2 - peerDependencies: - react: ^17.0.0 || ^16.3.0 || ^15.5.4 - react-dom: ^17.0.0 || ^16.3.0 || ^15.5.4 - checksum: 5718bcd9210ad5b06eb9469cf8b9b44be9498845a7702e621343618e8251f26357e6e1c865532cf170db6165df1cb30202787e057309d8848c220bc600ec0d1a - languageName: node - linkType: hard - -"react-lifecycles-compat@npm:^3.0.4": +"react-lifecycles-compat@npm:~3.0.4": version: 3.0.4 resolution: "react-lifecycles-compat@npm:3.0.4" checksum: a904b0fc0a8eeb15a148c9feb7bc17cec7ef96e71188280061fc340043fd6d8ee3ff233381f0e8f95c1cf926210b2c4a31f38182c8f35ac55057e453d6df204f @@ -9838,26 +10338,25 @@ __metadata: languageName: node linkType: hard -"react-textarea-autosize@npm:^8.3.2": - version: 8.4.0 - resolution: "react-textarea-autosize@npm:8.4.0" +"react-textarea-autosize@npm:~8.3.2": + version: 8.3.4 + resolution: "react-textarea-autosize@npm:8.3.4" dependencies: "@babel/runtime": ^7.10.2 use-composed-ref: ^1.3.0 use-latest: ^1.2.1 peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 055fb51b74e1ab6b286490cfcd8ed77a760f6fc90706053b5dfcb138199d02c56289a1060a1daf9f3ae37ffd66f73e9553f026d0fad446bc2243b713acf48e05 + checksum: 87360d4392276d4e87511a73be9b0634b8bcce8f4f648cf659334d993f25ad3d4062f468f1e1944fc614123acae4299580aad00b760c6a96cec190e076f847f5 languageName: node linkType: hard -"react@npm:^17.0.2": - version: 17.0.2 - resolution: "react@npm:17.0.2" +"react@npm:^18.0.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: b254cc17ce3011788330f7bbf383ab653c6848902d7936a87b09d835d091e3f295f7e9dd1597c6daac5dc80f90e778c8230218ba8ad599f74adcc11e33b9d61b + checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b languageName: node linkType: hard @@ -9937,33 +10436,33 @@ __metadata: languageName: node linkType: hard -"regenerator-runtime@npm:^0.13.11": - version: 0.13.11 - resolution: "regenerator-runtime@npm:0.13.11" - checksum: 27481628d22a1c4e3ff551096a683b424242a216fee44685467307f14d58020af1e19660bf2e26064de946bad7eff28950eae9f8209d55723e2d9351e632bbb4 +"regenerator-runtime@npm:^0.14.0": + version: 0.14.0 + resolution: "regenerator-runtime@npm:0.14.0" + checksum: 1c977ad82a82a4412e4f639d65d22be376d3ebdd30da2c003eeafdaaacd03fc00c2320f18120007ee700900979284fc78a9f00da7fb593f6e6eeebc673fba9a3 languageName: node linkType: hard -"regenerator-transform@npm:^0.15.1": - version: 0.15.1 - resolution: "regenerator-transform@npm:0.15.1" +"regenerator-transform@npm:^0.15.2": + version: 0.15.2 + resolution: "regenerator-transform@npm:0.15.2" dependencies: "@babel/runtime": ^7.8.4 - checksum: 2d15bdeadbbfb1d12c93f5775493d85874dbe1d405bec323da5c61ec6e701bc9eea36167483e1a5e752de9b2df59ab9a2dfff6bf3784f2b28af2279a673d29a4 + checksum: 20b6f9377d65954980fe044cfdd160de98df415b4bff38fbade67b3337efaf078308c4fed943067cd759827cc8cfeca9cb28ccda1f08333b85d6a2acbd022c27 languageName: node linkType: hard -"regexpu-core@npm:^5.2.1": - version: 5.2.2 - resolution: "regexpu-core@npm:5.2.2" +"regexpu-core@npm:^5.3.1": + version: 5.3.2 + resolution: "regexpu-core@npm:5.3.2" dependencies: + "@babel/regjsgen": ^0.8.0 regenerate: ^1.4.2 regenerate-unicode-properties: ^10.1.0 - regjsgen: ^0.7.1 regjsparser: ^0.9.1 unicode-match-property-ecmascript: ^2.0.0 unicode-match-property-value-ecmascript: ^2.1.0 - checksum: 87c56815e20d213848d38f6b047ba52f0d632f36e791b777f59327e8d350c0743b27cc25feab64c0eadc9fe9959dde6b1261af71108a9371b72c8c26beda05ef + checksum: 95bb97088419f5396e07769b7de96f995f58137ad75fac5811fb5fe53737766dfff35d66a0ee66babb1eb55386ef981feaef392f9df6d671f3c124812ba24da2 languageName: node linkType: hard @@ -9985,13 +10484,6 @@ __metadata: languageName: node linkType: hard -"regjsgen@npm:^0.7.1": - version: 0.7.1 - resolution: "regjsgen@npm:0.7.1" - checksum: 7cac399921c58db8e16454869283ff66871531180218064fa938ac05c11c2976792a00706c3c78bbc625e1d793ca373065ea90564e06189a751a7b4ae33acadc - languageName: node - linkType: hard - "regjsparser@npm:^0.9.1": version: 0.9.1 resolution: "regjsparser@npm:0.9.1" @@ -10021,17 +10513,6 @@ __metadata: languageName: node linkType: hard -"remark-comment@npm:^1.0.0": - version: 1.0.0 - resolution: "remark-comment@npm:1.0.0" - dependencies: - micromark-factory-space: ^1.0.0 - micromark-util-character: ^1.1.0 - micromark-util-symbol: ^1.0.1 - checksum: bb455a7a2ec88fe6927a5c585c2c61de9d2a178cec4f8ec9289a6549e07d835a026a0a8e29a27b125eedca04b3174cebd61d0cc30991b7d3d04b3a5bfc37fcd3 - languageName: node - linkType: hard - "remark-directive@npm:^2.0.1": version: 2.0.1 resolution: "remark-directive@npm:2.0.1" @@ -10055,6 +10536,18 @@ __metadata: languageName: node linkType: hard +"remark-frontmatter@npm:^5.0.0": + version: 5.0.0 + resolution: "remark-frontmatter@npm:5.0.0" + dependencies: + "@types/mdast": ^4.0.0 + mdast-util-frontmatter: ^2.0.0 + micromark-extension-frontmatter: ^2.0.0 + unified: ^11.0.0 + checksum: b36e11d528d1d0172489c74ce7961bb6073f7272e71ea1349f765fc79c4246a758aef949174d371a088c48e458af776fcfbb3b043c49cd1120ca8239aeafe16a + languageName: node + linkType: hard + "remark-gfm@npm:^3.0.1": version: 3.0.1 resolution: "remark-gfm@npm:3.0.1" @@ -10229,9 +10722,9 @@ __metadata: languageName: node linkType: hard -"rtlcss@npm:^4.0.0": - version: 4.1.0 - resolution: "rtlcss@npm:4.1.0" +"rtlcss@npm:^4.1.0": + version: 4.1.1 + resolution: "rtlcss@npm:4.1.1" dependencies: escalade: ^3.1.1 picocolors: ^1.0.0 @@ -10239,7 +10732,7 @@ __metadata: strip-json-comments: ^3.1.1 bin: rtlcss: bin/rtlcss.js - checksum: 778b0efb98f0e3a9e9cc2f3a1438887ae8248adf9e7e606361c88e86186cf1eb69d91e9476383b954c40f78bafeb3ce75e32d5fe36059901e07e4e6542ba8b6d + checksum: dcf37d76265b5c84d610488afa68a2506d008f95feac968b35ccae9aa49e7019ae0336a80363303f8f8bbf60df3ecdeb60413548b049114a24748319b68aefde languageName: node linkType: hard @@ -10317,15 +10810,15 @@ __metadata: linkType: hard "sass@npm:^1.57.1": - version: 1.66.1 - resolution: "sass@npm:1.66.1" + version: 1.69.3 + resolution: "sass@npm:1.69.3" dependencies: chokidar: ">=3.0.0 <4.0.0" immutable: ^4.0.0 source-map-js: ">=0.6.2 <2.0.0" bin: sass: sass.js - checksum: 74fc11d0fcd5e16c5331b57dd59865705a299c64e89f2b99646869caeb011dc8d0b6144a6c74a90c264e9ef70654207dbf44fc9b7e3393f8bd14809b904c8a52 + checksum: b89a3370c7ede462b344e2136bf1407bf375855c1ec54f73b6257b18fe59dae5377eb9f7b25f21ae4a25d8f0bc41a165d8d7e5f693d8285b1aa51ac6056c4d19 languageName: node linkType: hard @@ -10336,13 +10829,12 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:^0.20.2": - version: 0.20.2 - resolution: "scheduler@npm:0.20.2" +"scheduler@npm:^0.23.0": + version: 0.23.0 + resolution: "scheduler@npm:0.23.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: c4b35cf967c8f0d3e65753252d0f260271f81a81e427241295c5a7b783abf4ea9e905f22f815ab66676f5313be0a25f47be582254db8f9241b259213e999b8fc + checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a languageName: node linkType: hard @@ -10357,14 +10849,14 @@ __metadata: languageName: node linkType: hard -"schema-utils@npm:^3.0.0, schema-utils@npm:^3.1.1, schema-utils@npm:^3.1.2": - version: 3.1.2 - resolution: "schema-utils@npm:3.1.2" +"schema-utils@npm:^3.0.0, schema-utils@npm:^3.1.1, schema-utils@npm:^3.2.0": + version: 3.3.0 + resolution: "schema-utils@npm:3.3.0" dependencies: "@types/json-schema": ^7.0.8 ajv: ^6.12.5 ajv-keywords: ^3.5.2 - checksum: 39683edfe3beff018cdb1ae4fa296fc55cea13a080aa2b4d9351895cd64b22ba4d87e2e548c2a2ac1bc76e60980670adb0f413a58104479f1a0c12e5663cb8ca + checksum: ea56971926fac2487f0757da939a871388891bc87c6a82220d125d587b388f1704788f3706e7f63a7b70e49fc2db974c41343528caea60444afd5ce0fe4b85c0 languageName: node linkType: hard @@ -10415,7 +10907,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^6.0.0, semver@npm:^6.1.1, semver@npm:^6.1.2, semver@npm:^6.3.0": +"semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" bin: @@ -10424,14 +10916,14 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.2, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8": - version: 7.3.8 - resolution: "semver@npm:7.3.8" +"semver@npm:^7.3.2, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.4": + version: 7.5.4 + resolution: "semver@npm:7.5.4" dependencies: lru-cache: ^6.0.0 bin: semver: bin/semver.js - checksum: ba9c7cbbf2b7884696523450a61fee1a09930d888b7a8d7579025ad93d459b2d1949ee5bbfeb188b2be5f4ac163544c5e98491ad6152df34154feebc2cc337c1 + checksum: 12d8ad952fa353b0995bf180cdac205a4068b759a140e5d3c608317098b3575ac2f1e09182206bf2eb26120e1c0ed8fb92c48c592f6099680de56bb071423ca3 languageName: node linkType: hard @@ -10606,14 +11098,14 @@ __metadata: languageName: node linkType: hard -"sirv@npm:^1.0.7": - version: 1.0.19 - resolution: "sirv@npm:1.0.19" +"sirv@npm:^2.0.3": + version: 2.0.3 + resolution: "sirv@npm:2.0.3" dependencies: "@polka/url": ^1.0.0-next.20 mrmime: ^1.0.0 - totalist: ^1.0.0 - checksum: c943cfc61baf85f05f125451796212ec35d4377af4da90ae8ec1fa23e6d7b0b4d9c74a8fbf65af83c94e669e88a09dc6451ba99154235eead4393c10dda5b07c + totalist: ^3.0.0 + checksum: e2dfd4c97735a6ad6d842d0eec2cd9e3919ff0e46f0d228248c5753ad4b70b832711e77e1259c031c439cdb08303cc54d923685c92b0e890145cc733af7c5568 languageName: node linkType: hard @@ -10770,6 +11262,13 @@ __metadata: languageName: node linkType: hard +"srcset@npm:^4.0.0": + version: 4.0.0 + resolution: "srcset@npm:4.0.0" + checksum: aceb898c9281101ef43bfbf96bf04dfae828e1bf942a45df6fad74ae9f8f0a425f4bca1480e0d22879beb40dd2bc6947e0e1e5f4d307a714666196164bc5769d + languageName: node + linkType: hard + "ssri@npm:^9.0.0": version: 9.0.1 resolution: "ssri@npm:9.0.1" @@ -11031,15 +11530,15 @@ __metadata: languageName: node linkType: hard -"terser-webpack-plugin@npm:^5.3.7": - version: 5.3.7 - resolution: "terser-webpack-plugin@npm:5.3.7" +"terser-webpack-plugin@npm:^5.3.7, terser-webpack-plugin@npm:^5.3.9": + version: 5.3.9 + resolution: "terser-webpack-plugin@npm:5.3.9" dependencies: "@jridgewell/trace-mapping": ^0.3.17 jest-worker: ^27.4.5 schema-utils: ^3.1.1 serialize-javascript: ^6.0.1 - terser: ^5.16.5 + terser: ^5.16.8 peerDependencies: webpack: ^5.1.0 peerDependenciesMeta: @@ -11049,21 +11548,21 @@ __metadata: optional: true uglify-js: optional: true - checksum: 095e699fdeeb553cdf2c6f75f983949271b396d9c201d7ae9fc633c45c1c1ad14c7257ef9d51ccc62213dd3e97f875870ba31550f6d4f1b6674f2615562da7f7 + checksum: 41705713d6f9cb83287936b21e27c658891c78c4392159f5148b5623f0e8c48559869779619b058382a4c9758e7820ea034695e57dc7c474b4962b79f553bc5f languageName: node linkType: hard -"terser@npm:^5.10.0, terser@npm:^5.15.1, terser@npm:^5.16.5": - version: 5.17.1 - resolution: "terser@npm:5.17.1" +"terser@npm:^5.10.0, terser@npm:^5.15.1, terser@npm:^5.16.8": + version: 5.21.0 + resolution: "terser@npm:5.21.0" dependencies: - "@jridgewell/source-map": ^0.3.2 - acorn: ^8.5.0 + "@jridgewell/source-map": ^0.3.3 + acorn: ^8.8.2 commander: ^2.20.0 source-map-support: ~0.5.20 bin: terser: bin/terser - checksum: 69b0e80e3c4084db2819de4d6ae8a2ba79f2fcd7ed6df40fe4b602ec7bfd8e889cc63c7d5268f30990ffecbf6eeda18f857adad9386fe2c2331b398d58ed855c + checksum: 130f1567af1ffa4ddb067651bb284a01b45b5c83e82b3a072a5ff94b0b00ac35090f89c8714631a4a45972f65187bc149fc7144380611f437e1e3d9e174b136b languageName: node linkType: hard @@ -11118,10 +11617,10 @@ __metadata: languageName: node linkType: hard -"totalist@npm:^1.0.0": - version: 1.1.0 - resolution: "totalist@npm:1.1.0" - checksum: dfab80c7104a1d170adc8c18782d6c04b7df08352dec452191208c66395f7ef2af7537ddfa2cf1decbdcfab1a47afbbf0dec6543ea191da98c1c6e1599f86adc +"totalist@npm:^3.0.0": + version: 3.0.1 + resolution: "totalist@npm:3.0.1" + checksum: 5132d562cf88ff93fd710770a92f31dbe67cc19b5c6ccae2efc0da327f0954d211bbfd9456389655d726c624f284b4a23112f56d1da931ca7cfabbe1f45e778a languageName: node linkType: hard @@ -11146,10 +11645,10 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.5.0": - version: 2.5.0 - resolution: "tslib@npm:2.5.0" - checksum: ae3ed5f9ce29932d049908ebfdf21b3a003a85653a9a140d614da6b767a93ef94f460e52c3d787f0e4f383546981713f165037dc2274df212ea9f8a4541004e1 +"tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.6.0": + version: 2.6.2 + resolution: "tslib@npm:2.6.2" + checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad languageName: node linkType: hard @@ -11186,23 +11685,23 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^4.9.4": - version: 4.9.5 - resolution: "typescript@npm:4.9.5" +"typescript@npm:~5.0.0": + version: 5.0.4 + resolution: "typescript@npm:5.0.4" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: ee000bc26848147ad423b581bd250075662a354d84f0e06eb76d3b892328d8d4440b7487b5a83e851b12b255f55d71835b008a66cbf8f255a11e4400159237db + checksum: 82b94da3f4604a8946da585f7d6c3025fff8410779e5bde2855ab130d05e4fd08938b9e593b6ebed165bda6ad9292b230984f10952cf82f0a0ca07bbeaa08172 languageName: node linkType: hard -"typescript@patch:typescript@^4.9.4#~builtin<compat/typescript>": - version: 4.9.5 - resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin<compat/typescript>::version=4.9.5&hash=a1c5e5" +"typescript@patch:typescript@~5.0.0#~builtin<compat/typescript>": + version: 5.0.4 + resolution: "typescript@patch:typescript@npm%3A5.0.4#~builtin<compat/typescript>::version=5.0.4&hash=a1c5e5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 2eee5c37cad4390385db5db5a8e81470e42e8f1401b0358d7390095d6f681b410f2c4a0c496c6ff9ebd775423c7785cdace7bcdad76c7bee283df3d9718c0f20 + checksum: 6a1fe9a77bb9c5176ead919cc4a1499ee63e46b4e05bf667079f11bf3a8f7887f135aa72460a4c3b016e6e6bb65a822cb8689a6d86cbfe92d22cc9f501f09213 languageName: node linkType: hard @@ -11259,6 +11758,21 @@ __metadata: languageName: node linkType: hard +"unified@npm:^11.0.0": + version: 11.0.3 + resolution: "unified@npm:11.0.3" + dependencies: + "@types/unist": ^3.0.0 + bail: ^2.0.0 + devlop: ^1.0.0 + extend: ^3.0.0 + is-plain-obj: ^4.0.0 + trough: ^2.0.0 + vfile: ^6.0.0 + checksum: 402d6b397b98f8966993faca0e1480f5f1825cc44df6a5236b75ab099f14b10ed808e578155c3f535e60676c12ee3f52346ca08d64343a72181d7a6b4d32011d + languageName: node + linkType: hard + "unique-filename@npm:^2.0.0": version: 2.0.1 resolution: "unique-filename@npm:2.0.1" @@ -11309,6 +11823,15 @@ __metadata: languageName: node linkType: hard +"unist-util-is@npm:^6.0.0": + version: 6.0.0 + resolution: "unist-util-is@npm:6.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: f630a925126594af9993b091cf807b86811371e465b5049a6283e08537d3e6ba0f7e248e1e7dab52cfe33f9002606acef093441137181b327f6fe504884b20e2 + languageName: node + linkType: hard + "unist-util-position-from-estree@npm:^1.0.0, unist-util-position-from-estree@npm:^1.1.0": version: 1.1.2 resolution: "unist-util-position-from-estree@npm:1.1.2" @@ -11346,6 +11869,15 @@ __metadata: languageName: node linkType: hard +"unist-util-stringify-position@npm:^4.0.0": + version: 4.0.0 + resolution: "unist-util-stringify-position@npm:4.0.0" + dependencies: + "@types/unist": ^3.0.0 + checksum: e2e7aee4b92ddb64d314b4ac89eef7a46e4c829cbd3ee4aee516d100772b490eb6b4974f653ba0717a0071ca6ea0770bf22b0a2ea62c65fcba1d071285e96324 + languageName: node + linkType: hard + "unist-util-visit-parents@npm:^3.0.0": version: 3.1.1 resolution: "unist-util-visit-parents@npm:3.1.1" @@ -11366,6 +11898,16 @@ __metadata: languageName: node linkType: hard +"unist-util-visit-parents@npm:^6.0.0": + version: 6.0.1 + resolution: "unist-util-visit-parents@npm:6.0.1" + dependencies: + "@types/unist": ^3.0.0 + unist-util-is: ^6.0.0 + checksum: 08927647c579f63b91aafcbec9966dc4a7d0af1e5e26fc69f4e3e6a01215084835a2321b06f3cbe7bf7914a852830fc1439f0fc3d7153d8804ac3ef851ddfa20 + languageName: node + linkType: hard + "unist-util-visit@npm:^2.0.3": version: 2.0.3 resolution: "unist-util-visit@npm:2.0.3" @@ -11388,6 +11930,17 @@ __metadata: languageName: node linkType: hard +"unist-util-visit@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-visit@npm:5.0.0" + dependencies: + "@types/unist": ^3.0.0 + unist-util-is: ^6.0.0 + unist-util-visit-parents: ^6.0.0 + checksum: 9ec42e618e7e5d0202f3c191cd30791b51641285732767ee2e6bcd035931032e3c1b29093f4d7fd0c79175bbc1f26f24f26ee49770d32be76f8730a652a857e6 + languageName: node + linkType: hard + "universalify@npm:^2.0.0": version: 2.0.0 resolution: "universalify@npm:2.0.0" @@ -11402,9 +11955,9 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.0.10": - version: 1.0.11 - resolution: "update-browserslist-db@npm:1.0.11" +"update-browserslist-db@npm:^1.0.13": + version: 1.0.13 + resolution: "update-browserslist-db@npm:1.0.13" dependencies: escalade: ^3.1.1 picocolors: ^1.0.0 @@ -11412,7 +11965,7 @@ __metadata: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: b98327518f9a345c7cad5437afae4d2ae7d865f9779554baf2a200fdf4bac4969076b679b1115434bd6557376bdd37ca7583d0f9b8f8e302d7d4cc1e91b5f231 + checksum: 1e47d80182ab6e4ad35396ad8b61008ae2a1330221175d0abd37689658bdb61af9b705bfc41057fd16682474d79944fb2d86767c5ed5ae34b6276b9bed353322 languageName: node linkType: hard @@ -11499,15 +12052,6 @@ __metadata: languageName: node linkType: hard -"use-sync-external-store@npm:^1.2.0": - version: 1.2.0 - resolution: "use-sync-external-store@npm:1.2.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: 5c639e0f8da3521d605f59ce5be9e094ca772bd44a4ce7322b055a6f58eeed8dda3c94cabd90c7a41fb6fa852210092008afe48f7038792fd47501f33299116a - languageName: node - linkType: hard - "util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": version: 1.0.2 resolution: "util-deprecate@npm:1.0.2" @@ -11593,7 +12137,17 @@ __metadata: languageName: node linkType: hard -"vfile@npm:^5.0.0": +"vfile-message@npm:^4.0.0": + version: 4.0.2 + resolution: "vfile-message@npm:4.0.2" + dependencies: + "@types/unist": ^3.0.0 + unist-util-stringify-position: ^4.0.0 + checksum: 964e7e119f4c0e0270fc269119c41c96da20afa01acb7c9809a88365c8e0c64aa692fafbd952669382b978002ecd7ad31ef4446d85e8a22cdb62f6df20186c2d + languageName: node + linkType: hard + +"vfile@npm:^5.0.0, vfile@npm:^5.3.7": version: 5.3.7 resolution: "vfile@npm:5.3.7" dependencies: @@ -11605,6 +12159,17 @@ __metadata: languageName: node linkType: hard +"vfile@npm:^6.0.0": + version: 6.0.1 + resolution: "vfile@npm:6.0.1" + dependencies: + "@types/unist": ^3.0.0 + unist-util-stringify-position: ^4.0.0 + vfile-message: ^4.0.0 + checksum: 05ccee73aeb00402bc8a5d0708af299e9f4a33f5132805449099295085e3ca3b0d018328bad9ff44cf2e6f4cd364f1d558d3fb9b394243a25b2739207edcb0ed + languageName: node + linkType: hard + "wait-on@npm:^7.0.1": version: 7.0.1 resolution: "wait-on@npm:7.0.1" @@ -11653,23 +12218,30 @@ __metadata: languageName: node linkType: hard -"webpack-bundle-analyzer@npm:^4.8.0": - version: 4.8.0 - resolution: "webpack-bundle-analyzer@npm:4.8.0" +"webpack-bundle-analyzer@npm:^4.9.0": + version: 4.9.1 + resolution: "webpack-bundle-analyzer@npm:4.9.1" dependencies: "@discoveryjs/json-ext": 0.5.7 acorn: ^8.0.4 acorn-walk: ^8.0.0 - chalk: ^4.1.0 commander: ^7.2.0 + escape-string-regexp: ^4.0.0 gzip-size: ^6.0.0 - lodash: ^4.17.20 + is-plain-object: ^5.0.0 + lodash.debounce: ^4.0.8 + lodash.escape: ^4.0.1 + lodash.flatten: ^4.4.0 + lodash.invokemap: ^4.6.0 + lodash.pullall: ^4.2.0 + lodash.uniqby: ^4.7.0 opener: ^1.5.2 - sirv: ^1.0.7 + picocolors: ^1.0.0 + sirv: ^2.0.3 ws: ^7.3.1 bin: webpack-bundle-analyzer: lib/bin/analyzer.js - checksum: acd86f68abb2bcb1a240043c6e2d8e53079499363afed94b96c0ec1abcc4fca2b7a7cbeeb5e13027d02a993c6ea8153194c69e7697faf47528bdaff1e2ce297e + checksum: 7e891c28d5a903242893e55ecc714fa01d7ad6bedade143235c07091b235915349812fa048968462781d59187507962f38b6c61ed7d25fb836ba0ac0ee919a39 languageName: node linkType: hard @@ -11688,9 +12260,9 @@ __metadata: languageName: node linkType: hard -"webpack-dev-server@npm:^4.11.1": - version: 4.13.3 - resolution: "webpack-dev-server@npm:4.13.3" +"webpack-dev-server@npm:^4.15.1": + version: 4.15.1 + resolution: "webpack-dev-server@npm:4.15.1" dependencies: "@types/bonjour": ^3.5.9 "@types/connect-history-api-fallback": ^1.3.5 @@ -11698,7 +12270,7 @@ __metadata: "@types/serve-index": ^1.9.1 "@types/serve-static": ^1.13.10 "@types/sockjs": ^0.3.33 - "@types/ws": ^8.5.1 + "@types/ws": ^8.5.5 ansi-html-community: ^0.0.8 bonjour-service: ^1.0.11 chokidar: ^3.5.3 @@ -11731,17 +12303,17 @@ __metadata: optional: true bin: webpack-dev-server: bin/webpack-dev-server.js - checksum: d019844d3bc384676921afadfbd0a95fd06e475f2d43604789a4a8f42f79a8fb37e745f15f47f352630046dd6c6c9694051a7552b34a056c59d3a601e74d6320 + checksum: cd0063b068d2b938fd76c412d555374186ac2fa84bbae098265212ed50a5c15d6f03aa12a5a310c544a242943eb58c0bfde4c296d5c36765c182f53799e1bc71 languageName: node linkType: hard -"webpack-merge@npm:^5.8.0": - version: 5.8.0 - resolution: "webpack-merge@npm:5.8.0" +"webpack-merge@npm:^5.9.0": + version: 5.9.0 + resolution: "webpack-merge@npm:5.9.0" dependencies: clone-deep: ^4.0.1 wildcard: ^2.0.0 - checksum: 88786ab91013f1bd2a683834ff381be81c245a4b0f63304a5103e90f6653f44dab496a0768287f8531761f8ad957d1f9f3ccb2cb55df0de1bd9ee343e079da26 + checksum: 64fe2c23aacc5f19684452a0e84ec02c46b990423aee6fcc5c18d7d471155bd14e9a6adb02bd3656eb3e0ac2532c8e97d69412ad14c97eeafe32fa6d10050872 languageName: node linkType: hard @@ -11752,9 +12324,9 @@ __metadata: languageName: node linkType: hard -"webpack@npm:^5.76.0": - version: 5.81.0 - resolution: "webpack@npm:5.81.0" +"webpack@npm:^5.88.1": + version: 5.88.2 + resolution: "webpack@npm:5.88.2" dependencies: "@types/eslint-scope": ^3.7.3 "@types/estree": ^1.0.0 @@ -11762,10 +12334,10 @@ __metadata: "@webassemblyjs/wasm-edit": ^1.11.5 "@webassemblyjs/wasm-parser": ^1.11.5 acorn: ^8.7.1 - acorn-import-assertions: ^1.7.6 + acorn-import-assertions: ^1.9.0 browserslist: ^4.14.5 chrome-trace-event: ^1.0.2 - enhanced-resolve: ^5.13.0 + enhanced-resolve: ^5.15.0 es-module-lexer: ^1.2.1 eslint-scope: 5.1.1 events: ^3.2.0 @@ -11775,7 +12347,7 @@ __metadata: loader-runner: ^4.2.0 mime-types: ^2.1.27 neo-async: ^2.6.2 - schema-utils: ^3.1.2 + schema-utils: ^3.2.0 tapable: ^2.1.1 terser-webpack-plugin: ^5.3.7 watchpack: ^2.4.0 @@ -11785,7 +12357,7 @@ __metadata: optional: true bin: webpack: bin/webpack.js - checksum: 1a6eecaffac3226d80f4e8f330b32e0ff117d9dafd8700166d230afbc171d68ea1ff55a9939fa789307f7b9d11881889ccb8e6cd79d4ccbaeef916788ce73fdb + checksum: 79476a782da31a21f6dd38fbbd06b68da93baf6a62f0d08ca99222367f3b8668f5a1f2086b7bb78e23172e31fa6df6fa7ab09b25e827866c4fc4dc2b30443ce2 languageName: node linkType: hard @@ -12002,6 +12574,13 @@ __metadata: languageName: node linkType: hard +"yocto-queue@npm:^1.0.0": + version: 1.0.0 + resolution: "yocto-queue@npm:1.0.0" + checksum: 2cac84540f65c64ccc1683c267edce396b26b1e931aa429660aefac8fbe0188167b7aee815a3c22fa59a28a58d898d1a2b1825048f834d8d629f4c2a5d443801 + languageName: node + linkType: hard + "zwitch@npm:^2.0.0": version: 2.0.4 resolution: "zwitch@npm:2.0.4" diff --git a/package.json b/package.json index 7b7d962780..6a21034cae 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "build:api-reports": "yarn build:api-reports:only --tsc", "build:api-reports:only": "backstage-repo-tools api-reports --allow-warnings 'packages/core-components,plugins/+(catalog|catalog-import|git-release-manager|jenkins|kubernetes)' -o ae-wrong-input-file-type --validate-release-tags", "build:api-docs": "LANG=en_EN yarn build:api-reports --docs", + "build:plugins-report": "node ./scripts/build-plugins-report", "tsc": "tsc", "tsc:full": "backstage-cli repo clean && tsc --skipLibCheck false --incremental false", "clean": "backstage-cli repo clean", @@ -46,12 +47,14 @@ ] }, "resolutions": { - "@types/react": "^17", - "@types/react-dom": "^17", + "@types/react": "^18", + "@types/react-dom": "^18", "jest-haste-map@^29.4.3": "patch:jest-haste-map@npm%3A29.4.3#./.yarn/patches/jest-haste-map-npm-29.4.3-19b03fcef3.patch", - "mock-fs@^5.2.0": "patch:mock-fs@npm%3A5.2.0#./.yarn/patches/mock-fs-npm-5.2.0-5103a7b507.patch" + "mock-fs@^5.2.0": "patch:mock-fs@npm%3A5.2.0#./.yarn/patches/mock-fs-npm-5.2.0-5103a7b507.patch", + "@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.19.0-next.1", + "version": "1.19.0", "dependencies": { "@backstage/errors": "workspace:^", "@manypkg/get-packages": "^1.1.3" diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index 573ef62905..d212580484 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/app-defaults +## 1.4.4 + +### Patch Changes + +- 1a0616fa10: Add missing resource and template app icons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + +## 1.4.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-permission-react@0.4.16-next.1 + ## 1.4.4-next.1 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index b583443902..9ab12f7cc5 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.4-next.1", + "version": "1.4.4", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -42,15 +42,15 @@ "@material-ui/icons": "^4.9.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/packages/app-next-example-plugin/CHANGELOG.md b/packages/app-next-example-plugin/CHANGELOG.md index 22136e2b59..3402944211 100644 --- a/packages/app-next-example-plugin/CHANGELOG.md +++ b/packages/app-next-example-plugin/CHANGELOG.md @@ -1,5 +1,21 @@ # app-next-example-plugin +## 0.0.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-components@0.13.6 + +## 0.0.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/core-components@0.13.6-next.2 + ## 0.0.2-next.1 ### Patch Changes diff --git a/packages/app-next-example-plugin/api-report.md b/packages/app-next-example-plugin/api-report.md index 68a0471b6b..c89a7b599b 100644 --- a/packages/app-next-example-plugin/api-report.md +++ b/packages/app-next-example-plugin/api-report.md @@ -7,7 +7,7 @@ import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { default as React_2 } from 'react'; // @public (undocumented) -const examplePlugin: BackstagePlugin; +const examplePlugin: BackstagePlugin<{}, {}>; export default examplePlugin; // @public (undocumented) diff --git a/packages/app-next-example-plugin/package.json b/packages/app-next-example-plugin/package.json index ad797aaeb7..865c6e0800 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.2-next.1", + "version": "0.0.2", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -39,8 +39,8 @@ "@material-ui/icons": "^4.9.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/packages/app-next/CHANGELOG.md b/packages/app-next/CHANGELOG.md index b9aa117f5b..0a80d6d902 100644 --- a/packages/app-next/CHANGELOG.md +++ b/packages/app-next/CHANGELOG.md @@ -1,5 +1,159 @@ # example-app-next +## 0.0.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.2.0 + - @backstage/plugin-pagerduty@0.6.6 + - @backstage/plugin-org@0.6.15 + - @backstage/plugin-code-coverage@0.2.18 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-home@0.5.9 + - @backstage/plugin-newrelic@0.3.41 + - @backstage/plugin-user-settings@0.7.11 + - @backstage/plugin-scaffolder@1.15.1 + - @backstage/core-components@0.13.6 + - @backstage/plugin-entity-feedback@0.2.8 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-tech-radar@0.6.9 + - @backstage/plugin-adr@0.6.8 + - @backstage/app-defaults@1.4.4 + - @backstage/plugin-graphiql@0.2.55 + - @backstage/plugin-search@1.4.1 + - @backstage/plugin-jenkins@0.9.0 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-api-docs@0.9.12 + - @backstage/plugin-kubernetes@0.11.0 + - @backstage/plugin-airbrake@0.3.25 + - @backstage/plugin-apache-airflow@0.2.16 + - @backstage/plugin-azure-devops@0.3.7 + - @backstage/plugin-azure-sites@0.1.14 + - @backstage/plugin-badges@0.2.49 + - @backstage/plugin-catalog-graph@0.2.37 + - @backstage/plugin-catalog-import@0.10.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4 + - @backstage/plugin-circleci@0.3.25 + - @backstage/plugin-cloudbuild@0.3.25 + - @backstage/plugin-cost-insights@0.12.14 + - @backstage/plugin-devtools@0.1.5 + - @backstage/plugin-dynatrace@7.0.5 + - @backstage/plugin-explore@0.4.11 + - @backstage/plugin-gcalendar@0.3.19 + - @backstage/plugin-gcp-projects@0.3.42 + - @backstage/plugin-github-actions@0.6.6 + - @backstage/plugin-gocd@0.1.31 + - @backstage/plugin-kafka@0.3.25 + - @backstage/plugin-lighthouse@0.4.10 + - @backstage/plugin-linguist@0.1.10 + - @backstage/plugin-microsoft-calendar@0.1.8 + - @backstage/plugin-newrelic-dashboard@0.3.0 + - @backstage/plugin-octopus-deploy@0.2.7 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/plugin-playlist@0.1.17 + - @backstage/plugin-puppetdb@0.1.8 + - @backstage/plugin-rollbar@0.4.25 + - @backstage/plugin-scaffolder-react@1.5.6 + - @backstage/plugin-sentry@0.5.10 + - @backstage/plugin-shortcuts@0.3.15 + - @backstage/plugin-stack-overflow@0.1.21 + - @backstage/plugin-stackstorm@0.1.7 + - @backstage/plugin-tech-insights@0.3.17 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/plugin-todo@0.2.28 + - @backstage/theme@0.4.3 + - app-next-example-plugin@0.0.2 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.7 + +## 0.0.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.23.0-next.2 + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/frontend-app-api@0.2.0-next.2 + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/plugin-techdocs@1.7.1-next.2 + - @backstage/plugin-newrelic@0.3.41-next.2 + - @backstage/plugin-scaffolder@1.15.1-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/plugin-tech-radar@0.6.9-next.2 + - @backstage/plugin-catalog@1.14.0-next.2 + - @backstage/plugin-adr@0.6.8-next.2 + - @backstage/plugin-graphiql@0.2.55-next.2 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/plugin-newrelic-dashboard@0.3.0-next.2 + - @backstage/plugin-kubernetes@0.11.0-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-jenkins@0.8.7-next.2 + - @backstage/plugin-tech-insights@0.3.17-next.2 + - @backstage/plugin-playlist@0.1.17-next.2 + - @backstage/app-defaults@1.4.4-next.2 + - app-next-example-plugin@0.0.2-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-airbrake@0.3.25-next.2 + - @backstage/plugin-apache-airflow@0.2.16-next.2 + - @backstage/plugin-api-docs@0.9.12-next.2 + - @backstage/plugin-azure-devops@0.3.7-next.2 + - @backstage/plugin-azure-sites@0.1.14-next.2 + - @backstage/plugin-badges@0.2.49-next.2 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-catalog-graph@0.2.37-next.2 + - @backstage/plugin-catalog-import@0.10.1-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4-next.2 + - @backstage/plugin-circleci@0.3.25-next.2 + - @backstage/plugin-cloudbuild@0.3.25-next.2 + - @backstage/plugin-code-coverage@0.2.18-next.2 + - @backstage/plugin-cost-insights@0.12.14-next.2 + - @backstage/plugin-devtools@0.1.5-next.2 + - @backstage/plugin-dynatrace@7.0.5-next.2 + - @backstage/plugin-entity-feedback@0.2.8-next.2 + - @backstage/plugin-explore@0.4.11-next.2 + - @backstage/plugin-gcalendar@0.3.19-next.2 + - @backstage/plugin-gcp-projects@0.3.42-next.2 + - @backstage/plugin-github-actions@0.6.6-next.2 + - @backstage/plugin-gocd@0.1.31-next.2 + - @backstage/plugin-home@0.5.9-next.2 + - @backstage/plugin-kafka@0.3.25-next.2 + - @backstage/plugin-lighthouse@0.4.10-next.2 + - @backstage/plugin-linguist@0.1.10-next.2 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-microsoft-calendar@0.1.8-next.2 + - @backstage/plugin-octopus-deploy@0.2.7-next.2 + - @backstage/plugin-org@0.6.15-next.2 + - @backstage/plugin-pagerduty@0.6.6-next.2 + - @backstage/plugin-permission-react@0.4.16-next.1 + - @backstage/plugin-puppetdb@0.1.8-next.2 + - @backstage/plugin-rollbar@0.4.25-next.2 + - @backstage/plugin-scaffolder-react@1.5.6-next.2 + - @backstage/plugin-search@1.4.1-next.2 + - @backstage/plugin-search-common@1.2.7-next.0 + - @backstage/plugin-sentry@0.5.10-next.2 + - @backstage/plugin-shortcuts@0.3.15-next.2 + - @backstage/plugin-stack-overflow@0.1.21-next.2 + - @backstage/plugin-stackstorm@0.1.7-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1-next.2 + - @backstage/plugin-techdocs-react@1.1.12-next.2 + - @backstage/plugin-todo@0.2.28-next.2 + - @backstage/plugin-user-settings@0.7.11-next.2 + ## 0.0.2-next.1 ### Patch Changes diff --git a/packages/app-next/app-config.yaml b/packages/app-next/app-config.yaml index a97c52f40f..6f6081fece 100644 --- a/packages/app-next/app-config.yaml +++ b/packages/app-next/app-config.yaml @@ -1,6 +1,11 @@ app: experimental: packages: 'all' # ✨ + routes: + bindings: + plugin.pages.externalRoutes.pageX: plugin.pages.routes.pageX + # waiting for https://github.com/backstage/backstage/pull/20605 + # catalog.externalRoutes.viewTechDoc: techdocs.routes.docRoot extensions: - apis.plugin.graphiql.browse.gitlab: true diff --git a/packages/app-next/package.json b/packages/app-next/package.json index 50ebf77ec2..71d888ee50 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -1,6 +1,6 @@ { "name": "example-app-next", - "version": "0.0.2-next.1", + "version": "0.0.2", "private": true, "backstage": { "role": "frontend" @@ -12,6 +12,7 @@ "@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/frontend-app-api": "workspace:^", @@ -89,9 +90,8 @@ "app-next-example-plugin": "workspace:^", "history": "^5.0.0", "lodash": "^4.17.21", - "prop-types": "^15.7.2", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.0.2", + "react-dom": "^18.0.2", "react-router": "^6.3.0", "react-router-dom": "^6.3.0", "react-use": "^17.2.4", @@ -99,9 +99,9 @@ }, "devDependencies": { "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/jquery": "^3.3.34", "@types/react": "*", diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index d844939cf2..4e42d9b268 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -14,10 +14,37 @@ * limitations under the License. */ +import React from 'react'; import { createApp } from '@backstage/frontend-app-api'; import { pagesPlugin } from './examples/pagesPlugin'; import graphiqlPlugin from '@backstage/plugin-graphiql/alpha'; import techRadarPlugin from '@backstage/plugin-tech-radar/alpha'; +import userSettingsPlugin from '@backstage/plugin-user-settings/alpha'; +import homePlugin, { + titleExtensionDataRef, +} from '@backstage/plugin-home/alpha'; + +import { + coreExtensionData, + createExtension, + createApiExtension, + createExtensionOverrides, + createPageExtension, +} from '@backstage/frontend-plugin-api'; +import { entityRouteRef } from '@backstage/plugin-catalog-react'; +import techdocsPlugin from '@backstage/plugin-techdocs/alpha'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; +import { homePage } from './HomePage'; +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 { + ScmAuth, + ScmIntegrationsApi, + scmIntegrationsApiRef, +} from '@backstage/integration-react'; /* @@ -48,15 +75,64 @@ TODO: /* app.tsx */ +const entityPageExtension = createPageExtension({ + id: 'catalog:entity', + defaultPath: '/catalog/:namespace/:kind/:name', + routeRef: convertLegacyRouteRef(entityRouteRef), + loader: async () => <div>Just a temporary mocked entity page</div>, +}); + +const homePageExtension = createExtension({ + id: 'myhomepage', + attachTo: { id: 'home', input: 'props' }, + output: { + children: coreExtensionData.reactElement, + title: titleExtensionDataRef, + }, + factory({ bind }) { + bind({ children: homePage, title: 'just a title' }); + }, +}); + +const scmAuthExtension = createApiExtension({ + factory: ScmAuth.createDefaultApiFactory(), +}); + +const scmIntegrationApi = createApiExtension({ + factory: createApiFactory({ + api: scmIntegrationsApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => ScmIntegrationsApi.fromConfig(configApi), + }), +}); + +const collectedLegacyPlugins = collectLegacyRoutes( + <FlatRoutes> + <Route path="/catalog-import" element={<CatalogImportPage />} /> + </FlatRoutes>, +); + const app = createApp({ - plugins: [graphiqlPlugin, pagesPlugin, techRadarPlugin], + features: [ + graphiqlPlugin, + pagesPlugin, + techRadarPlugin, + techdocsPlugin, + userSettingsPlugin, + homePlugin, + ...collectedLegacyPlugins, + createExtensionOverrides({ + extensions: [ + entityPageExtension, + homePageExtension, + scmAuthExtension, + scmIntegrationApi, + ], + }), + ], + /* Handled through config instead */ // bindRoutes({ bind }) { - // bind(catalogPlugin.externalRoutes, { - // createComponent: scaffolderPlugin.routes.root, - // }); - // bind(scaffolderPlugin.externalRoutes, { - // registerComponent: catalogImportPlugin.routes.importPage, - // }); + // bind(pagesPlugin.externalRoutes, { pageX: pagesPlugin.routes.pageX }); // }, }); diff --git a/packages/app-next/src/HomePage.tsx b/packages/app-next/src/HomePage.tsx new file mode 100644 index 0000000000..cb31beb34a --- /dev/null +++ b/packages/app-next/src/HomePage.tsx @@ -0,0 +1,119 @@ +/* + * 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 { + ClockConfig, + CustomHomepageGrid, + HeaderWorldClock, + HomePageCompanyLogo, + HomePageRandomJoke, + HomePageStarredEntities, + HomePageToolkit, + HomePageTopVisited, + HomePageRecentlyVisited, + WelcomeTitle, +} from '@backstage/plugin-home'; +import { Content, Header, Page } from '@backstage/core-components'; +import { HomePageCalendar } from '@backstage/plugin-gcalendar'; +import { MicrosoftCalendarCard } from '@backstage/plugin-microsoft-calendar'; +import React from 'react'; +import HomeIcon from '@material-ui/icons/Home'; +import { HomePagePagerDutyCard } from '@backstage/plugin-pagerduty'; + +const clockConfigs: ClockConfig[] = [ + { + label: 'NYC', + timeZone: 'America/New_York', + }, + { + label: 'UTC', + timeZone: 'UTC', + }, + { + label: 'STO', + timeZone: 'Europe/Stockholm', + }, + { + label: 'TYO', + timeZone: 'Asia/Tokyo', + }, +]; + +const timeFormat: Intl.DateTimeFormatOptions = { + hour: '2-digit', + minute: '2-digit', + hour12: false, +}; + +const defaultConfig = [ + { + component: 'CompanyLogo', + x: 0, + y: 0, + width: 12, + height: 1, + movable: false, + resizable: false, + deletable: false, + }, + { + component: 'WelcomeTitle', + x: 0, + y: 1, + width: 12, + height: 1, + }, + { + component: 'HomePageSearchBar', + x: 0, + y: 2, + width: 12, + height: 2, + }, +]; + +export const homePage = ( + <Page themeId="home"> + <Header title={<WelcomeTitle />} pageTitleOverride="Home"> + <HeaderWorldClock + clockConfigs={clockConfigs} + customTimeFormat={timeFormat} + /> + </Header> + <Content> + <CustomHomepageGrid config={defaultConfig}> + <HomePageRandomJoke /> + <HomePageCalendar /> + <HomePagePagerDutyCard name="Rota" /> + <MicrosoftCalendarCard /> + <HomePageStarredEntities /> + <HomePageCompanyLogo /> + <WelcomeTitle /> + <HomePageToolkit + tools={[ + { + url: 'https://backstage.io', + label: 'Backstage Homepage', + icon: <HomeIcon />, + }, + ]} + /> + <HomePageTopVisited /> + <HomePageRecentlyVisited /> + </CustomHomepageGrid> + </Content> + </Page> +); diff --git a/packages/app-next/src/examples/pagesPlugin.tsx b/packages/app-next/src/examples/pagesPlugin.tsx index 290c6b118e..1e9409a5e4 100644 --- a/packages/app-next/src/examples/pagesPlugin.tsx +++ b/packages/app-next/src/examples/pagesPlugin.tsx @@ -19,13 +19,16 @@ import { Link } from '@backstage/core-components'; import { createPageExtension, createPlugin, + createRouteRef, + createExternalRouteRef, useRouteRef, } from '@backstage/frontend-plugin-api'; -import { createRouteRef } from '@backstage/core-plugin-api'; import { Route, Routes } from 'react-router-dom'; -const indexRouteRef = createRouteRef({ id: 'index' }); -const page1RouteRef = createRouteRef({ id: 'page1' }); +const indexRouteRef = createRouteRef(); +const page1RouteRef = createRouteRef(); +export const externalPageXRouteRef = createExternalRouteRef(); +export const pageXRouteRef = createRouteRef(); // const page2RouteRef = createSubRouteRef({ // id: 'page2', // parent: page1RouteRef, @@ -45,12 +48,18 @@ const IndexPage = createPageExtension({ <div> <Link to={page1Link()}>Page 1</Link> </div> + <div> + <Link to="/home">Home</Link> + </div> <div> <Link to="/graphiql">GraphiQL</Link> </div> <div> <Link to="/search">Search</Link> </div> + <div> + <Link to="/settings">Settings</Link> + </div> </div> ); }; @@ -65,6 +74,7 @@ const Page1 = createPageExtension({ loader: async () => { const Component = () => { const indexLink = useRouteRef(indexRouteRef); + const xLink = useRouteRef(externalPageXRouteRef); // const page2Link = useRouteRef(page2RouteRef); return ( @@ -73,6 +83,7 @@ const Page1 = createPageExtension({ <Link to={indexLink()}>Go back</Link> <Link to="./page2">Page 2</Link> {/* <Link to={page2Link()}>Page 2</Link> */} + <Link to={xLink()}>Page X</Link> <div> Sub-page content: @@ -90,6 +101,26 @@ const Page1 = createPageExtension({ }, }); +const ExternalPage = createPageExtension({ + id: 'pageX', + defaultPath: '/pageX', + routeRef: pageXRouteRef, + loader: async () => { + const Component = () => { + const indexLink = useRouteRef(indexRouteRef); + // const pageXLink = useRouteRef(pageXRouteRef); + + return ( + <div> + <h1>This is page X</h1> + <Link to={indexLink()}>Go back</Link> + </div> + ); + }; + return <Component />; + }, +}); + export const pagesPlugin = createPlugin({ id: 'pages', // routes: { @@ -99,5 +130,12 @@ export const pagesPlugin = createPlugin({ // // OR // // 'page1' // }, - extensions: [IndexPage, Page1], + routes: { + page1: page1RouteRef, + pageX: pageXRouteRef, + }, + externalRoutes: { + pageX: externalPageXRouteRef, + }, + extensions: [IndexPage, Page1, ExternalPage], }); diff --git a/packages/app-next/src/index.tsx b/packages/app-next/src/index.tsx index 3c354b06d0..37a2574484 100644 --- a/packages/app-next/src/index.tsx +++ b/packages/app-next/src/index.tsx @@ -15,7 +15,7 @@ */ import '@backstage/cli/asset-types'; -import ReactDOM from 'react-dom'; +import ReactDOM from 'react-dom/client'; import app from './App'; -ReactDOM.render(app, document.getElementById('root')); +ReactDOM.createRoot(document.getElementById('root')!).render(app); diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 7b14d026a0..f339cf74da 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,159 @@ # example-app +## 0.2.88 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-app-api@0.2.0 + - @backstage/plugin-pagerduty@0.6.6 + - @backstage/plugin-org@0.6.15 + - @backstage/plugin-code-coverage@0.2.18 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-home@0.5.9 + - @backstage/plugin-newrelic@0.3.41 + - @backstage/plugin-user-settings@0.7.11 + - @backstage/plugin-scaffolder@1.15.1 + - @backstage/core-components@0.13.6 + - @backstage/plugin-entity-feedback@0.2.8 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-tech-radar@0.6.9 + - @backstage/plugin-adr@0.6.8 + - @backstage/app-defaults@1.4.4 + - @backstage/plugin-graphiql@0.2.55 + - @backstage/plugin-search@1.4.1 + - @backstage/plugin-jenkins@0.9.0 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-api-docs@0.9.12 + - @backstage/plugin-kubernetes@0.11.0 + - @backstage/plugin-airbrake@0.3.25 + - @backstage/plugin-apache-airflow@0.2.16 + - @backstage/plugin-azure-devops@0.3.7 + - @backstage/plugin-azure-sites@0.1.14 + - @backstage/plugin-badges@0.2.49 + - @backstage/plugin-catalog-graph@0.2.37 + - @backstage/plugin-catalog-import@0.10.1 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4 + - @backstage/plugin-circleci@0.3.25 + - @backstage/plugin-cloudbuild@0.3.25 + - @backstage/plugin-cost-insights@0.12.14 + - @backstage/plugin-devtools@0.1.5 + - @backstage/plugin-dynatrace@7.0.5 + - @backstage/plugin-explore@0.4.11 + - @backstage/plugin-gcalendar@0.3.19 + - @backstage/plugin-gcp-projects@0.3.42 + - @backstage/plugin-github-actions@0.6.6 + - @backstage/plugin-gocd@0.1.31 + - @backstage/plugin-kafka@0.3.25 + - @backstage/plugin-kubernetes-cluster@0.0.1 + - @backstage/plugin-lighthouse@0.4.10 + - @backstage/plugin-linguist@0.1.10 + - @backstage/plugin-microsoft-calendar@0.1.8 + - @backstage/plugin-newrelic-dashboard@0.3.0 + - @backstage/plugin-nomad@0.1.6 + - @backstage/plugin-octopus-deploy@0.2.7 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/plugin-playlist@0.1.17 + - @backstage/plugin-puppetdb@0.1.8 + - @backstage/plugin-rollbar@0.4.25 + - @backstage/plugin-scaffolder-react@1.5.6 + - @backstage/plugin-sentry@0.5.10 + - @backstage/plugin-shortcuts@0.3.15 + - @backstage/plugin-stack-overflow@0.1.21 + - @backstage/plugin-stackstorm@0.1.7 + - @backstage/plugin-tech-insights@0.3.17 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/plugin-todo@0.2.28 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-search-common@1.2.7 + +## 0.2.88-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.23.0-next.2 + - @backstage/frontend-app-api@0.2.0-next.2 + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/plugin-techdocs@1.7.1-next.2 + - @backstage/plugin-newrelic@0.3.41-next.2 + - @backstage/plugin-scaffolder@1.15.1-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/plugin-tech-radar@0.6.9-next.2 + - @backstage/plugin-catalog@1.14.0-next.2 + - @backstage/plugin-adr@0.6.8-next.2 + - @backstage/plugin-graphiql@0.2.55-next.2 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/plugin-newrelic-dashboard@0.3.0-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.1-next.0 + - @backstage/plugin-kubernetes@0.11.0-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-jenkins@0.8.7-next.2 + - @backstage/plugin-tech-insights@0.3.17-next.2 + - @backstage/plugin-playlist@0.1.17-next.2 + - @backstage/app-defaults@1.4.4-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-airbrake@0.3.25-next.2 + - @backstage/plugin-apache-airflow@0.2.16-next.2 + - @backstage/plugin-api-docs@0.9.12-next.2 + - @backstage/plugin-azure-devops@0.3.7-next.2 + - @backstage/plugin-azure-sites@0.1.14-next.2 + - @backstage/plugin-badges@0.2.49-next.2 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-catalog-graph@0.2.37-next.2 + - @backstage/plugin-catalog-import@0.10.1-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.1.4-next.2 + - @backstage/plugin-circleci@0.3.25-next.2 + - @backstage/plugin-cloudbuild@0.3.25-next.2 + - @backstage/plugin-code-coverage@0.2.18-next.2 + - @backstage/plugin-cost-insights@0.12.14-next.2 + - @backstage/plugin-devtools@0.1.5-next.2 + - @backstage/plugin-dynatrace@7.0.5-next.2 + - @backstage/plugin-entity-feedback@0.2.8-next.2 + - @backstage/plugin-explore@0.4.11-next.2 + - @backstage/plugin-gcalendar@0.3.19-next.2 + - @backstage/plugin-gcp-projects@0.3.42-next.2 + - @backstage/plugin-github-actions@0.6.6-next.2 + - @backstage/plugin-gocd@0.1.31-next.2 + - @backstage/plugin-home@0.5.9-next.2 + - @backstage/plugin-kafka@0.3.25-next.2 + - @backstage/plugin-lighthouse@0.4.10-next.2 + - @backstage/plugin-linguist@0.1.10-next.2 + - @backstage/plugin-linguist-common@0.1.2 + - @backstage/plugin-microsoft-calendar@0.1.8-next.2 + - @backstage/plugin-nomad@0.1.6-next.2 + - @backstage/plugin-octopus-deploy@0.2.7-next.2 + - @backstage/plugin-org@0.6.15-next.2 + - @backstage/plugin-pagerduty@0.6.6-next.2 + - @backstage/plugin-permission-react@0.4.16-next.1 + - @backstage/plugin-puppetdb@0.1.8-next.2 + - @backstage/plugin-rollbar@0.4.25-next.2 + - @backstage/plugin-scaffolder-react@1.5.6-next.2 + - @backstage/plugin-search@1.4.1-next.2 + - @backstage/plugin-search-common@1.2.7-next.0 + - @backstage/plugin-sentry@0.5.10-next.2 + - @backstage/plugin-shortcuts@0.3.15-next.2 + - @backstage/plugin-stack-overflow@0.1.21-next.2 + - @backstage/plugin-stackstorm@0.1.7-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.1-next.2 + - @backstage/plugin-techdocs-react@1.1.12-next.2 + - @backstage/plugin-todo@0.2.28-next.2 + - @backstage/plugin-user-settings@0.7.11-next.2 + ## 0.2.88-next.1 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 6e06d2ca03..df48491481 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.88-next.1", + "version": "0.2.88", "private": true, "backstage": { "role": "frontend" @@ -94,9 +94,8 @@ "@roadiehq/backstage-plugin-github-pull-requests": "^2.2.7", "@roadiehq/backstage-plugin-travis-ci": "^2.0.5", "history": "^5.0.0", - "prop-types": "^15.7.2", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.0.2", + "react-dom": "^18.0.2", "react-router": "^6.3.0", "react-router-dom": "^6.3.0", "react-use": "^17.2.4", @@ -105,9 +104,9 @@ "devDependencies": { "@backstage/test-utils": "workspace:^", "@playwright/test": "^1.32.3", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/jquery": "^3.3.34", "@types/react": "*", diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index f2b7d66b21..cc3787a8bc 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -64,7 +64,7 @@ import { GcpProjectsPage } from '@backstage/plugin-gcp-projects'; import { HomepageCompositionRoot, VisitListener } from '@backstage/plugin-home'; import { LighthousePage } from '@backstage/plugin-lighthouse'; import { NewRelicPage } from '@backstage/plugin-newrelic'; -import { NextScaffolderPage } from '@backstage/plugin-scaffolder/alpha'; +import { LegacyScaffolderPage } from '@backstage/plugin-scaffolder/alpha'; import { ScaffolderPage, scaffolderPlugin } from '@backstage/plugin-scaffolder'; import { ScaffolderFieldExtensions, @@ -236,11 +236,11 @@ const routes = ( <LightBox /> </TechDocsAddons> </Route> - <FeatureFlagged with="scaffolder-next-preview"> + <FeatureFlagged with="scaffolder-legacy"> <Route path="/create" element={ - <NextScaffolderPage + <LegacyScaffolderPage groups={[ { title: 'Recommended', @@ -252,14 +252,14 @@ const routes = ( } > <ScaffolderFieldExtensions> - <DelayingComponentFieldExtension /> + <LowerCaseValuePickerFieldExtension /> </ScaffolderFieldExtensions> <ScaffolderLayouts> <TwoColumnLayout /> </ScaffolderLayouts> </Route> </FeatureFlagged> - <FeatureFlagged without="scaffolder-next-preview"> + <FeatureFlagged without="scaffolder-legacy"> <Route path="/create" element={ @@ -276,7 +276,7 @@ const routes = ( } > <ScaffolderFieldExtensions> - <LowerCaseValuePickerFieldExtension /> + <DelayingComponentFieldExtension /> </ScaffolderFieldExtensions> <ScaffolderLayouts> <TwoColumnLayout /> diff --git a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx index b15d12979a..e236e01d79 100644 --- a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx +++ b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx @@ -17,10 +17,6 @@ import React from 'react'; import type { FieldValidation } from '@rjsf/utils'; import { scaffolderPlugin } from '@backstage/plugin-scaffolder'; import { TextField } from '@material-ui/core'; -import { - NextFieldExtensionComponentProps, - createNextScaffolderFieldExtension, -} from '@backstage/plugin-scaffolder-react/alpha'; import { createScaffolderFieldExtension, FieldExtensionComponentProps, @@ -67,7 +63,7 @@ export const LowerCaseValuePickerFieldExtension = scaffolderPlugin.provide( ); const MockDelayComponent = ( - props: NextFieldExtensionComponentProps<{ test?: string }>, + props: FieldExtensionComponentProps<{ test?: string }>, ) => { const { onChange, formData, rawErrors = [] } = props; return ( @@ -83,7 +79,7 @@ const MockDelayComponent = ( }; export const DelayingComponentFieldExtension = scaffolderPlugin.provide( - createNextScaffolderFieldExtension({ + createScaffolderFieldExtension({ name: 'DelayingComponent', component: MockDelayComponent, validation: async ( diff --git a/packages/app/src/index.tsx b/packages/app/src/index.tsx index b15bc4c102..e5ca03fe64 100644 --- a/packages/app/src/index.tsx +++ b/packages/app/src/index.tsx @@ -16,7 +16,7 @@ import '@backstage/cli/asset-types'; import React from 'react'; -import ReactDOM from 'react-dom'; +import ReactDOM from 'react-dom/client'; import App from './App'; -ReactDOM.render(<App />, document.getElementById('root')); +ReactDOM.createRoot(document.getElementById('root')!).render(<App />); diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index cf24e558fd..efc72cefc8 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/backend-app-api +## 0.5.6 + +### Patch Changes + +- 74491c9602: Moved `HostDiscovery` from `@backstage/backend-common`. +- a4617c422a: Added `watch` option to configuration loaders that can be used to disable file watching by setting it to `false`. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/cli-node@0.1.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.5.6-next.2 + +### Patch Changes + +- 74491c9602: Moved `HostDiscovery` from `@backstage/backend-common`. +- a4617c422a: Added `watch` option to configuration loaders that can be used to disable file watching by setting it to `false`. +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/config-loader@1.5.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/cli-node@0.1.5-next.1 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + ## 0.5.5-next.1 ### Patch Changes diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md index ecfbc1fe7d..e478a91bb7 100644 --- a/packages/backend-app-api/api-report.md +++ b/packages/backend-app-api/api-report.md @@ -204,6 +204,7 @@ export function loadBackendConfig(options: { remote?: LoadConfigOptionsRemote; argv: string[]; additionalConfigs?: AppConfig[]; + watch?: boolean; }): Promise<{ config: Config; }>; diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index 24959ff290..48a3b7a05b 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.5-next.1", + "version": "0.5.6", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -87,7 +87,6 @@ "@types/node-forge": "^1.3.0", "@types/stoppable": "^1.1.0", "http-errors": "^2.0.0", - "mock-fs": "^5.2.0", "supertest": "^6.1.3" }, "configSchema": "config.d.ts", diff --git a/packages/backend-app-api/src/alpha/featureDiscoveryServiceFactory.test.ts b/packages/backend-app-api/src/alpha/featureDiscoveryServiceFactory.test.ts index 448f1a8ff7..92f34bb94f 100644 --- a/packages/backend-app-api/src/alpha/featureDiscoveryServiceFactory.test.ts +++ b/packages/backend-app-api/src/alpha/featureDiscoveryServiceFactory.test.ts @@ -14,28 +14,31 @@ * limitations under the License. */ -import mockFs from 'mock-fs'; -import { resolve as resolvePath, dirname } from 'path'; -import { startTestBackend, mockServices } from '@backstage/backend-test-utils'; +import { + startTestBackend, + mockServices, + createMockDirectory, +} from '@backstage/backend-test-utils'; import { featureDiscoveryServiceFactory } from './featureDiscoveryServiceFactory'; -const rootDir = dirname(process.argv[1]); +const mockDir = createMockDirectory(); +process.argv[1] = mockDir.path; + +const pluginApiPath = require.resolve('@backstage/backend-plugin-api'); describe('featureDiscoveryServiceFactory', () => { beforeEach(() => { - mockFs({ - [rootDir]: { - 'package.json': JSON.stringify({ - name: 'example-app', - dependencies: { - 'detected-plugin': '0.0.0', - 'detected-module': '0.0.0', - 'detected-plugin-with-alpha': '0.0.0', - 'detected-library': '0.0.0', - }, - }), - }, - [resolvePath(rootDir, 'node_modules/detected-plugin')]: { + mockDir.setContent({ + 'package.json': JSON.stringify({ + name: 'example-app', + dependencies: { + 'detected-plugin': '0.0.0', + 'detected-module': '0.0.0', + 'detected-plugin-with-alpha': '0.0.0', + 'detected-library': '0.0.0', + }, + }), + 'node_modules/detected-plugin': { 'package.json': JSON.stringify({ name: 'detected-plugin', main: 'index.js', @@ -44,7 +47,7 @@ describe('featureDiscoveryServiceFactory', () => { }, }), 'index.js': ` - const { createBackendPlugin, coreServices } = require('@backstage/backend-plugin-api'); + const { createBackendPlugin, coreServices } = require('${pluginApiPath}'); exports.default = createBackendPlugin({ pluginId: 'detected', register(env) { @@ -58,7 +61,7 @@ describe('featureDiscoveryServiceFactory', () => { }); `, }, - [resolvePath(rootDir, 'node_modules/detected-module')]: { + 'node_modules/detected-module': { 'package.json': JSON.stringify({ name: 'detected-module', main: 'index.js', @@ -67,7 +70,7 @@ describe('featureDiscoveryServiceFactory', () => { }, }), 'index.js': ` - const { createBackendModule, coreServices } = require('@backstage/backend-plugin-api'); + const { createBackendModule, coreServices } = require('${pluginApiPath}'); exports.default = createBackendModule({ pluginId: 'detected', moduleId: 'derp', @@ -82,7 +85,7 @@ describe('featureDiscoveryServiceFactory', () => { }); `, }, - [resolvePath(rootDir, 'node_modules/detected-plugin-with-alpha')]: { + 'node_modules/detected-plugin-with-alpha': { 'package.json': JSON.stringify({ name: 'detected-plugin-with-alpha', main: 'index.js', @@ -101,7 +104,7 @@ describe('featureDiscoveryServiceFactory', () => { }), 'index.js': `exports.default = undefined;`, 'alpha.js': ` - const { createBackendPlugin, coreServices } = require('@backstage/backend-plugin-api'); + const { createBackendPlugin, coreServices } = require('${pluginApiPath}'); exports.default = createBackendPlugin({ pluginId: 'detected-alpha', register(env) { @@ -115,7 +118,7 @@ describe('featureDiscoveryServiceFactory', () => { }); `, }, - [resolvePath(rootDir, 'node_modules/detected-library')]: { + 'node_modules/detected-library': { 'package.json': JSON.stringify({ name: 'detected-library', main: 'index.js', @@ -124,7 +127,7 @@ describe('featureDiscoveryServiceFactory', () => { }, }), 'index.js': ` - const { createServiceFactory, createServiceRef, coreServices } = require('@backstage/backend-plugin-api'); + const { createServiceFactory, createServiceRef, coreServices } = require('${pluginApiPath}'); exports.default = createServiceFactory({ service: createServiceRef({ id: 'test', scope: 'root' }), deps: { logger: coreServices.rootLogger }, @@ -138,10 +141,6 @@ describe('featureDiscoveryServiceFactory', () => { }); }); - afterEach(() => { - mockFs.restore(); - }); - it('should detect plugin and module packages when "all" is specified', async () => { const mock = mockServices.rootLogger.mock({ child: () => mock }); diff --git a/packages/backend-app-api/src/config/config.ts b/packages/backend-app-api/src/config/config.ts index 7367767870..8ecc015b66 100644 --- a/packages/backend-app-api/src/config/config.ts +++ b/packages/backend-app-api/src/config/config.ts @@ -72,6 +72,7 @@ export async function loadBackendConfig(options: { remote?: LoadConfigOptionsRemote; argv: string[]; additionalConfigs?: AppConfig[]; + watch?: boolean; }): Promise<{ config: Config }> { const args = parseArgs(options.argv); @@ -89,30 +90,35 @@ export async function loadBackendConfig(options: { configRoot: paths.targetRoot, configTargets: configTargets, remote: options.remote, - watch: { - onChange(newConfigs) { - console.info( - `Reloaded config from ${newConfigs.map(c => c.context).join(', ')}`, - ); - const configsToMerge = [...newConfigs]; - if (options.additionalConfigs) { - configsToMerge.push(...options.additionalConfigs); - } - config.setConfig(ConfigReader.fromConfigs(configsToMerge)); - }, - stopSignal: new Promise(resolve => { - if (currentCancelFunc) { - currentCancelFunc(); - } - currentCancelFunc = resolve; + watch: + options.watch ?? true + ? { + onChange(newConfigs) { + console.info( + `Reloaded config from ${newConfigs + .map(c => c.context) + .join(', ')}`, + ); + const configsToMerge = [...newConfigs]; + if (options.additionalConfigs) { + configsToMerge.push(...options.additionalConfigs); + } + config.setConfig(ConfigReader.fromConfigs(configsToMerge)); + }, + stopSignal: new Promise(resolve => { + if (currentCancelFunc) { + currentCancelFunc(); + } + currentCancelFunc = resolve; - // TODO(Rugvip): We keep this here for now to avoid breaking the old system - // since this is re-used in backend-common - if (module.hot) { - module.hot.addDisposeHandler(resolve); - } - }), - }, + // TODO(Rugvip): We keep this here for now to avoid breaking the old system + // since this is re-used in backend-common + if (module.hot) { + module.hot.addDisposeHandler(resolve); + } + }), + } + : undefined, }); console.info( `Loaded config from ${appConfigs.map(c => c.context).join(', ')}`, diff --git a/packages/backend-common/CHANGELOG.md b/packages/backend-common/CHANGELOG.md index 05aecf893b..50216d5139 100644 --- a/packages/backend-common/CHANGELOG.md +++ b/packages/backend-common/CHANGELOG.md @@ -1,5 +1,51 @@ # @backstage/backend-common +## 0.19.8 + +### Patch Changes + +- 74491c9602: The `HostDiscovery` export has been deprecated, import it from `@backstage/backend-app-api` instead. +- b95d66d4ea: Properly close write stream when writing temporary archive for processing zip-based `.readTree()` responses. +- b94f32271e: Added the ability to fetch git tags through the `Git` class. This is useful for scaffolder actions that want to take action based on tag versions in a cloned repository +- 0b55f773a7: Removed some unused dependencies +- 4c39e38f1e: Added `/testUtils` entry point, with a utility for mocking resolve package paths as returned by `resolvePackagePath`. +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- a250ad775f: Removed `mock-fs` dev dependency. +- 2a40cd46a8: Adds the optional flag for useRedisSets for the Redis cache to the config. +- 1c3d6fa2b2: The `useHotCleanup` and `useHotMemoize` helpers are now deprecated, since hot module reloads for backend are being phased out. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/backend-dev-utils@0.1.2 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-app-api@0.5.6 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/types@1.1.1 + +## 0.19.8-next.2 + +### Patch Changes + +- 74491c9602: The `HostDiscovery` export has been deprecated, import it from `@backstage/backend-app-api` instead. +- b95d66d4ea: Properly close write stream when writing temporary archive for processing zip-based `.readTree()` responses. +- 0b55f773a7: Removed some unused dependencies +- 4c39e38f1e: Added `/testUtils` entry point, with a utility for mocking resolve package paths as returned by `resolvePackagePath`. +- a250ad775f: Removed `mock-fs` dev dependency. +- Updated dependencies + - @backstage/config-loader@1.5.1-next.1 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-app-api@0.5.6-next.2 + - @backstage/backend-dev-utils@0.1.2-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/integration-aws-node@0.1.7-next.0 + - @backstage/types@1.1.1 + ## 0.19.7-next.1 ### Patch Changes diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index d6ac25326f..f4d430ccbd 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -546,6 +546,7 @@ export function loadBackendConfig(options: { remote?: LoadConfigOptionsRemote; additionalConfigs?: AppConfig[]; argv: string[]; + watch?: boolean; }): Promise<Config>; // @public (undocumented) diff --git a/packages/backend-common/package.json b/packages/backend-common/package.json index 63158fc30e..11facfa7ce 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.7-next.1", + "version": "0.19.8", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { @@ -67,7 +67,7 @@ "@google-cloud/storage": "^6.0.0", "@keyv/memcache": "^1.3.5", "@keyv/redis": "^2.5.3", - "@kubernetes/client-node": "0.18.1", + "@kubernetes/client-node": "0.19.0", "@manypkg/get-packages": "^1.1.3", "@octokit/rest": "^19.0.3", "@types/cors": "^2.8.6", @@ -94,15 +94,10 @@ "logform": "^2.3.2", "luxon": "^3.0.0", "minimatch": "^5.0.0", - "minimist": "^1.2.5", - "morgan": "^1.10.0", "mysql2": "^2.2.5", "node-fetch": "^2.6.7", - "node-forge": "^1.3.1", "pg": "^8.3.0", "raw-body": "^2.4.1", - "selfsigned": "^2.0.0", - "stoppable": "^1.1.0", "tar": "^6.1.12", "uuid": "^8.3.2", "winston": "^3.2.1", @@ -128,12 +123,7 @@ "@types/concat-stream": "^2.0.0", "@types/fs-extra": "^9.0.3", "@types/http-errors": "^2.0.0", - "@types/minimist": "^1.2.0", - "@types/morgan": "^1.9.0", - "@types/node-forge": "^1.3.0", "@types/pg": "^8.6.6", - "@types/recursive-readdir": "^2.2.0", - "@types/stoppable": "^1.1.0", "@types/supertest": "^2.0.8", "@types/tar": "^6.1.1", "@types/webpack-env": "^1.15.2", @@ -143,7 +133,6 @@ "http-errors": "^2.0.0", "msw": "^1.0.0", "mysql2": "^2.2.5", - "recursive-readdir": "^2.2.2", "supertest": "^6.1.3" }, "files": [ diff --git a/packages/backend-common/src/cache/CacheManager.test.ts b/packages/backend-common/src/cache/CacheManager.test.ts index 4578d4fed9..13a4a0d599 100644 --- a/packages/backend-common/src/cache/CacheManager.test.ts +++ b/packages/backend-common/src/cache/CacheManager.test.ts @@ -48,8 +48,10 @@ describe('CacheManager', () => { describe('CacheManager.fromConfig', () => { it('accesses the backend.cache key', () => { const getOptionalString = jest.fn(); + const getOptionalBoolean = jest.fn(); const config = defaultConfig(); config.getOptionalString = getOptionalString; + config.getOptionalBoolean = getOptionalBoolean; CacheManager.fromConfig(config); @@ -57,6 +59,9 @@ describe('CacheManager', () => { expect(getOptionalString.mock.calls[1][0]).toEqual( 'backend.cache.connection', ); + expect(getOptionalBoolean.mock.calls[0][0]).toEqual( + 'backend.cache.useRedisSets', + ); }); it('does not require the backend.cache key', () => { @@ -195,32 +200,61 @@ describe('CacheManager', () => { const mockMemcacheCalls = memcache.mock.calls.splice(-1); expect(mockMemcacheCalls[0][0]).toEqual(expectedHost); }); - }); - it('returns a Redis client when configured', () => { - const redisConnection = 'redis://127.0.0.1:6379'; - const manager = CacheManager.fromConfig( - new ConfigReader({ - backend: { - cache: { - store: 'redis', - connection: redisConnection, + it('returns a Redis client when configured', () => { + const redisConnection = 'redis://127.0.0.1:6379'; + const manager = CacheManager.fromConfig( + new ConfigReader({ + backend: { + cache: { + store: 'redis', + connection: redisConnection, + }, }, - }, - }), - ); - const expectedTtl = 3600; - manager.forPlugin('test').getClient({ defaultTtl: expectedTtl }); + }), + ); + const expectedTtl = 3600; + manager.forPlugin('test').getClient({ defaultTtl: expectedTtl }); - const cache = Keyv as unknown as jest.Mock; - const mockCacheCalls = cache.mock.calls.splice(-1); - expect(mockCacheCalls[0][0]).toMatchObject({ - ttl: expectedTtl, + const cache = Keyv as unknown as jest.Mock; + const mockCacheCalls = cache.mock.calls.splice(-1); + expect(mockCacheCalls[0][0]).toMatchObject({ + ttl: expectedTtl, + }); + expect(mockCacheCalls[0][0].store).toBeInstanceOf(KeyvRedis); + const redis = KeyvRedis as unknown as jest.Mock; + const mockRedisCalls = redis.mock.calls.splice(-1); + expect(mockRedisCalls[0][0]).toEqual(redisConnection); + }); + + it('returns a Redis client when configured with useRedisSets flag', () => { + const redisConnection = 'redis://127.0.0.1:6379'; + const useRedisSets = false; + const manager = CacheManager.fromConfig( + new ConfigReader({ + backend: { + cache: { + store: 'redis', + connection: redisConnection, + useRedisSets: useRedisSets, + }, + }, + }), + ); + const expectedTtl = 3600; + manager.forPlugin('test').getClient({ defaultTtl: expectedTtl }); + + const cache = Keyv as unknown as jest.Mock; + const mockCacheCalls = cache.mock.calls.splice(-1); + expect(mockCacheCalls[0][0]).toMatchObject({ + ttl: expectedTtl, + useRedisSets: useRedisSets, + }); + expect(mockCacheCalls[0][0].store).toBeInstanceOf(KeyvRedis); + const redis = KeyvRedis as unknown as jest.Mock; + const mockRedisCalls = redis.mock.calls.splice(-1); + expect(mockRedisCalls[0][0]).toEqual(redisConnection); }); - expect(mockCacheCalls[0][0].store).toBeInstanceOf(KeyvRedis); - const redis = KeyvRedis as unknown as jest.Mock; - const mockRedisCalls = redis.mock.calls.splice(-1); - expect(mockRedisCalls[0][0]).toEqual(redisConnection); }); describe('connection errors', () => { diff --git a/packages/backend-common/src/cache/CacheManager.ts b/packages/backend-common/src/cache/CacheManager.ts index 9101445b08..efaaf04e3a 100644 --- a/packages/backend-common/src/cache/CacheManager.ts +++ b/packages/backend-common/src/cache/CacheManager.ts @@ -55,6 +55,7 @@ export class CacheManager { private readonly logger: LoggerService; private readonly store: keyof CacheManager['storeFactories']; private readonly connection: string; + private readonly useRedisSets: boolean; private readonly errorHandler: CacheManagerOptions['onError']; /** @@ -72,15 +73,24 @@ export class CacheManager { const store = config.getOptionalString('backend.cache.store') || 'memory'; const connectionString = config.getOptionalString('backend.cache.connection') || ''; + const useRedisSets = + config.getOptionalBoolean('backend.cache.useRedisSets') ?? true; const logger = (options.logger || getRootLogger()).child({ type: 'cacheManager', }); - return new CacheManager(store, connectionString, logger, options.onError); + return new CacheManager( + store, + connectionString, + useRedisSets, + logger, + options.onError, + ); } private constructor( store: string, connectionString: string, + useRedisSets: boolean, logger: LoggerService, errorHandler: CacheManagerOptions['onError'], ) { @@ -90,6 +100,7 @@ export class CacheManager { this.logger = logger; this.store = store as keyof CacheManager['storeFactories']; this.connection = connectionString; + this.useRedisSets = useRedisSets; this.errorHandler = errorHandler; } @@ -143,6 +154,7 @@ export class CacheManager { namespace: pluginId, ttl: defaultTtl, store: new KeyvRedis(this.connection), + useRedisSets: this.useRedisSets, }); } diff --git a/packages/backend-common/src/config.ts b/packages/backend-common/src/config.ts index 53b438de5d..b452d8db70 100644 --- a/packages/backend-common/src/config.ts +++ b/packages/backend-common/src/config.ts @@ -36,6 +36,7 @@ export async function loadBackendConfig(options: { remote?: LoadConfigOptionsRemote; additionalConfigs?: AppConfig[]; argv: string[]; + watch?: boolean; }): Promise<Config> { const secretEnumerator = await createConfigSecretEnumerator({ logger: options.logger, diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index 885ea4ced9..6c9089fd06 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/backend-defaults +## 0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-app-api@0.5.6 + - @backstage/backend-plugin-api@0.6.6 + +## 0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-app-api@0.5.6-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + ## 0.2.5-next.1 ### Patch Changes diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 00472e0a7d..c843bbc412 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.5-next.1", + "version": "0.2.6", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-dev-utils/CHANGELOG.md b/packages/backend-dev-utils/CHANGELOG.md index 3710cf3bd5..f1d1887b78 100644 --- a/packages/backend-dev-utils/CHANGELOG.md +++ b/packages/backend-dev-utils/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/backend-dev-utils +## 0.1.2 + +### Patch Changes + +- afa48341fb: Fix an issue where early IPC responses would be lost. + ## 0.1.2-next.0 ### Patch Changes diff --git a/packages/backend-dev-utils/package.json b/packages/backend-dev-utils/package.json index 8d461b46cf..b6156e622c 100644 --- a/packages/backend-dev-utils/package.json +++ b/packages/backend-dev-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-dev-utils", - "version": "0.1.2-next.0", + "version": "0.1.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-next/CHANGELOG.md b/packages/backend-next/CHANGELOG.md index 8760f6cff2..171d82887c 100644 --- a/packages/backend-next/CHANGELOG.md +++ b/packages/backend-next/CHANGELOG.md @@ -1,5 +1,83 @@ # example-backend-next +## 0.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-nomad-backend@0.1.8 + - @backstage/backend-tasks@0.5.11 + - @backstage/plugin-sonarqube-backend@0.2.8 + - @backstage/plugin-scaffolder-backend@1.18.0 + - @backstage/plugin-playlist-backend@0.3.10 + - @backstage/plugin-techdocs-backend@1.8.0 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/plugin-badges-backend@0.3.3 + - @backstage/plugin-kubernetes-backend@0.13.0 + - @backstage/plugin-jenkins-backend@0.3.0 + - @backstage/plugin-search-backend@1.4.6 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-lighthouse-backend@0.3.3 + - @backstage/plugin-linguist-backend@0.5.3 + - @backstage/plugin-search-backend-module-catalog@0.1.10 + - @backstage/plugin-search-backend-module-explore@0.1.10 + - @backstage/plugin-search-backend-module-techdocs@0.1.10 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/backend-defaults@0.2.6 + - @backstage/plugin-adr-backend@0.4.3 + - @backstage/plugin-app-backend@0.3.54 + - @backstage/plugin-azure-devops-backend@0.4.3 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3 + - @backstage/plugin-devtools-backend@0.2.3 + - @backstage/plugin-entity-feedback-backend@0.2.3 + - @backstage/plugin-permission-backend@0.5.29 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.3 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-proxy-backend@0.4.3 + - @backstage/plugin-todo-backend@0.3.4 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.3 + - @backstage/plugin-permission-common@0.7.9 + +## 0.0.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-nomad-backend@0.1.8-next.2 + - @backstage/plugin-scaffolder-backend@1.18.0-next.2 + - @backstage/plugin-techdocs-backend@1.8.0-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/plugin-catalog-backend@1.14.0-next.2 + - @backstage/plugin-kubernetes-backend@0.12.3-next.2 + - @backstage/plugin-jenkins-backend@0.2.9-next.2 + - @backstage/backend-defaults@0.2.6-next.2 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-adr-backend@0.4.3-next.2 + - @backstage/plugin-app-backend@0.3.54-next.2 + - @backstage/plugin-azure-devops-backend@0.4.3-next.2 + - @backstage/plugin-badges-backend@0.3.3-next.2 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3-next.2 + - @backstage/plugin-devtools-backend@0.2.3-next.2 + - @backstage/plugin-entity-feedback-backend@0.2.3-next.2 + - @backstage/plugin-lighthouse-backend@0.3.3-next.2 + - @backstage/plugin-linguist-backend@0.5.3-next.2 + - @backstage/plugin-permission-backend@0.5.29-next.2 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.1.3-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/plugin-playlist-backend@0.3.10-next.2 + - @backstage/plugin-proxy-backend@0.4.3-next.2 + - @backstage/plugin-search-backend@1.4.6-next.2 + - @backstage/plugin-search-backend-module-catalog@0.1.10-next.2 + - @backstage/plugin-search-backend-module-explore@0.1.10-next.2 + - @backstage/plugin-search-backend-module-techdocs@0.1.10-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/plugin-sonarqube-backend@0.2.8-next.2 + - @backstage/plugin-todo-backend@0.3.4-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.3-next.2 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 0.0.16-next.1 ### Patch Changes diff --git a/packages/backend-next/package.json b/packages/backend-next/package.json index 3e5b4f8057..69aa81a9cb 100644 --- a/packages/backend-next/package.json +++ b/packages/backend-next/package.json @@ -1,6 +1,6 @@ { "name": "example-backend-next", - "version": "0.0.16-next.1", + "version": "0.0.16", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,6 +38,7 @@ "@backstage/plugin-catalog-backend-module-unprocessed": "workspace:^", "@backstage/plugin-devtools-backend": "workspace:^", "@backstage/plugin-entity-feedback-backend": "workspace:^", + "@backstage/plugin-jenkins-backend": "workspace:^", "@backstage/plugin-kubernetes-backend": "workspace:^", "@backstage/plugin-lighthouse-backend": "workspace:^", "@backstage/plugin-linguist-backend": "workspace:^", diff --git a/packages/backend-next/src/index.ts b/packages/backend-next/src/index.ts index 1b4867c05e..bdfbc2c26b 100644 --- a/packages/backend-next/src/index.ts +++ b/packages/backend-next/src/index.ts @@ -29,6 +29,7 @@ backend.add( backend.add(import('@backstage/plugin-catalog-backend/alpha')); backend.add(import('@backstage/plugin-devtools-backend')); backend.add(import('@backstage/plugin-entity-feedback-backend')); +backend.add(import('@backstage/plugin-jenkins-backend')); backend.add(import('@backstage/plugin-kubernetes-backend/alpha')); backend.add(import('@backstage/plugin-lighthouse-backend')); backend.add(import('@backstage/plugin-linguist-backend')); diff --git a/packages/backend-openapi-utils/CHANGELOG.md b/packages/backend-openapi-utils/CHANGELOG.md index 65c508997b..097b0aa089 100644 --- a/packages/backend-openapi-utils/CHANGELOG.md +++ b/packages/backend-openapi-utils/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/backend-openapi-utils +## 0.0.5 + +### Patch Changes + +- 7c83975531: Adds new public utility types for common OpenAPI values, like request and response shapes and parameters available on an endpoint. + + **deprecated** `internal` namespace + The internal namespace will continue to be exported but now uses OpenAPI format for path parameters. You should use the new utility types. + +- Updated dependencies + - @backstage/errors@1.2.3 + +## 0.0.5-next.0 + +### Patch Changes + +- 7c83975531: Adds new public utility types for common OpenAPI values, like request and response shapes and parameters available on an endpoint. + + **deprecated** `internal` namespace + The internal namespace will continue to be exported but now uses OpenAPI format for path parameters. You should use the new utility types. + +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + ## 0.0.4 ### Patch Changes diff --git a/packages/backend-openapi-utils/catalog-info.yaml b/packages/backend-openapi-utils/catalog-info.yaml index ab0a4be883..abb8977130 100644 --- a/packages/backend-openapi-utils/catalog-info.yaml +++ b/packages/backend-openapi-utils/catalog-info.yaml @@ -7,4 +7,4 @@ metadata: spec: lifecycle: experimental type: backstage-node-library - owner: maintainers + owner: openapi-tooling-maintainers diff --git a/packages/backend-openapi-utils/package.json b/packages/backend-openapi-utils/package.json index 8fa83bd584..04dc3f19f2 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.0.4", + "version": "0.0.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/backend-plugin-api/CHANGELOG.md b/packages/backend-plugin-api/CHANGELOG.md index ce19f9a798..63600bed9f 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/backend-plugin-api +## 0.6.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## 0.6.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 0.6.5-next.1 ### Patch Changes diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 8374a002b8..2706b1bdaf 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.5-next.1", + "version": "0.6.6", "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 6e1499eb1b..526bc6c802 100644 --- a/packages/backend-plugin-manager/CHANGELOG.md +++ b/packages/backend-plugin-manager/CHANGELOG.md @@ -1,5 +1,51 @@ # @backstage/backend-plugin-manager +## 0.0.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/plugin-events-backend@0.2.15 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/cli-node@0.1.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## 0.0.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/plugin-catalog-backend@1.14.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-events-backend@0.2.15-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/cli-node@0.1.5-next.1 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.15-next.2 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 0.0.2-next.1 ### Patch Changes diff --git a/packages/backend-plugin-manager/package.json b/packages/backend-plugin-manager/package.json index 33675dda1f..20446196cf 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.2-next.1", + "version": "0.0.2", "private": true, "main": "src/index.ts", "types": "src/index.ts", 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 f356163dea..4aabd2c072 100644 --- a/packages/backend-plugin-manager/src/manager/plugin-manager.test.ts +++ b/packages/backend-plugin-manager/src/manager/plugin-manager.test.ts @@ -452,16 +452,13 @@ describe('backend-plugin-manager', () => { findPaths(__dirname).resolveTargetRoot('package.json'), ), 'dynamic-plugins-root': {}, + 'dynamic-plugins-root/a-dynamic-plugin': ctx => + ctx.symlink(otherMockDir.resolve('a-dynamic-plugin')), }); otherMockDir.setContent({ 'a-dynamic-plugin': {}, }); - fs.symlinkSync( - otherMockDir.resolve('a-dynamic-plugin'), - mockDir.resolve('dynamic-plugins-root/a-dynamic-plugin'), - ); - const fromConfigSpier = jest.spyOn(PluginManager, 'fromConfig'); const applyConfigSpier = jest .spyOn(PluginScanner.prototype as any, 'applyConfig') diff --git a/packages/backend-plugin-manager/src/scanner/plugin-scanner.test.ts b/packages/backend-plugin-manager/src/scanner/plugin-scanner.test.ts index 04ce69ec98..d4ab8940c9 100644 --- a/packages/backend-plugin-manager/src/scanner/plugin-scanner.test.ts +++ b/packages/backend-plugin-manager/src/scanner/plugin-scanner.test.ts @@ -19,10 +19,12 @@ import { JsonObject } from '@backstage/types'; import { Logs, MockedLogger } from '../__testUtils__/testUtils'; import { ConfigReader } from '@backstage/config'; import path from 'path'; -import fs from 'fs'; import * as url from 'url'; import { ScannedPluginPackage } from './types'; -import { createMockDirectory } from '@backstage/backend-test-utils'; +import { + MockDirectoryContent, + createMockDirectory, +} from '@backstage/backend-test-utils'; const mockDir = createMockDirectory(); @@ -233,8 +235,7 @@ Please add '${mockDir.resolve( type TestCase = { name: string; preferAlpha?: boolean; - fileSystem?: any; - symlinks?: { source: string; target: string }[]; + fileSystem?: MockDirectoryContent; expectedLogs?: Logs; expectedPluginPackages?: ScannedPluginPackage[]; expectedError?: string; @@ -286,7 +287,12 @@ Please add '${mockDir.resolve( name: 'backend plugin found in symlink', fileSystem: { backstageRoot: { - 'dist-dynamic': {}, + 'dist-dynamic': { + 'test-backend-plugin': ctx => + ctx.symlink( + mockDir.resolve('somewhere-else/test-backend-plugin-target'), + ), + }, }, 'somewhere-else': { 'test-backend-plugin-target': { @@ -299,16 +305,6 @@ Please add '${mockDir.resolve( }, }, }, - symlinks: [ - { - source: mockDir.resolve( - 'backstageRoot/dist-dynamic/test-backend-plugin', - ), - target: mockDir.resolve( - 'somewhere-else/test-backend-plugin-target', - ), - }, - ], expectedPluginPackages: [ { location: url.pathToFileURL( @@ -347,22 +343,17 @@ Please add '${mockDir.resolve( name: 'ignored folder child symlink: target is not a directory', fileSystem: { backstageRoot: { - 'dist-dynamic': {}, + 'dist-dynamic': { + 'test-backend-plugin': ctx => + ctx.symlink( + mockDir.resolve('somewhere-else/test-backend-plugin-target'), + ), + }, }, 'somewhere-else': { 'test-backend-plugin-target': '', }, }, - symlinks: [ - { - source: mockDir.resolve( - 'backstageRoot/dist-dynamic/test-backend-plugin', - ), - target: mockDir.resolve( - 'somewhere-else/test-backend-plugin-target', - ), - }, - ], expectedPluginPackages: [], expectedLogs: { infos: [ @@ -637,11 +628,6 @@ Please add '${mockDir.resolve( if (tc.fileSystem) { mockDir.setContent(tc.fileSystem); } - if (tc.symlinks) { - for (const { source, target } of tc.symlinks) { - fs.symlinkSync(target, source); - } - } if (tc.expectedError) { /* eslint-disable-next-line jest/no-conditional-expect */ expect(toTest).toThrow(tc.expectedError); diff --git a/packages/backend-tasks/CHANGELOG.md b/packages/backend-tasks/CHANGELOG.md index bd1284aaf5..2a209521f1 100644 --- a/packages/backend-tasks/CHANGELOG.md +++ b/packages/backend-tasks/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/backend-tasks +## 0.5.11 + +### Patch Changes + +- 5db102bfdf: Instrument `backend-tasks` with some counters and histograms for duration. + + `backend_tasks.task.runs.count`: Counter with the total number of times a task has been run. + `backend_tasks.task.runs.duration`: Histogram with the run durations for each task. + + Both these metrics have come with `result` `taskId` and `scope` labels for finer grained grouping. + +- ddd76ac98d: Fix bug where backend tasks that are defined with HumanDuration are immediately triggered on application startup +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.5.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + ## 0.5.10-next.1 ### Patch Changes diff --git a/packages/backend-tasks/package.json b/packages/backend-tasks/package.json index 9a42aab169..c386654a24 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.10-next.1", + "version": "0.5.11", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-tasks/src/tasks/TaskWorker.test.ts b/packages/backend-tasks/src/tasks/TaskWorker.test.ts index efad4e649b..45eb7d1003 100644 --- a/packages/backend-tasks/src/tasks/TaskWorker.test.ts +++ b/packages/backend-tasks/src/tasks/TaskWorker.test.ts @@ -371,7 +371,14 @@ describe('TaskWorker', () => { await worker.persistTask(settings3); const row3 = (await knex<DbTasksRow>(DB_TASKS_TABLE))[0]; - expect(row3.next_run_start_at).toStrictEqual(row2.next_run_start_at); + // The new timestamp can basically be 0 or a minute depending on how the + // initialDelayDuration falls right on a cron boundary. This kinda + // contrived check removes a test flakiness based on wall clock time. + expect( + Math.abs( + +new Date(row3.next_run_start_at) - +new Date(row2.next_run_start_at), + ), + ).toBeLessThanOrEqual(60_000); await knex.destroy(); }, diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index 5bd1c6d498..8cb13b24c5 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/backend-test-utils +## 0.2.7 + +### Patch Changes + +- a250ad775f: Added `createMockDirectory()` to help out with file system mocking in tests. +- 5ddc03813e: Remove third type parameter used for `MockInstance`, in order to be compatible with older versions of `@types/jest`. +- 74491c9602: Updated to import `HostDiscovery` from `@backstage/backend-app-api`. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-app-api@0.5.6 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.2.7-next.2 + +### Patch Changes + +- a250ad775f: Added `createMockDirectory()` to help out with file system mocking in tests. +- 74491c9602: Updated to import `HostDiscovery` from `@backstage/backend-app-api`. +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-app-api@0.5.6-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + ## 0.2.6-next.1 ### Patch Changes diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md index a477f70298..ac012e2f69 100644 --- a/packages/backend-test-utils/api-report.md +++ b/packages/backend-test-utils/api-report.md @@ -54,9 +54,24 @@ export interface MockDirectory { // @public export type MockDirectoryContent = { - [name in string]: MockDirectoryContent | string | Buffer; + [name in string]: + | MockDirectoryContent + | string + | Buffer + | MockDirectoryContentCallback; }; +// @public +export type MockDirectoryContentCallback = ( + ctx: MockDirectoryContentCallbackContext, +) => void; + +// @public +export interface MockDirectoryContentCallbackContext { + path: string; + symlink(target: string): void; +} + // @public export interface MockDirectoryContentOptions { path?: string; diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 691f0a921b..1094de8ced 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.6-next.1", + "version": "0.2.7", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/backend-test-utils/src/filesystem/MockDirectory.test.ts b/packages/backend-test-utils/src/filesystem/MockDirectory.test.ts index 8040d03f44..fd22f09432 100644 --- a/packages/backend-test-utils/src/filesystem/MockDirectory.test.ts +++ b/packages/backend-test-utils/src/filesystem/MockDirectory.test.ts @@ -119,6 +119,20 @@ describe('createMockDirectory', () => { }); }); + it('should be able to use callback for more detailed file system operations', () => { + mockDir.setContent({ + 'a.txt': 'a', + 'b.txt': ctx => ctx.symlink('./a.txt'), + 'c.txt': ctx => fs.copyFileSync(mockDir.resolve('a.txt'), ctx.path), + }); + + expect(mockDir.content()).toEqual({ + 'a.txt': 'a', + 'b.txt': 'a', + 'c.txt': 'a', + }); + }); + it('should read content from sub dirs', () => { mockDir.setContent({ 'a.txt': 'a', diff --git a/packages/backend-test-utils/src/filesystem/MockDirectory.ts b/packages/backend-test-utils/src/filesystem/MockDirectory.ts index 61eb4fce24..b066b9acd5 100644 --- a/packages/backend-test-utils/src/filesystem/MockDirectory.ts +++ b/packages/backend-test-utils/src/filesystem/MockDirectory.ts @@ -30,6 +30,28 @@ import { const tmpdirMarker = Symbol('os-tmpdir-mock'); +/** + * A context that allows for more advanced file system operations when writing mock directory content. + * + * @public + */ +export interface MockDirectoryContentCallbackContext { + /** Absolute path to the location of this piece of content on the filesystem */ + path: string; + + /** Creates a symbolic link at the current location */ + symlink(target: string): void; +} + +/** + * A callback that allows for more advanced file system operations when writing mock directory content. + * + * @public + */ +export type MockDirectoryContentCallback = ( + ctx: MockDirectoryContentCallbackContext, +) => void; + /** * The content of a mock directory represented by a nested object structure. * @@ -54,7 +76,11 @@ const tmpdirMarker = Symbol('os-tmpdir-mock'); * @public */ export type MockDirectoryContent = { - [name in string]: MockDirectoryContent | string | Buffer; + [name in string]: + | MockDirectoryContent + | string + | Buffer + | MockDirectoryContentCallback; }; /** @@ -178,6 +204,11 @@ type MockEntry = | { type: 'dir'; path: string; + } + | { + type: 'callback'; + path: string; + callback: MockDirectoryContentCallback; }; /** @internal */ @@ -214,10 +245,18 @@ class MockDirectoryImpl { } if (entry.type === 'dir') { - fs.ensureDirSync(fullPath, { mode: 0o777 }); + fs.ensureDirSync(fullPath); } else if (entry.type === 'file') { - fs.ensureDirSync(dirname(fullPath), { mode: 0o777 }); - fs.writeFileSync(fullPath, entry.content, { mode: 0o666 }); + fs.ensureDirSync(dirname(fullPath)); + fs.writeFileSync(fullPath, entry.content); + } else if (entry.type === 'callback') { + fs.ensureDirSync(dirname(fullPath)); + entry.callback({ + path: fullPath, + symlink(target: string) { + fs.symlinkSync(target, fullPath); + }, + }); } } } @@ -287,6 +326,8 @@ class MockDirectoryImpl { }); } else if (node instanceof Buffer) { entries.push({ type: 'file', path, content: node }); + } else if (typeof node === 'function') { + entries.push({ type: 'callback', path, callback: node }); } else { entries.push({ type: 'dir', path }); for (const [name, child] of Object.entries(node)) { diff --git a/packages/backend-test-utils/src/filesystem/index.ts b/packages/backend-test-utils/src/filesystem/index.ts index 0a4d8c7d00..e18b0b55b8 100644 --- a/packages/backend-test-utils/src/filesystem/index.ts +++ b/packages/backend-test-utils/src/filesystem/index.ts @@ -20,4 +20,6 @@ export { type MockDirectoryOptions, type MockDirectoryContent, type MockDirectoryContentOptions, + type MockDirectoryContentCallback, + type MockDirectoryContentCallbackContext, } from './MockDirectory'; diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index 07105a0417..9eb282bb1c 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,123 @@ # example-backend +## 0.2.88 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-nomad-backend@0.1.8 + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-scaffolder-backend@1.18.0 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.9 + - @backstage/integration@1.7.1 + - @backstage/plugin-playlist-backend@0.3.10 + - @backstage/plugin-techdocs-backend@1.8.0 + - @backstage/plugin-auth-backend@0.19.3 + - @backstage/plugin-rollbar-backend@0.1.51 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/plugin-graphql-backend@0.2.0 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-badges-backend@0.3.3 + - @backstage/plugin-tech-insights-backend@0.5.20 + - @backstage/plugin-kubernetes-backend@0.13.0 + - @backstage/plugin-jenkins-backend@0.3.0 + - @backstage/plugin-code-coverage-backend@0.2.20 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.23 + - @backstage/plugin-search-backend@1.4.6 + - example-app@0.2.88 + - @backstage/plugin-lighthouse-backend@0.3.3 + - @backstage/plugin-linguist-backend@0.5.3 + - @backstage/plugin-search-backend-module-catalog@0.1.10 + - @backstage/plugin-search-backend-module-explore@0.1.10 + - @backstage/plugin-search-backend-module-techdocs@0.1.10 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/plugin-tech-insights-node@0.4.12 + - @backstage/plugin-adr-backend@0.4.3 + - @backstage/plugin-app-backend@0.3.54 + - @backstage/plugin-azure-devops-backend@0.4.3 + - @backstage/plugin-azure-sites-backend@0.1.16 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3 + - @backstage/plugin-devtools-backend@0.2.3 + - @backstage/plugin-entity-feedback-backend@0.2.3 + - @backstage/plugin-events-backend@0.2.15 + - @backstage/plugin-explore-backend@0.0.16 + - @backstage/plugin-kafka-backend@0.3.3 + - @backstage/plugin-permission-backend@0.5.29 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-proxy-backend@0.4.3 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.7 + - @backstage/plugin-search-backend-module-pg@0.5.15 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.38 + - @backstage/plugin-todo-backend@0.3.4 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.3 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## 0.2.88-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-nomad-backend@0.1.8-next.2 + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-scaffolder-backend@1.18.0-next.2 + - @backstage/plugin-techdocs-backend@1.8.0-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/plugin-catalog-backend@1.14.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/plugin-kubernetes-backend@0.12.3-next.2 + - @backstage/plugin-jenkins-backend@0.2.9-next.2 + - @backstage/plugin-auth-backend@0.19.3-next.2 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-adr-backend@0.4.3-next.2 + - @backstage/plugin-app-backend@0.3.54-next.2 + - @backstage/plugin-azure-devops-backend@0.4.3-next.2 + - @backstage/plugin-azure-sites-backend@0.1.16-next.2 + - @backstage/plugin-badges-backend@0.3.3-next.2 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/plugin-code-coverage-backend@0.2.20-next.2 + - @backstage/plugin-devtools-backend@0.2.3-next.2 + - @backstage/plugin-entity-feedback-backend@0.2.3-next.2 + - @backstage/plugin-events-backend@0.2.15-next.2 + - @backstage/plugin-explore-backend@0.0.16-next.2 + - @backstage/plugin-graphql-backend@0.1.44-next.2 + - @backstage/plugin-kafka-backend@0.3.3-next.2 + - @backstage/plugin-lighthouse-backend@0.3.3-next.2 + - @backstage/plugin-linguist-backend@0.5.3-next.2 + - @backstage/plugin-permission-backend@0.5.29-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/plugin-playlist-backend@0.3.10-next.2 + - @backstage/plugin-proxy-backend@0.4.3-next.2 + - @backstage/plugin-rollbar-backend@0.1.51-next.2 + - @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.2.7-next.2 + - @backstage/plugin-scaffolder-backend-module-rails@0.4.23-next.2 + - @backstage/plugin-search-backend@1.4.6-next.2 + - @backstage/plugin-search-backend-module-catalog@0.1.10-next.2 + - @backstage/plugin-search-backend-module-elasticsearch@1.3.9-next.2 + - @backstage/plugin-search-backend-module-explore@0.1.10-next.2 + - @backstage/plugin-search-backend-module-pg@0.5.15-next.2 + - @backstage/plugin-search-backend-module-techdocs@0.1.10-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/plugin-tech-insights-backend@0.5.20-next.2 + - @backstage/plugin-tech-insights-backend-module-jsonfc@0.1.38-next.2 + - @backstage/plugin-tech-insights-node@0.4.12-next.2 + - @backstage/plugin-todo-backend@0.3.4-next.2 + - example-app@0.2.88-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.3.3-next.2 + - @backstage/plugin-events-node@0.2.15-next.2 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 0.2.88-next.1 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 8519a5ed71..76ef8dfb2d 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.2.88-next.1", + "version": "0.2.88", "main": "dist/index.cjs.js", "types": "src/index.ts", "license": "Apache-2.0", @@ -81,7 +81,7 @@ "@gitbeaker/node": "^35.1.0", "@octokit/rest": "^19.0.3", "@opentelemetry/api": "^1.4.1", - "@opentelemetry/exporter-prometheus": "^0.39.1", + "@opentelemetry/exporter-prometheus": "^0.44.0", "@opentelemetry/sdk-metrics": "^1.13.0", "azure-devops-node-api": "^11.0.1", "better-sqlite3": "^8.0.0", diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index b22f7d2983..8df01b050e 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -55,7 +55,6 @@ import search from './plugins/search'; import techdocs from './plugins/techdocs'; import techInsights from './plugins/techInsights'; import todo from './plugins/todo'; -import graphql from './plugins/graphql'; import app from './plugins/app'; import badges from './plugins/badges'; import jenkins from './plugins/jenkins'; @@ -155,7 +154,6 @@ async function main() { const todoEnv = useHotMemoize(module, () => createEnv('todo')); const kubernetesEnv = useHotMemoize(module, () => createEnv('kubernetes')); const kafkaEnv = useHotMemoize(module, () => createEnv('kafka')); - const graphqlEnv = useHotMemoize(module, () => createEnv('graphql')); const appEnv = useHotMemoize(module, () => createEnv('app')); const badgesEnv = useHotMemoize(module, () => createEnv('badges')); const jenkinsEnv = useHotMemoize(module, () => createEnv('jenkins')); @@ -190,7 +188,6 @@ async function main() { apiRouter.use('/kubernetes', await kubernetes(kubernetesEnv)); apiRouter.use('/kafka', await kafka(kafkaEnv)); apiRouter.use('/proxy', await proxy(proxyEnv)); - apiRouter.use('/graphql', await graphql(graphqlEnv)); apiRouter.use('/badges', await badges(badgesEnv)); apiRouter.use('/jenkins', await jenkins(jenkinsEnv)); apiRouter.use('/permission', await permission(permissionEnv)); diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index 06231c6c7a..b3c1aeb56f 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/catalog-client +## 1.4.5 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## 1.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + ## 1.4.4 ### Patch Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index b7fcdb549e..28cbe0879a 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.4", + "version": "1.4.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/catalog-model/CHANGELOG.md b/packages/catalog-model/CHANGELOG.md index 3972ea9761..6f374cdbc5 100644 --- a/packages/catalog-model/CHANGELOG.md +++ b/packages/catalog-model/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/catalog-model +## 1.4.3 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## 1.4.3-next.0 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + - @backstage/types@1.1.1 + ## 1.4.2 ### Patch Changes diff --git a/packages/catalog-model/package.json b/packages/catalog-model/package.json index cb6dbb6f31..746ef803ff 100644 --- a/packages/catalog-model/package.json +++ b/packages/catalog-model/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/catalog-model", "description": "Types and validators that help describe the model of a Backstage Catalog", - "version": "1.4.2", + "version": "1.4.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,13 +45,10 @@ "clean": "backstage-cli package clean" }, "dependencies": { - "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/types": "workspace:^", "ajv": "^8.10.0", - "json-schema": "^0.4.0", - "lodash": "^4.17.21", - "uuid": "^8.0.0" + "lodash": "^4.17.21" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/packages/cli-common/CHANGELOG.md b/packages/cli-common/CHANGELOG.md index 30b9670251..70e98da8dd 100644 --- a/packages/cli-common/CHANGELOG.md +++ b/packages/cli-common/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/cli-common +## 0.1.13 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. + ## 0.1.13-next.0 ### Patch Changes diff --git a/packages/cli-common/package.json b/packages/cli-common/package.json index 8aed6881e2..b8bd27cef9 100644 --- a/packages/cli-common/package.json +++ b/packages/cli-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli-common", "description": "Common functionality used by cli, backend, and create-app", - "version": "0.1.13-next.0", + "version": "0.1.13", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/cli-node/CHANGELOG.md b/packages/cli-node/CHANGELOG.md index ab16a5d036..d5dcb6e976 100644 --- a/packages/cli-node/CHANGELOG.md +++ b/packages/cli-node/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/cli-node +## 0.1.5 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/types@1.1.1 + +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/types@1.1.1 + ## 0.1.5-next.0 ### Patch Changes diff --git a/packages/cli-node/package.json b/packages/cli-node/package.json index a1062c2783..1d1158c818 100644 --- a/packages/cli-node/package.json +++ b/packages/cli-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/cli-node", "description": "Node.js library for Backstage CLIs", - "version": "0.1.5-next.0", + "version": "0.1.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index d9d7c426e3..65d0b752e7 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,100 @@ # @backstage/cli +## 0.23.0 + +### Minor Changes + +- 8defbd5434: Update typescript-eslint to 6.7.x, adding compatibility with TypeScript 5.2. + + This includes a major update on typescript-eslint, you can see the details in the [release notes](https://typescript-eslint.io/blog/announcing-typescript-eslint-v6/). + +- 7077dbf131: **BREAKING** The new backend start command that used to be enabled by setting `EXPERIMENTAL_BACKEND_START` is now the default. To revert to the old behavior set `LEGACY_BACKEND_START`, which is recommended if you haven't migrated to the new backend system. + + This new command is no longer based on Webpack, but instead uses Node.js loaders to transpile on the fly. Rather than hot reloading modules the entire backend is now restarted on change, but the SQLite database state is still maintained across restarts via a parent process. + +### Patch Changes + +- 9468a67b92: In frontend builds and tests `process.env.HAS_REACT_DOM_CLIENT` will now be defined if `react-dom/client` is present, i.e. if using React 18. This allows for conditional imports of `react-dom/client`. +- 68158034e8: Fix for the new backend `start` command to make it work on Windows. +- 4f16e60e6d: Request slightly smaller pages of data from GitHub +- 21cd3b1b24: Added a template for creating `node-library` packages with `yarn new`. +- d0f26cfa4f: Fixed an issue where the new backend start command would not gracefully shut down the backend process on Windows. +- 1ea20b0be5: Updated dependency `@typescript-eslint/eslint-plugin` to `6.7.5`. +- 2ef6522552: Support for the `.icon.svg` extension has been deprecated and will be removed in the future. The implementation of this extension is too tied to a particular version of MUI and the SVGO, and it makes it harder to evolve the build system. We may introduce the ability to reintroduce this kind of functionality in the future through configuration for use in internal plugins, but for now we're forced to remove it. + + To migrate existing code, rename the `.icon.svg` file to `.tsx` and replace the `<svg>` element with `<SvgIcon>` from MUI and add necessary imports. For example: + + ```tsx + import React from 'react'; + import SvgIcon from '@material-ui/core/SvgIcon'; + import { IconComponent } from '@backstage/core-plugin-api'; + + export const CodeSceneIcon = (props: SvgIconProps) => ( + <SvgIcon {...props}> + <g> + <path d="..." /> + </g> + </SvgIcon> + ); + ``` + +- b9ec93430e: The scaffolder-module template now recommends usage of `createMockDirectory` instead of `mock-fs`. +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- 425203f898: Fixed recursive reloading issues of the backend, caused by unwanted watched files. +- 3ef18f8c06: Explicitly set `exports: 'named'` for CJS builds, ensuring that they have e.g. `exports["default"] = catalogPlugin;` +- 7187f2953e: The experimental package discovery will now always use the package name for include and exclude filtering, rather than the full module id. Entries pointing to a subpath export will now instead have an `export` field specifying the subpath that the import is from. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.1.5 + - @backstage/config@1.1.1 + - @backstage/eslint-plugin@0.1.3 + - @backstage/release-manifests@0.0.10 + - @backstage/types@1.1.1 + +## 0.23.0-next.2 + +### Minor Changes + +- 8defbd5434: Update typescript-eslint to 6.7.x, adding compatibility with TypeScript 5.2. + + This includes a major update on typescript-eslint, you can see the details in the [release notes](https://typescript-eslint.io/blog/announcing-typescript-eslint-v6/). + +### Patch Changes + +- 2ef6522552: Support for the `.icon.svg` extension has been deprecated and will be removed in the future. The implementation of this extension is too tied to a particular version of MUI and the SVGO, and it makes it harder to evolve the build system. We may introduce the ability to reintroduce this kind of functionality in the future through configuration for use in internal plugins, but for now we're forced to remove it. + + To migrate existing code, rename the `.icon.svg` file to `.tsx` and replace the `<svg>` element with `<SvgIcon>` from MUI and add necessary imports. For example: + + ```tsx + import React from 'react'; + import SvgIcon from '@material-ui/core/SvgIcon'; + import { IconComponent } from '@backstage/core-plugin-api'; + + export const CodeSceneIcon = (props: SvgIconProps) => ( + <SvgIcon {...props}> + <g> + <path d="..." /> + </g> + </SvgIcon> + ); + ``` + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/config-loader@1.5.1-next.1 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/cli-node@0.1.5-next.1 + - @backstage/config@1.1.1-next.0 + - @backstage/eslint-plugin@0.1.3 + - @backstage/release-manifests@0.0.10 + - @backstage/types@1.1.1 + ## 0.23.0-next.1 ### Patch Changes @@ -21,7 +116,7 @@ ### Minor Changes -- 7077dbf131: The new backend start command that used to be enabled by setting `EXPERIMENTAL_BACKEND_START` is now the default. To revert to the old behavior, set `LEGACY_BACKEND_START` instead. +- 7077dbf131: **BREAKING** The new backend start command that used to be enabled by setting `EXPERIMENTAL_BACKEND_START` is now the default. To revert to the old behavior set `LEGACY_BACKEND_START`, which is recommended if you haven't migrated to the new backend system. This new command is no longer based on Webpack, but instead uses Node.js loaders to transpile on the fly. Rather than hot reloading modules the entire backend is now restarted on change, but the SQLite database state is still maintained across restarts via a parent process. diff --git a/packages/cli/asset-types/asset-types.d.ts b/packages/cli/asset-types/asset-types.d.ts index a1c053dc54..2d288fd0e3 100644 --- a/packages/cli/asset-types/asset-types.d.ts +++ b/packages/cli/asset-types/asset-types.d.ts @@ -60,10 +60,40 @@ declare module '*.yaml' { export default src; } +/** + * @deprecated support for .icon.svg extensions are being removed, inline the SVG elements in a MUI SvgIcon instead. + * @example + * ```tsx + * import SvgIcon from '@material-ui/core/SvgIcon'; + * + * const MyIcon = () => ( + * <SvgIcon> + * <g> + * <path d="..." /> + * </g> + * </SvgIcon> + * ) + * ``` + */ declare module '*.icon.svg' { import { ComponentType } from 'react'; import { SvgIconProps } from '@material-ui/core'; + /** + * @deprecated support for .icon.svg extensions are being removed, inline the SVG elements in a MUI SvgIcon instead. + * @example + * ```tsx + * import SvgIcon from '@material-ui/core/SvgIcon'; + * + * const MyIcon = () => ( + * <SvgIcon> + * <g> + * <path d="..." /> + * </g> + * </SvgIcon> + * ) + * ``` + */ const Icon: ComponentType<SvgIconProps>; export default Icon; } diff --git a/packages/cli/config/jest.js b/packages/cli/config/jest.js index 1756b37db2..4a8bf9694f 100644 --- a/packages/cli/config/jest.js +++ b/packages/cli/config/jest.js @@ -24,6 +24,13 @@ const envOptions = { oldTests: Boolean(process.env.BACKSTAGE_OLD_TESTS), }; +try { + require.resolve('react-dom/client'); + process.env.HAS_REACT_DOM_CLIENT = true; +} catch { + /* ignored */ +} + const transformIgnorePattern = [ '@material-ui', 'ajv', diff --git a/packages/cli/package.json b/packages/cli/package.json index ee1eb52a2c..419b02d929 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.23.0-next.1", + "version": "0.23.0", "publishConfig": { "access": "public" }, @@ -66,8 +66,8 @@ "@swc/jest": "^0.2.22", "@types/jest": "^29.0.0", "@types/webpack-env": "^1.15.2", - "@typescript-eslint/eslint-plugin": "^5.9.0", - "@typescript-eslint/parser": "^5.9.0", + "@typescript-eslint/eslint-plugin": "6.7.5", + "@typescript-eslint/parser": "^6.7.2", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "^3.0.0-rc.4", "bfj": "^7.0.2", @@ -158,7 +158,6 @@ "@types/http-proxy": "^1.17.4", "@types/inquirer": "^8.1.3", "@types/minimatch": "^5.0.0", - "@types/mock-fs": "^4.13.0", "@types/node": "^18.17.8", "@types/npm-packlist": "^3.0.0", "@types/recursive-readdir": "^2.2.0", @@ -169,7 +168,6 @@ "@types/terser-webpack-plugin": "^5.0.4", "@types/yarnpkg__lockfile": "^1.1.4", "del": "^7.0.0", - "mock-fs": "^5.2.0", "msw": "^1.0.0", "nodemon": "^3.0.1", "ts-node": "^10.0.0", diff --git a/packages/cli/src/commands/create-plugin/createPlugin.test.ts b/packages/cli/src/commands/create-plugin/createPlugin.test.ts index aa59f94fb4..84af6ebf69 100644 --- a/packages/cli/src/commands/create-plugin/createPlugin.test.ts +++ b/packages/cli/src/commands/create-plugin/createPlugin.test.ts @@ -16,23 +16,21 @@ import fs from 'fs-extra'; import path from 'path'; -import mockFs from 'mock-fs'; import { movePlugin } from './createPlugin'; +import { createMockDirectory } from '@backstage/backend-test-utils'; const id = 'testPluginMock'; describe('createPlugin', () => { - afterEach(() => { - mockFs.restore(); - }); + const mockDir = createMockDirectory(); describe('movePlugin', () => { it('should move the temporary plugin directory to its final place', async () => { - mockFs({ + mockDir.setContent({ [id]: {}, }); - const tempDir = id; - const pluginDir = path.join('test-temp', 'plugins', id); + const tempDir = mockDir.resolve(id); + const pluginDir = mockDir.resolve('test-temp/plugins', id); await movePlugin(tempDir, pluginDir, id); await expect(fs.pathExists(pluginDir)).resolves.toBe(true); diff --git a/packages/cli/src/commands/onboard/discovery/providers/github/GithubDiscoveryProvider.ts b/packages/cli/src/commands/onboard/discovery/providers/github/GithubDiscoveryProvider.ts index d5a3dc4a77..a24756edd7 100644 --- a/packages/cli/src/commands/onboard/discovery/providers/github/GithubDiscoveryProvider.ts +++ b/packages/cli/src/commands/onboard/discovery/providers/github/GithubDiscoveryProvider.ts @@ -113,7 +113,7 @@ export class GithubDiscoveryProvider implements Provider { const query = `query repositories($org: String!, $cursor: String) { repositoryOwner(login: $org) { login - repositories(first: 100, after: $cursor) { + repositories(first: 50, after: $cursor) { nodes { name url diff --git a/packages/cli/src/commands/versions/bump.test.ts b/packages/cli/src/commands/versions/bump.test.ts index 7af6c6160b..d00b4ce8da 100644 --- a/packages/cli/src/commands/versions/bump.test.ts +++ b/packages/cli/src/commands/versions/bump.test.ts @@ -15,10 +15,7 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; import { Command } from 'commander'; -import { resolve as resolvePath } from 'path'; -import { paths } from '../../lib/paths'; import * as runObj from '../../lib/run'; import bump, { bumpBackstageJsonVersion, createVersionFinder } from './bump'; import { @@ -30,6 +27,10 @@ import { setupServer } from 'msw/node'; import { rest } from 'msw'; import { NotFoundError } from '@backstage/errors'; import { Lockfile } from '../../lib/versioning/Lockfile'; +import { + MockDirectory, + createMockDirectory, +} from '@backstage/backend-test-utils'; // Avoid mutating the global http(s) agent used in other tests jest.mock('global-agent/bootstrap', () => {}); @@ -56,6 +57,19 @@ jest.mock('ora', () => ({ }, })); +let mockDir: MockDirectory; + +jest.mock('../../lib/paths', () => ({ + paths: { + resolveTargetRoot(filename: string) { + return mockDir.resolve(filename); + }, + get targetDir() { + return mockDir.path; + }, + }, +})); + jest.mock('../../lib/run', () => { return { run: jest.fn(), @@ -117,7 +131,17 @@ const lockfileMockResult = `${HEADER} version "1.0.0" `; +// Avoid flakes by comparing sorted log lines. File system access is async, which leads to the log line order being indeterministic +const expectLogsToMatch = ( + recievedLogs: String[], + expected: String[], +): void => { + expect(recievedLogs.filter(Boolean).sort()).toEqual(expected.sort()); +}; + describe('bump', () => { + mockDir = createMockDirectory(); + beforeEach(() => { mockFetchPackageInfo.mockImplementation(async name => ({ name: name, @@ -128,7 +152,6 @@ describe('bump', () => { }); afterEach(() => { - mockFs.restore(); jest.resetAllMocks(); }); @@ -136,31 +159,34 @@ describe('bump', () => { setupRequestMockHandlers(worker); it('should bump backstage dependencies', async () => { - mockFs({ - '/yarn.lock': lockfileMock, - '/package.json': JSON.stringify({ + mockDir.setContent({ + 'yarn.lock': lockfileMock, + 'package.json': JSON.stringify({ workspaces: { packages: ['packages/*'], }, }), - '/packages/a/package.json': JSON.stringify({ - name: 'a', - dependencies: { - '@backstage/core': '^1.0.5', + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '^1.0.5', + }, + }), }, - }), - '/packages/b/package.json': JSON.stringify({ - name: 'b', - dependencies: { - '@backstage/core': '^1.0.3', - '@backstage/theme': '^1.0.0', + b: { + 'package.json': JSON.stringify({ + name: 'b', + dependencies: { + '@backstage/core': '^1.0.3', + '@backstage/theme': '^1.0.0', + }, + }), }, - }), + }, }); - jest - .spyOn(paths, 'resolveTargetRoot') - .mockImplementation((...path) => resolvePath('/', ...path)); jest.spyOn(runObj, 'run').mockResolvedValue(undefined); worker.use( rest.get( @@ -177,7 +203,7 @@ describe('bump', () => { const { log: logs } = await withLogCollector(['log'], async () => { await bump({ pattern: null, release: 'main' } as unknown as Command); }); - expect(logs.filter(Boolean)).toEqual([ + expectLogsToMatch(logs, [ 'Using default pattern glob @backstage/*', 'Checking for updates of @backstage/core', 'Checking for updates of @backstage/theme', @@ -208,17 +234,24 @@ describe('bump', () => { expect.any(Object), ); - const lockfileContents = await fs.readFile('/yarn.lock', 'utf8'); + const lockfileContents = await fs.readFile( + mockDir.resolve('yarn.lock'), + 'utf8', + ); expect(lockfileContents).toBe(lockfileMockResult); - const packageA = await fs.readJson('/packages/a/package.json'); + const packageA = await fs.readJson( + mockDir.resolve('packages/a/package.json'), + ); expect(packageA).toEqual({ name: 'a', dependencies: { '@backstage/core': '^1.0.6', }, }); - const packageB = await fs.readJson('/packages/b/package.json'); + const packageB = await fs.readJson( + mockDir.resolve('packages/b/package.json'), + ); expect(packageB).toEqual({ name: 'b', dependencies: { @@ -229,31 +262,34 @@ describe('bump', () => { }); it('should bump backstage dependencies but not install them', async () => { - mockFs({ - '/yarn.lock': lockfileMock, - '/package.json': JSON.stringify({ + mockDir.setContent({ + 'yarn.lock': lockfileMock, + 'package.json': JSON.stringify({ workspaces: { packages: ['packages/*'], }, }), - '/packages/a/package.json': JSON.stringify({ - name: 'a', - dependencies: { - '@backstage/core': '^1.0.5', + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '^1.0.5', + }, + }), }, - }), - '/packages/b/package.json': JSON.stringify({ - name: 'b', - dependencies: { - '@backstage/core': '^1.0.3', - '@backstage/theme': '^1.0.0', + b: { + 'package.json': JSON.stringify({ + name: 'b', + dependencies: { + '@backstage/core': '^1.0.3', + '@backstage/theme': '^1.0.0', + }, + }), }, - }), + }, }); - jest - .spyOn(paths, 'resolveTargetRoot') - .mockImplementation((...path) => resolvePath('/', ...path)); jest.spyOn(runObj, 'run').mockResolvedValue(undefined); worker.use( rest.get( @@ -274,7 +310,7 @@ describe('bump', () => { skipInstall: true, } as unknown as Command); }); - expect(logs.filter(Boolean)).toEqual([ + expectLogsToMatch(logs, [ 'Using default pattern glob @backstage/*', 'Checking for updates of @backstage/core', 'Checking for updates of @backstage/theme', @@ -304,17 +340,24 @@ describe('bump', () => { expect.any(Object), ); - const lockfileContents = await fs.readFile('/yarn.lock', 'utf8'); + const lockfileContents = await fs.readFile( + mockDir.resolve('yarn.lock'), + 'utf8', + ); expect(lockfileContents).toBe(lockfileMockResult); - const packageA = await fs.readJson('/packages/a/package.json'); + const packageA = await fs.readJson( + mockDir.resolve('packages/a/package.json'), + ); expect(packageA).toEqual({ name: 'a', dependencies: { '@backstage/core': '^1.0.6', }, }); - const packageB = await fs.readJson('/packages/b/package.json'); + const packageB = await fs.readJson( + mockDir.resolve('packages/b/package.json'), + ); expect(packageB).toEqual({ name: 'b', dependencies: { @@ -325,31 +368,34 @@ describe('bump', () => { }); it('should prefer dependency versions from release manifest', async () => { - mockFs({ - '/yarn.lock': lockfileMock, - '/package.json': JSON.stringify({ + mockDir.setContent({ + 'yarn.lock': lockfileMock, + 'package.json': JSON.stringify({ workspaces: { packages: ['packages/*'], }, }), - '/packages/a/package.json': JSON.stringify({ - name: 'a', - dependencies: { - '@backstage/core': '^1.0.5', + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '^1.0.5', + }, + }), }, - }), - '/packages/b/package.json': JSON.stringify({ - name: 'b', - dependencies: { - '@backstage/core': '^1.0.3', - '@backstage/theme': '^1.0.0', + b: { + 'package.json': JSON.stringify({ + name: 'b', + dependencies: { + '@backstage/core': '^1.0.3', + '@backstage/theme': '^1.0.0', + }, + }), }, - }), + }, }); - jest - .spyOn(paths, 'resolveTargetRoot') - .mockImplementation((...path) => resolvePath('/', ...path)); jest.spyOn(runObj, 'run').mockResolvedValue(undefined); worker.use( rest.get( @@ -376,7 +422,7 @@ describe('bump', () => { const { log: logs } = await withLogCollector(['log'], async () => { await bump({ pattern: null, release: 'main' } as unknown as Command); }); - expect(logs.filter(Boolean)).toEqual([ + expectLogsToMatch(logs, [ 'Using default pattern glob @backstage/*', 'Checking for updates of @backstage/core', 'Checking for updates of @backstage/theme', @@ -408,17 +454,24 @@ describe('bump', () => { expect.any(Object), ); - const lockfileContents = await fs.readFile('/yarn.lock', 'utf8'); + const lockfileContents = await fs.readFile( + mockDir.resolve('yarn.lock'), + 'utf8', + ); expect(lockfileContents).toBe(lockfileMockResult); - const packageA = await fs.readJson('/packages/a/package.json'); + const packageA = await fs.readJson( + mockDir.resolve('packages/a/package.json'), + ); expect(packageA).toEqual({ name: 'a', dependencies: { '@backstage/core': '^1.0.6', }, }); - const packageB = await fs.readJson('/packages/b/package.json'); + const packageB = await fs.readJson( + mockDir.resolve('packages/b/package.json'), + ); expect(packageB).toEqual({ name: 'b', dependencies: { @@ -429,30 +482,33 @@ describe('bump', () => { }); it('should only bump packages in the manifest when a specific release is specified', async () => { - mockFs({ - '/yarn.lock': lockfileMock, - '/package.json': JSON.stringify({ + mockDir.setContent({ + 'yarn.lock': lockfileMock, + 'package.json': JSON.stringify({ workspaces: { packages: ['packages/*'], }, }), - '/packages/a/package.json': JSON.stringify({ - name: 'a', - dependencies: { - '@backstage/core': '^1.0.5', + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '^1.0.5', + }, + }), }, - }), - '/packages/b/package.json': JSON.stringify({ - name: 'b', - dependencies: { - '@backstage/core': '^1.0.3', - '@backstage/theme': '^1.0.0', + b: { + 'package.json': JSON.stringify({ + name: 'b', + dependencies: { + '@backstage/core': '^1.0.3', + '@backstage/theme': '^1.0.0', + }, + }), }, - }), + }, }); - jest - .spyOn(paths, 'resolveTargetRoot') - .mockImplementation((...path) => resolvePath('/', ...path)); jest.spyOn(runObj, 'run').mockResolvedValue(undefined); worker.use( @@ -472,14 +528,18 @@ describe('bump', () => { expect(runObj.run).toHaveBeenCalledTimes(0); - const packageA = await fs.readJson('/packages/a/package.json'); + const packageA = await fs.readJson( + mockDir.resolve('packages/a/package.json'), + ); expect(packageA).toEqual({ name: 'a', dependencies: { '@backstage/core': '^1.0.5', }, }); - const packageB = await fs.readJson('/packages/b/package.json'); + const packageB = await fs.readJson( + mockDir.resolve('packages/b/package.json'), + ); expect(packageB).toEqual({ name: 'b', dependencies: { @@ -489,32 +549,36 @@ describe('bump', () => { }); }); + // eslint-disable-next-line jest/expect-expect it('should prefer versions from the highest manifest version when main is not specified', async () => { - mockFs({ - '/yarn.lock': lockfileMock, - '/package.json': JSON.stringify({ + mockDir.setContent({ + 'yarn.lock': lockfileMock, + 'package.json': JSON.stringify({ workspaces: { packages: ['packages/*'], }, }), - '/packages/a/package.json': JSON.stringify({ - name: 'a', - dependencies: { - '@backstage/core': '^1.0.5', + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '^1.0.5', + }, + }), }, - }), - '/packages/b/package.json': JSON.stringify({ - name: 'b', - dependencies: { - '@backstage/core': '^1.0.3', - '@backstage/theme': '^1.0.0', + b: { + 'package.json': JSON.stringify({ + name: 'b', + dependencies: { + '@backstage/core': '^1.0.3', + '@backstage/theme': '^1.0.0', + }, + }), }, - }), + }, }); - jest - .spyOn(paths, 'resolveTargetRoot') - .mockImplementation((...path) => resolvePath('/', ...path)); jest.spyOn(runObj, 'run').mockResolvedValue(undefined); worker.use( rest.get( @@ -561,7 +625,7 @@ describe('bump', () => { const { log: logs } = await withLogCollector(['log'], async () => { await bump({ pattern: null, release: 'next' } as unknown as Command); }); - expect(logs.filter(Boolean)).toEqual([ + expectLogsToMatch(logs, [ 'Using default pattern glob @backstage/*', 'Checking for updates of @backstage/core', 'Checking for updates of @backstage/theme', @@ -609,35 +673,38 @@ describe('bump', () => { "@backstage/theme@^1.0.0": version "1.0.0" `; - mockFs({ - '/yarn.lock': customLockfileMock, - '/package.json': JSON.stringify({ + mockDir.setContent({ + 'yarn.lock': customLockfileMock, + 'package.json': JSON.stringify({ workspaces: { packages: ['packages/*'], }, }), - '/packages/a/package.json': JSON.stringify({ - name: 'a', - dependencies: { - '@backstage/core': '^1.0.5', - '@backstage-extra/custom': '^1.0.1', - '@backstage-extra/custom-two': '^1.0.0', + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '^1.0.5', + '@backstage-extra/custom': '^1.0.1', + '@backstage-extra/custom-two': '^1.0.0', + }, + }), }, - }), - '/packages/b/package.json': JSON.stringify({ - name: 'b', - dependencies: { - '@backstage/core': '^1.0.3', - '@backstage/theme': '^1.0.0', - '@backstage-extra/custom': '^1.1.0', - '@backstage-extra/custom-two': '^1.0.0', + b: { + 'package.json': JSON.stringify({ + name: 'b', + dependencies: { + '@backstage/core': '^1.0.3', + '@backstage/theme': '^1.0.0', + '@backstage-extra/custom': '^1.1.0', + '@backstage-extra/custom-two': '^1.0.0', + }, + }), }, - }), + }, }); - jest - .spyOn(paths, 'resolveTargetRoot') - .mockImplementation((...path) => resolvePath('/', ...path)); jest.spyOn(runObj, 'run').mockResolvedValue(undefined); worker.use( rest.get( @@ -657,7 +724,7 @@ describe('bump', () => { release: 'main', } as any); }); - expect(logs.filter(Boolean)).toEqual([ + expectLogsToMatch(logs, [ 'Using custom pattern glob @{backstage,backstage-extra}/*', 'Checking for updates of @backstage/core', 'Checking for updates of @backstage-extra/custom', @@ -696,10 +763,15 @@ describe('bump', () => { expect.any(Object), ); - const lockfileContents = await fs.readFile('/yarn.lock', 'utf8'); + const lockfileContents = await fs.readFile( + mockDir.resolve('yarn.lock'), + 'utf8', + ); expect(lockfileContents).toEqual(customLockfileMockResult); - const packageA = await fs.readJson('/packages/a/package.json'); + const packageA = await fs.readJson( + mockDir.resolve('packages/a/package.json'), + ); expect(packageA).toEqual({ name: 'a', dependencies: { @@ -708,7 +780,9 @@ describe('bump', () => { '@backstage/core': '^1.0.6', }, }); - const packageB = await fs.readJson('/packages/b/package.json'); + const packageB = await fs.readJson( + mockDir.resolve('packages/b/package.json'), + ); expect(packageB).toEqual({ name: 'b', dependencies: { @@ -721,31 +795,34 @@ describe('bump', () => { }); it('should ignore not found packages', async () => { - mockFs({ - '/yarn.lock': lockfileMockResult, - '/package.json': JSON.stringify({ + mockDir.setContent({ + 'yarn.lock': lockfileMockResult, + 'package.json': JSON.stringify({ workspaces: { packages: ['packages/*'], }, }), - '/packages/a/package.json': JSON.stringify({ - name: 'a', - dependencies: { - '@backstage/core': '^1.0.5', + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '^1.0.5', + }, + }), }, - }), - '/packages/b/package.json': JSON.stringify({ - name: 'b', - dependencies: { - '@backstage/core': '^1.0.3', - '@backstage/theme': '^2.0.0', + b: { + 'package.json': JSON.stringify({ + name: 'b', + dependencies: { + '@backstage/core': '^1.0.3', + '@backstage/theme': '^2.0.0', + }, + }), }, - }), + }, }); - jest - .spyOn(paths, 'resolveTargetRoot') - .mockImplementation((...path) => resolvePath('/', ...path)); mockFetchPackageInfo.mockRejectedValue(new NotFoundError('Nope')); jest.spyOn(runObj, 'run').mockResolvedValue(undefined); worker.use( @@ -763,7 +840,7 @@ describe('bump', () => { const { log: logs } = await withLogCollector(['log'], async () => { await bump({ pattern: null, release: 'main' } as unknown as Command); }); - expect(logs.filter(Boolean)).toEqual([ + expectLogsToMatch(logs, [ 'Using default pattern glob @backstage/*', 'Checking for updates of @backstage/core', 'Checking for updates of @backstage/theme', @@ -778,17 +855,24 @@ describe('bump', () => { expect(runObj.run).toHaveBeenCalledTimes(0); - const lockfileContents = await fs.readFile('/yarn.lock', 'utf8'); + const lockfileContents = await fs.readFile( + mockDir.resolve('yarn.lock'), + 'utf8', + ); expect(lockfileContents).toBe(lockfileMockResult); - const packageA = await fs.readJson('/packages/a/package.json'); + const packageA = await fs.readJson( + mockDir.resolve('packages/a/package.json'), + ); expect(packageA).toEqual({ name: 'a', dependencies: { '@backstage/core': '^1.0.5', // not bumped }, }); - const packageB = await fs.readJson('/packages/b/package.json'); + const packageB = await fs.readJson( + mockDir.resolve('packages/b/package.json'), + ); expect(packageB).toEqual({ name: 'b', dependencies: { @@ -798,6 +882,7 @@ describe('bump', () => { }); }); + // eslint-disable-next-line jest/expect-expect it('should log duplicates', async () => { jest.spyOn(Lockfile.prototype, 'analyze').mockReturnValue({ invalidRanges: [], @@ -826,31 +911,34 @@ describe('bump', () => { }, ], }); - mockFs({ - '/yarn.lock': lockfileMock, - '/package.json': JSON.stringify({ + mockDir.setContent({ + 'yarn.lock': lockfileMock, + 'package.json': JSON.stringify({ workspaces: { packages: ['packages/*'], }, }), - '/packages/a/package.json': JSON.stringify({ - name: 'a', - dependencies: { - '@backstage/core': '^1.0.5', + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '^1.0.5', + }, + }), }, - }), - '/packages/b/package.json': JSON.stringify({ - name: 'b', - dependencies: { - '@backstage/core': '^1.0.3', - '@backstage/theme': '^1.0.0', + b: { + 'package.json': JSON.stringify({ + name: 'b', + dependencies: { + '@backstage/core': '^1.0.3', + '@backstage/theme': '^1.0.0', + }, + }), }, - }), + }, }); - jest - .spyOn(paths, 'resolveTargetRoot') - .mockImplementation((...path) => resolvePath('/', ...path)); jest.spyOn(runObj, 'run').mockResolvedValue(undefined); worker.use( rest.get( @@ -867,7 +955,7 @@ describe('bump', () => { const { log: logs } = await withLogCollector(['log'], async () => { await bump({ pattern: null, release: 'main' } as unknown as Command); }); - expect(logs.filter(Boolean)).toEqual([ + expectLogsToMatch(logs, [ 'Using default pattern glob @backstage/*', 'Checking for updates of @backstage/core', 'Checking for updates of @backstage/theme', @@ -891,24 +979,23 @@ describe('bump', () => { }); describe('bumpBackstageJsonVersion', () => { + mockDir = createMockDirectory(); + afterEach(() => { - mockFs.restore(); jest.resetAllMocks(); }); it('should bump version in backstage.json', async () => { - mockFs({ - '/backstage.json': JSON.stringify({ version: '0.0.1' }), + mockDir.setContent({ + 'backstage.json': JSON.stringify({ version: '0.0.1' }), }); - paths.targetDir = '/'; - jest - .spyOn(paths, 'resolveTargetRoot') - .mockImplementation((...path) => resolvePath('/', ...path)); const { log } = await withLogCollector(async () => { await bumpBackstageJsonVersion('1.4.1'); }); - expect(await fs.readJson('/backstage.json')).toEqual({ version: '1.4.1' }); + expect(await fs.readJson(mockDir.resolve('backstage.json'))).toEqual({ + version: '1.4.1', + }); expect(log).toEqual([ 'Upgraded from release 0.0.1 to 1.4.1, please review these template changes:', undefined, @@ -918,17 +1005,15 @@ describe('bumpBackstageJsonVersion', () => { }); it("should create backstage.json if doesn't exist", async () => { - mockFs({}); - paths.targetDir = '/'; + mockDir.clear(); // empty temp test folder const latest = '1.4.1'; - jest - .spyOn(paths, 'resolveTargetRoot') - .mockImplementation((...path) => resolvePath('/', ...path)); const { log } = await withLogCollector(async () => { await bumpBackstageJsonVersion(latest); }); - expect(await fs.readJson('/backstage.json')).toEqual({ version: latest }); + expect(await fs.readJson(mockDir.resolve('backstage.json'))).toEqual({ + version: latest, + }); expect(log).toEqual([ 'Your project is now at version 1.4.1, which has been written to backstage.json', ]); diff --git a/packages/cli/src/lib/builder/plugins.test.ts b/packages/cli/src/lib/builder/plugins.test.ts index dcbdc55cc0..f6984dd67e 100644 --- a/packages/cli/src/lib/builder/plugins.test.ts +++ b/packages/cli/src/lib/builder/plugins.test.ts @@ -15,7 +15,6 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; import { NormalizedOutputOptions, OutputAsset, @@ -24,6 +23,7 @@ import { } from 'rollup'; import { forwardFileImports } from './plugins'; +import { createMockDirectory } from '@backstage/backend-test-utils'; const context = { meta: { @@ -91,16 +91,18 @@ describe('forwardFileImports', () => { ); }); - describe('with mock fs', () => { - beforeEach(() => { - mockFs({ - '/dev/src/my-module.ts': '', - '/dev/src/dir/my-image.png': 'my-image', - }); - }); + describe('with createMockDirectory', () => { + const mockDir = createMockDirectory(); - afterEach(() => { - mockFs.restore(); + beforeEach(() => { + mockDir.setContent({ + dev: { + src: { + 'my-module.ts': '', + dir: { 'my-image.png': 'my-image' }, + }, + }, + }); }); it('should extract files', async () => { @@ -111,23 +113,33 @@ describe('forwardFileImports', () => { throw new Error('options.external is not a function'); } - expect(options.external('./my-module', '/dev/src/index.ts', false)).toBe( - false, - ); expect( - options.external('./my-image.png', '/dev/src/dir/index.ts', false), + options.external( + './my-module', + mockDir.resolve('dev/src/index.ts'), + false, + ), + ).toBe(false); + expect( + options.external( + './my-image.png', + mockDir.resolve('dev', 'src', 'dir', 'index.ts'), + false, + ), ).toBe(true); - const outPath = '/dev/dist/dir/my-image.png'; + const outPath = mockDir.resolve('dev', 'dist', 'dir', 'my-image.png'); await expect(fs.pathExists(outPath)).resolves.toBe(false); await plugin.generateBundle?.call( context, - { dir: '/dev/dist' } as NormalizedOutputOptions, + { + dir: mockDir.resolve('dev/dist'), + } as NormalizedOutputOptions, { ['index.js']: { type: 'chunk', - facadeModuleId: '/dev/src/index.ts', + facadeModuleId: mockDir.resolve('dev/src/index.ts'), } as OutputChunk, }, false, // isWrite = false -> no write @@ -136,7 +148,9 @@ describe('forwardFileImports', () => { await plugin.generateBundle?.call( context, - { dir: '/dev/dist' } as NormalizedOutputOptions, + { + dir: mockDir.resolve('dev/dist'), + } as NormalizedOutputOptions, { // output assets should not cause a write ['index.js']: { type: 'asset' } as OutputAsset, @@ -150,11 +164,13 @@ describe('forwardFileImports', () => { // output chunk + isWrite -> generate files await plugin.generateBundle?.call( context, - { dir: '/dev/dist' } as NormalizedOutputOptions, + { + dir: mockDir.resolve('dev/dist'), + } as NormalizedOutputOptions, { ['index.js']: { type: 'chunk', - facadeModuleId: '/dev/src/index.ts', + facadeModuleId: mockDir.resolve('dev/src/index.ts'), } as OutputChunk, }, true, @@ -164,11 +180,13 @@ describe('forwardFileImports', () => { // should not break when triggering another write await plugin.generateBundle?.call( context, - { file: '/dev/dist/my-output.js' } as NormalizedOutputOptions, + { + file: mockDir.resolve('dev/dist/my-output.js'), + } as NormalizedOutputOptions, { ['index.js']: { type: 'chunk', - facadeModuleId: '/dev/src/index.ts', + facadeModuleId: mockDir.resolve('dev/src/index.ts'), } as OutputChunk, }, true, diff --git a/packages/cli/src/lib/builder/plugins.ts b/packages/cli/src/lib/builder/plugins.ts index e68758c1c8..1c1dd1b1e2 100644 --- a/packages/cli/src/lib/builder/plugins.ts +++ b/packages/cli/src/lib/builder/plugins.ts @@ -37,7 +37,7 @@ type ForwardFileImportsOptions = { * path `dist/MyComponent/my-image.png`. The import itself will stay, but be resolved, * resulting in something like `import ImageUrl from './MyComponent/my-image.png'` */ -export function forwardFileImports(options: ForwardFileImportsOptions): Plugin { +export function forwardFileImports(options: ForwardFileImportsOptions) { const filter = createFilter(options.include, options.exclude); // We collect the absolute paths to all files we want to bundle into the @@ -131,5 +131,5 @@ export function forwardFileImports(options: ForwardFileImportsOptions): Plugin { return { ...inputOptions, external }; }, - }; + } satisfies Plugin; } diff --git a/packages/cli/src/lib/bundler/config.ts b/packages/cli/src/lib/bundler/config.ts index ed20fe385a..534ffe8c58 100644 --- a/packages/cli/src/lib/bundler/config.ts +++ b/packages/cli/src/lib/bundler/config.ts @@ -81,6 +81,15 @@ async function readBuildInfo() { }; } +function hasReactDomClient() { + try { + require.resolve('react-dom/client'); + return true; + } catch { + return false; + } +} + export async function createConfig( paths: BundlingPaths, options: BundlingOptions, @@ -136,6 +145,9 @@ export async function createConfig( () => JSON.stringify(options.getFrontendAppConfigs()), true, ), + // This allows for conditional imports of react-dom/client, since there's no way + // to check for presence of it in source code without module resolution errors. + 'process.env.HAS_REACT_DOM_CLIENT': JSON.stringify(hasReactDomClient()), }), ); diff --git a/packages/cli/src/lib/bundler/packageDetection.ts b/packages/cli/src/lib/bundler/packageDetection.ts index 10686f7c86..2095fe23e7 100644 --- a/packages/cli/src/lib/bundler/packageDetection.ts +++ b/packages/cli/src/lib/bundler/packageDetection.ts @@ -15,7 +15,7 @@ */ import { BackstagePackageJson } from '@backstage/cli-node'; -import { Config } from '@backstage/config'; +import { Config, ConfigReader } from '@backstage/config'; import chokidar from 'chokidar'; import fs from 'fs-extra'; import { join as joinPath, resolve as resolvePath } from 'path'; @@ -45,9 +45,19 @@ function readPackageDetectionConfig( return {}; } + if (typeof packages !== 'object' || Array.isArray(packages)) { + throw new Error( + "Invalid config at 'app.experimental.packages', expected object", + ); + } + const packagesConfig = new ConfigReader( + packages, + 'app.experimental.packages', + ); + return { - include: config.getOptionalStringArray('app.experimental.packages.include'), - exclude: config.getOptionalStringArray('app.experimental.packages.exclude'), + include: packagesConfig.getOptionalStringArray('include'), + exclude: packagesConfig.getOptionalStringArray('exclude'), }; } @@ -59,40 +69,47 @@ async function detectPackages( resolvePath(targetPath, 'package.json'), ); - return Object.keys(pkg.dependencies ?? {}) - .flatMap(depName => { - const depPackageJson: BackstagePackageJson = require(require.resolve( - `${depName}/package.json`, - { paths: [targetPath] }, - )); - if ( - ['frontend-plugin', 'frontend-plugin-module'].includes( - depPackageJson.backstage?.role ?? '', - ) - ) { - // Include alpha entry point if available. If there's no default export it will be ignored - const exp = depPackageJson.exports; - if (exp && typeof exp === 'object' && './alpha' in exp) { - return [depName, `${depName}/alpha`]; - } - return [depName]; - } + return Object.keys(pkg.dependencies ?? {}).flatMap(depName => { + if (exclude?.includes(depName)) { return []; - }) - .filter(name => { - if (exclude?.includes(name)) { - return false; + } + if (include && !include.includes(depName)) { + return []; + } + + const depPackageJson: BackstagePackageJson = require(require.resolve( + `${depName}/package.json`, + { paths: [targetPath] }, + )); + if ( + ['frontend-plugin', 'frontend-plugin-module'].includes( + depPackageJson.backstage?.role ?? '', + ) + ) { + // Include alpha entry point if available. If there's no default export it will be ignored + const exp = depPackageJson.exports; + if (exp && typeof exp === 'object' && './alpha' in exp) { + return [ + { name: depName, import: depName }, + { name: depName, export: './alpha', import: `${depName}/alpha` }, + ]; } - if (include && !include.includes(name)) { - return false; - } - return true; - }); + return [{ name: depName, import: depName }]; + } + return []; + }); } -async function writeDetectedPackagesModule(packageNames: string[]) { - const requirePackageScript = packageNames - ?.map(pkg => `{ name: '${pkg}', default: require('${pkg}').default }`) +async function writeDetectedPackagesModule( + pkgs: { name: string; export?: string; import: string }[], +) { + const requirePackageScript = pkgs + ?.map( + pkg => + `{ name: ${JSON.stringify(pkg.name)}, export: ${JSON.stringify( + pkg.export, + )}, default: require('${pkg.import}').default }`, + ) .join(','); await fs.writeFile( diff --git a/packages/cli/src/lib/experimental/startBackendExperimental.ts b/packages/cli/src/lib/experimental/startBackendExperimental.ts index 578fd1c747..c4271deb3d 100644 --- a/packages/cli/src/lib/experimental/startBackendExperimental.ts +++ b/packages/cli/src/lib/experimental/startBackendExperimental.ts @@ -124,9 +124,8 @@ export async function startBackendExperimental(options: BackendServeOptions) { restart(); - watcher = watch([paths.targetDir], { + watcher = watch([], { cwd: process.cwd(), - ignored: ['**/.*/**', '**/node_modules/**'], ignoreInitial: true, ignorePermissionErrors: true, }).on('all', restart); diff --git a/packages/cli/src/lib/new/factories/backendModule.test.ts b/packages/cli/src/lib/new/factories/backendModule.test.ts index c633b1c1b2..78ef5f96bb 100644 --- a/packages/cli/src/lib/new/factories/backendModule.test.ts +++ b/packages/cli/src/lib/new/factories/backendModule.test.ts @@ -15,39 +15,38 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; -import { sep, resolve as resolvePath } from 'path'; -import { paths } from '../../paths'; +import { sep } from 'path'; import { Task } from '../../tasks'; import { FactoryRegistry } from '../FactoryRegistry'; -import { createMockOutputStream, mockPaths } from './common/testUtils'; +import { + createMockOutputStream, + expectLogsToMatch, + mockPaths, +} from './common/testUtils'; import { backendModule } from './backendModule'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('backendModule factory', () => { + const mockDir = createMockDirectory(); + beforeEach(() => { mockPaths({ - targetRoot: '/root', + targetRoot: mockDir.path, }); }); afterEach(() => { - mockFs.restore(); jest.resetAllMocks(); }); it('should create a backend plugin', async () => { - mockFs({ - '/root': { - packages: { - backend: { - 'package.json': JSON.stringify({}), - }, + mockDir.setContent({ + packages: { + backend: { + 'package.json': JSON.stringify({}), }, - plugins: mockFs.directory(), }, - [paths.resolveOwn('templates')]: mockFs.load( - paths.resolveOwn('templates'), - ), + plugins: {}, }); const options = await FactoryRegistry.populateOptions(backendModule, { @@ -73,8 +72,7 @@ describe('backendModule factory', () => { expect(modified).toBe(true); - expect(output).toEqual([ - '', + expectLogsToMatch(output, [ 'Creating backend module backstage-plugin-test-backend-module-tester-two', 'Checking Prerequisites:', `availability plugins${sep}test-backend-module-tester-two`, @@ -91,14 +89,14 @@ describe('backendModule factory', () => { ]); await expect( - fs.readJson('/root/packages/backend/package.json'), + fs.readJson(mockDir.resolve('packages/backend/package.json')), ).resolves.toEqual({ dependencies: { 'backstage-plugin-test-backend-module-tester-two': '^1.0.0', }, }); const moduleFile = await fs.readFile( - '/root/plugins/test-backend-module-tester-two/src/module.ts', + mockDir.resolve('plugins/test-backend-module-tester-two/src/module.ts'), 'utf-8', ); @@ -110,11 +108,11 @@ describe('backendModule factory', () => { expect(Task.forCommand).toHaveBeenCalledTimes(2); expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { - cwd: resolvePath('/root/plugins/test-backend-module-tester-two'), + cwd: mockDir.resolve('plugins/test-backend-module-tester-two'), optional: true, }); expect(Task.forCommand).toHaveBeenCalledWith('yarn lint --fix', { - cwd: resolvePath('/root/plugins/test-backend-module-tester-two'), + cwd: mockDir.resolve('plugins/test-backend-module-tester-two'), optional: true, }); }); diff --git a/packages/cli/src/lib/new/factories/backendPlugin.test.ts b/packages/cli/src/lib/new/factories/backendPlugin.test.ts index f326de88b8..5c1d496e49 100644 --- a/packages/cli/src/lib/new/factories/backendPlugin.test.ts +++ b/packages/cli/src/lib/new/factories/backendPlugin.test.ts @@ -15,39 +15,38 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; -import { sep, resolve as resolvePath } from 'path'; -import { paths } from '../../paths'; +import { sep } from 'path'; import { Task } from '../../tasks'; import { FactoryRegistry } from '../FactoryRegistry'; -import { createMockOutputStream, mockPaths } from './common/testUtils'; +import { + createMockOutputStream, + expectLogsToMatch, + mockPaths, +} from './common/testUtils'; import { backendPlugin } from './backendPlugin'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('backendPlugin factory', () => { + const mockDir = createMockDirectory(); + beforeEach(() => { mockPaths({ - targetRoot: '/root', + targetRoot: mockDir.path, }); }); afterEach(() => { - mockFs.restore(); jest.resetAllMocks(); }); it('should create a backend plugin', async () => { - mockFs({ - '/root': { - packages: { - backend: { - 'package.json': JSON.stringify({}), - }, + mockDir.setContent({ + packages: { + backend: { + 'package.json': JSON.stringify({}), }, - plugins: mockFs.directory(), }, - [paths.resolveOwn('templates')]: mockFs.load( - paths.resolveOwn('templates'), - ), + plugins: {}, }); const options = await FactoryRegistry.populateOptions(backendPlugin, { @@ -72,8 +71,7 @@ describe('backendPlugin factory', () => { expect(modified).toBe(true); - expect(output).toEqual([ - '', + expectLogsToMatch(output, [ 'Creating backend plugin backstage-plugin-test-backend', 'Checking Prerequisites:', `availability plugins${sep}test-backend`, @@ -94,14 +92,14 @@ describe('backendPlugin factory', () => { ]); await expect( - fs.readJson('/root/packages/backend/package.json'), + fs.readJson(mockDir.resolve('packages/backend/package.json')), ).resolves.toEqual({ dependencies: { 'backstage-plugin-test-backend': '^1.0.0', }, }); const standaloneServerFile = await fs.readFile( - '/root/plugins/test-backend/src/service/standaloneServer.ts', + mockDir.resolve('plugins/test-backend/src/service/standaloneServer.ts'), 'utf-8', ); @@ -112,11 +110,11 @@ describe('backendPlugin factory', () => { expect(Task.forCommand).toHaveBeenCalledTimes(2); expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { - cwd: resolvePath('/root/plugins/test-backend'), + cwd: mockDir.resolve('plugins/test-backend'), optional: true, }); expect(Task.forCommand).toHaveBeenCalledWith('yarn lint --fix', { - cwd: resolvePath('/root/plugins/test-backend'), + cwd: mockDir.resolve('plugins/test-backend'), optional: true, }); }); diff --git a/packages/cli/src/lib/new/factories/common/tasks.test.ts b/packages/cli/src/lib/new/factories/common/tasks.test.ts index 49381676e7..60783344fc 100644 --- a/packages/cli/src/lib/new/factories/common/tasks.test.ts +++ b/packages/cli/src/lib/new/factories/common/tasks.test.ts @@ -15,32 +15,37 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; import { sep } from 'path'; -import { createMockOutputStream, mockPaths } from './testUtils'; +import { + createMockOutputStream, + expectLogsToMatch, + mockPaths, +} from './testUtils'; import { CreateContext } from '../../types'; import { executePluginPackageTemplate } from './tasks'; +import { createMockDirectory } from '@backstage/backend-test-utils'; + +const mockDir = createMockDirectory(); mockPaths({ - ownDir: '/own', - targetRoot: '/root', + ownDir: mockDir.resolve('own'), + targetRoot: mockDir.resolve('root'), }); describe('executePluginPackageTemplate', () => { afterEach(() => { - mockFs.restore(); jest.resetAllMocks(); }); it('should execute template', async () => { - mockFs({ - '/root': { + mockDir.setContent({ + root: { 'yarn.lock': ` some-package@^1.1.0: version "1.5.0" `, }, - '/own': { + own: { templates: { 'test-template': { 'package.json.hbs': ` @@ -78,7 +83,7 @@ some-package@^1.1.0: } as CreateContext, { templateName: 'test-template', - targetDir: '/target', + targetDir: mockDir.resolve('target'), values: { id: 'testing', makePrivate: true, @@ -87,7 +92,7 @@ some-package@^1.1.0: ); expect(modified).toBe(true); - expect(output).toEqual([ + expectLogsToMatch(output, [ 'Checking Prerequisites:', `availability ..${sep}target`, 'creating temp dir', @@ -98,7 +103,8 @@ some-package@^1.1.0: 'Installing:', `moving ..${sep}target`, ]); - await expect(fs.readFile('/target/package.json', 'utf8')).resolves.toBe(`{ + await expect(fs.readFile(mockDir.resolve('target/package.json'), 'utf8')) + .resolves.toBe(`{ "name": "my-testing-plugin", "private": true, "description": "testing", @@ -109,10 +115,10 @@ some-package@^1.1.0: } `); await expect( - fs.readFile('/target/subdir/templated.txt', 'utf8'), + fs.readFile(mockDir.resolve('target/subdir/templated.txt'), 'utf8'), ).resolves.toBe('Hello testing!'); await expect( - fs.readFile('/target/subdir/not-templated.txt', 'utf8'), + fs.readFile(mockDir.resolve('target/subdir/not-templated.txt'), 'utf8'), ).resolves.toBe('Hello {{id}}!'); }); }); diff --git a/packages/cli/src/lib/new/factories/common/testUtils.ts b/packages/cli/src/lib/new/factories/common/testUtils.ts index 01081a7486..1ade13a996 100644 --- a/packages/cli/src/lib/new/factories/common/testUtils.ts +++ b/packages/cli/src/lib/new/factories/common/testUtils.ts @@ -73,3 +73,11 @@ export function createMockOutputStream() { } as unknown as WriteStream & { fd: any }, ] as const; } + +// Avoid flakes by comparing sorted log lines. File system access is async, which leads to the log line order being indeterministic +export function expectLogsToMatch( + recievedLogs: String[], + expected: String[], +): void { + expect(recievedLogs.filter(Boolean).sort()).toEqual(expected.sort()); +} diff --git a/packages/cli/src/lib/new/factories/frontendPlugin.test.ts b/packages/cli/src/lib/new/factories/frontendPlugin.test.ts index 8390eb192e..94d4a7eb4c 100644 --- a/packages/cli/src/lib/new/factories/frontendPlugin.test.ts +++ b/packages/cli/src/lib/new/factories/frontendPlugin.test.ts @@ -15,13 +15,16 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; -import { sep, resolve as resolvePath } from 'path'; -import { paths } from '../../paths'; +import { sep } from 'path'; import { Task } from '../../tasks'; import { FactoryRegistry } from '../FactoryRegistry'; -import { createMockOutputStream, mockPaths } from './common/testUtils'; +import { + createMockOutputStream, + expectLogsToMatch, + mockPaths, +} from './common/testUtils'; import { frontendPlugin } from './frontendPlugin'; +import { createMockDirectory } from '@backstage/backend-test-utils'; const appTsxContent = ` import { createApp } from '@backstage/app-defaults'; @@ -34,33 +37,29 @@ const router = ( `; describe('frontendPlugin factory', () => { + const mockDir = createMockDirectory(); + beforeEach(() => { mockPaths({ - targetRoot: '/root', + targetRoot: mockDir.path, }); }); afterEach(() => { - mockFs.restore(); jest.resetAllMocks(); }); it('should create a frontend plugin', async () => { - mockFs({ - '/root': { - packages: { - app: { - 'package.json': JSON.stringify({}), - src: { - 'App.tsx': appTsxContent, - }, + mockDir.setContent({ + packages: { + app: { + 'package.json': JSON.stringify({}), + src: { + 'App.tsx': appTsxContent, }, }, - plugins: mockFs.directory(), }, - [paths.resolveOwn('templates')]: mockFs.load( - paths.resolveOwn('templates'), - ), + plugins: {}, }); const options = await FactoryRegistry.populateOptions(frontendPlugin, { @@ -85,8 +84,7 @@ describe('frontendPlugin factory', () => { expect(modified).toBe(true); - expect(output).toEqual([ - '', + expectLogsToMatch(output, [ 'Creating frontend plugin backstage-plugin-test', 'Checking Prerequisites:', `availability plugins${sep}test`, @@ -114,15 +112,16 @@ describe('frontendPlugin factory', () => { ]); await expect( - fs.readJson('/root/packages/app/package.json'), + fs.readJson(mockDir.resolve('packages/app/package.json')), ).resolves.toEqual({ dependencies: { 'backstage-plugin-test': '^1.0.0', }, }); - await expect(fs.readFile('/root/packages/app/src/App.tsx', 'utf8')).resolves - .toBe(` + await expect( + fs.readFile(mockDir.resolve('packages/app/src/App.tsx'), 'utf8'), + ).resolves.toBe(` import { createApp } from '@backstage/app-defaults'; import { TestPage } from 'backstage-plugin-test'; @@ -136,32 +135,27 @@ const router = ( expect(Task.forCommand).toHaveBeenCalledTimes(2); expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { - cwd: resolvePath('/root/plugins/test'), + cwd: mockDir.resolve('plugins/test'), optional: true, }); expect(Task.forCommand).toHaveBeenCalledWith('yarn lint --fix', { - cwd: resolvePath('/root/plugins/test'), + cwd: mockDir.resolve('plugins/test'), optional: true, }); }); it('should create a frontend plugin with more options and codeowners', async () => { - mockFs({ - '/root': { - CODEOWNERS: '', - packages: { - app: { - 'package.json': JSON.stringify({}), - src: { - 'App.tsx': appTsxContent, - }, + mockDir.setContent({ + CODEOWNERS: '', + packages: { + app: { + 'package.json': JSON.stringify({}), + src: { + 'App.tsx': appTsxContent, }, }, - plugins: mockFs.directory(), }, - [paths.resolveOwn('templates')]: mockFs.load( - paths.resolveOwn('templates'), - ), + plugins: {}, }); const options = await FactoryRegistry.populateOptions(frontendPlugin, { @@ -183,15 +177,16 @@ const router = ( }); await expect( - fs.readJson('/root/packages/app/package.json'), + fs.readJson(mockDir.resolve('packages/app/package.json')), ).resolves.toEqual({ dependencies: { '@internal/plugin-test': '^1.0.0', }, }); - await expect(fs.readFile('/root/packages/app/src/App.tsx', 'utf8')).resolves - .toBe(` + await expect( + fs.readFile(mockDir.resolve('packages/app/src/App.tsx'), 'utf8'), + ).resolves.toBe(` import { createApp } from '@backstage/app-defaults'; import { TestPage } from '@internal/plugin-test'; @@ -205,11 +200,11 @@ const router = ( expect(Task.forCommand).toHaveBeenCalledTimes(2); expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { - cwd: resolvePath('/root/plugins/test'), + cwd: mockDir.resolve('plugins/test'), optional: true, }); expect(Task.forCommand).toHaveBeenCalledWith('yarn lint --fix', { - cwd: resolvePath('/root/plugins/test'), + cwd: mockDir.resolve('plugins/test'), optional: true, }); }); diff --git a/packages/cli/src/lib/new/factories/nodeLibraryPackage.test.ts b/packages/cli/src/lib/new/factories/nodeLibraryPackage.test.ts index d0b08f4f06..e3673d21ba 100644 --- a/packages/cli/src/lib/new/factories/nodeLibraryPackage.test.ts +++ b/packages/cli/src/lib/new/factories/nodeLibraryPackage.test.ts @@ -15,36 +15,35 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; -import { resolve as resolvePath, join as joinPath } from 'path'; -import { paths } from '../../paths'; +import { join as joinPath } from 'path'; import { Task } from '../../tasks'; import { FactoryRegistry } from '../FactoryRegistry'; -import { createMockOutputStream, mockPaths } from './common/testUtils'; +import { + createMockOutputStream, + expectLogsToMatch, + mockPaths, +} from './common/testUtils'; import { nodeLibraryPackage } from './nodeLibraryPackage'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('nodeLibraryPackage factory', () => { + const mockDir = createMockDirectory(); + beforeEach(() => { mockPaths({ - targetRoot: '/root', + targetRoot: mockDir.path, }); }); afterEach(() => { - mockFs.restore(); jest.resetAllMocks(); }); it('should create a node library package', async () => { const expectedNodeLibraryPackageName = 'test'; - mockFs({ - '/root': { - packages: mockFs.directory(), - }, - [paths.resolveOwn('templates')]: mockFs.load( - paths.resolveOwn('templates'), - ), + mockDir.setContent({ + packages: {}, }); const options = await FactoryRegistry.populateOptions(nodeLibraryPackage, { @@ -69,8 +68,7 @@ describe('nodeLibraryPackage factory', () => { expect(modified).toBe(true); - expect(output).toEqual([ - '', + expectLogsToMatch(output, [ `Creating node-library package ${expectedNodeLibraryPackageName}`, 'Checking Prerequisites:', `availability ${joinPath('packages', expectedNodeLibraryPackageName)}`, @@ -87,7 +85,11 @@ describe('nodeLibraryPackage factory', () => { await expect( fs.readJson( - `/root/packages/${expectedNodeLibraryPackageName}/package.json`, + mockDir.resolve( + 'packages', + expectedNodeLibraryPackageName, + 'package.json', + ), ), ).resolves.toEqual( expect.objectContaining({ @@ -99,11 +101,11 @@ describe('nodeLibraryPackage factory', () => { expect(Task.forCommand).toHaveBeenCalledTimes(2); expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { - cwd: resolvePath(`/root/packages/${expectedNodeLibraryPackageName}`), + cwd: mockDir.resolve('packages', expectedNodeLibraryPackageName), optional: true, }); expect(Task.forCommand).toHaveBeenCalledWith('yarn lint --fix', { - cwd: resolvePath(`/root/packages/${expectedNodeLibraryPackageName}`), + cwd: mockDir.resolve('packages', expectedNodeLibraryPackageName), optional: true, }); }); @@ -111,14 +113,9 @@ describe('nodeLibraryPackage factory', () => { it('should create a node library plugin with options and codeowners', async () => { const expectedNodeLibraryPackageName = 'test'; - mockFs({ - '/root': { - CODEOWNERS: '', - packages: mockFs.directory(), - }, - [paths.resolveOwn('templates')]: mockFs.load( - paths.resolveOwn('templates'), - ), + mockDir.setContent({ + CODEOWNERS: '', + packages: {}, }); const options = await FactoryRegistry.populateOptions(nodeLibraryPackage, { @@ -141,11 +138,11 @@ describe('nodeLibraryPackage factory', () => { expect(Task.forCommand).toHaveBeenCalledTimes(2); expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { - cwd: resolvePath(`/root/${expectedNodeLibraryPackageName}`), + cwd: mockDir.resolve(expectedNodeLibraryPackageName), optional: true, }); expect(Task.forCommand).toHaveBeenCalledWith('yarn lint --fix', { - cwd: resolvePath(`/root/${expectedNodeLibraryPackageName}`), + cwd: mockDir.resolve(expectedNodeLibraryPackageName), optional: true, }); }); diff --git a/packages/cli/src/lib/new/factories/pluginCommon.test.ts b/packages/cli/src/lib/new/factories/pluginCommon.test.ts index 25b6b51905..d85e490510 100644 --- a/packages/cli/src/lib/new/factories/pluginCommon.test.ts +++ b/packages/cli/src/lib/new/factories/pluginCommon.test.ts @@ -15,34 +15,33 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; -import { sep, resolve as resolvePath } from 'path'; -import { paths } from '../../paths'; +import { sep } from 'path'; import { Task } from '../../tasks'; import { FactoryRegistry } from '../FactoryRegistry'; -import { createMockOutputStream, mockPaths } from './common/testUtils'; +import { + createMockOutputStream, + expectLogsToMatch, + mockPaths, +} from './common/testUtils'; import { pluginCommon } from './pluginCommon'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('pluginCommon factory', () => { + const mockDir = createMockDirectory(); + beforeEach(() => { mockPaths({ - targetRoot: '/root', + targetRoot: mockDir.path, }); }); afterEach(() => { - mockFs.restore(); jest.resetAllMocks(); }); it('should create a common plugin package', async () => { - mockFs({ - '/root': { - plugins: mockFs.directory(), - }, - [paths.resolveOwn('templates')]: mockFs.load( - paths.resolveOwn('templates'), - ), + mockDir.setContent({ + plugins: {}, }); const options = await FactoryRegistry.populateOptions(pluginCommon, { @@ -67,8 +66,7 @@ describe('pluginCommon factory', () => { expect(modified).toBe(true); - expect(output).toEqual([ - '', + expectLogsToMatch(output, [ 'Creating backend plugin backstage-plugin-test-common', 'Checking Prerequisites:', `availability plugins${sep}test-common`, @@ -84,7 +82,7 @@ describe('pluginCommon factory', () => { ]); await expect( - fs.readJson('/root/plugins/test-common/package.json'), + fs.readJson(mockDir.resolve('plugins/test-common/package.json')), ).resolves.toEqual( expect.objectContaining({ name: 'backstage-plugin-test-common', @@ -96,11 +94,11 @@ describe('pluginCommon factory', () => { expect(Task.forCommand).toHaveBeenCalledTimes(2); expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { - cwd: resolvePath('/root/plugins/test-common'), + cwd: mockDir.resolve('plugins/test-common'), optional: true, }); expect(Task.forCommand).toHaveBeenCalledWith('yarn lint --fix', { - cwd: resolvePath('/root/plugins/test-common'), + cwd: mockDir.resolve('plugins/test-common'), optional: true, }); }); diff --git a/packages/cli/src/lib/new/factories/pluginNode.test.ts b/packages/cli/src/lib/new/factories/pluginNode.test.ts index 50971ff191..d8d9ea33ab 100644 --- a/packages/cli/src/lib/new/factories/pluginNode.test.ts +++ b/packages/cli/src/lib/new/factories/pluginNode.test.ts @@ -15,34 +15,33 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; -import { sep, resolve as resolvePath } from 'path'; -import { paths } from '../../paths'; +import { sep } from 'path'; import { Task } from '../../tasks'; import { FactoryRegistry } from '../FactoryRegistry'; -import { createMockOutputStream, mockPaths } from './common/testUtils'; +import { + createMockOutputStream, + expectLogsToMatch, + mockPaths, +} from './common/testUtils'; import { pluginNode } from './pluginNode'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('pluginNode factory', () => { + const mockDir = createMockDirectory(); + beforeEach(() => { mockPaths({ - targetRoot: '/root', + targetRoot: mockDir.path, }); }); afterEach(() => { - mockFs.restore(); jest.resetAllMocks(); }); it('should create a node plugin package', async () => { - mockFs({ - '/root': { - plugins: mockFs.directory(), - }, - [paths.resolveOwn('templates')]: mockFs.load( - paths.resolveOwn('templates'), - ), + mockDir.setContent({ + plugins: {}, }); const options = await FactoryRegistry.populateOptions(pluginNode, { @@ -67,8 +66,7 @@ describe('pluginNode factory', () => { expect(modified).toBe(true); - expect(output).toEqual([ - '', + expectLogsToMatch(output, [ 'Creating Node.js plugin library backstage-plugin-test-node', 'Checking Prerequisites:', `availability plugins${sep}test-node`, @@ -84,7 +82,7 @@ describe('pluginNode factory', () => { ]); await expect( - fs.readJson('/root/plugins/test-node/package.json'), + fs.readJson(mockDir.resolve('plugins/test-node/package.json')), ).resolves.toEqual( expect.objectContaining({ name: 'backstage-plugin-test-node', @@ -96,11 +94,11 @@ describe('pluginNode factory', () => { expect(Task.forCommand).toHaveBeenCalledTimes(2); expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { - cwd: resolvePath('/root/plugins/test-node'), + cwd: mockDir.resolve('plugins/test-node'), optional: true, }); expect(Task.forCommand).toHaveBeenCalledWith('yarn lint --fix', { - cwd: resolvePath('/root/plugins/test-node'), + cwd: mockDir.resolve('plugins/test-node'), optional: true, }); }); diff --git a/packages/cli/src/lib/new/factories/pluginWeb.test.ts b/packages/cli/src/lib/new/factories/pluginWeb.test.ts index bcd62f3bcd..ff4211d8fa 100644 --- a/packages/cli/src/lib/new/factories/pluginWeb.test.ts +++ b/packages/cli/src/lib/new/factories/pluginWeb.test.ts @@ -15,34 +15,33 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; -import { sep, resolve as resolvePath } from 'path'; -import { paths } from '../../paths'; +import { sep } from 'path'; import { Task } from '../../tasks'; import { FactoryRegistry } from '../FactoryRegistry'; -import { createMockOutputStream, mockPaths } from './common/testUtils'; +import { + createMockOutputStream, + expectLogsToMatch, + mockPaths, +} from './common/testUtils'; import { pluginWeb } from './pluginWeb'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('pluginWeb factory', () => { + const mockDir = createMockDirectory(); + beforeEach(() => { mockPaths({ - targetRoot: '/root', + targetRoot: mockDir.path, }); }); afterEach(() => { - mockFs.restore(); jest.resetAllMocks(); }); it('should create a react plugin package', async () => { - mockFs({ - '/root': { - plugins: mockFs.directory(), - }, - [paths.resolveOwn('templates')]: mockFs.load( - paths.resolveOwn('templates'), - ), + mockDir.setContent({ + plugins: {}, }); const options = await FactoryRegistry.populateOptions(pluginWeb, { @@ -67,8 +66,7 @@ describe('pluginWeb factory', () => { expect(modified).toBe(true); - expect(output).toEqual([ - '', + expectLogsToMatch(output, [ 'Creating web plugin library backstage-plugin-test-react', 'Checking Prerequisites:', `availability plugins${sep}test-react`, @@ -91,7 +89,7 @@ describe('pluginWeb factory', () => { ]); await expect( - fs.readJson('/root/plugins/test-react/package.json'), + fs.readJson(mockDir.resolve('plugins/test-react/package.json')), ).resolves.toEqual( expect.objectContaining({ name: 'backstage-plugin-test-react', @@ -103,11 +101,11 @@ describe('pluginWeb factory', () => { expect(Task.forCommand).toHaveBeenCalledTimes(2); expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { - cwd: resolvePath('/root/plugins/test-react'), + cwd: mockDir.resolve('plugins/test-react'), optional: true, }); expect(Task.forCommand).toHaveBeenCalledWith('yarn lint --fix', { - cwd: resolvePath('/root/plugins/test-react'), + cwd: mockDir.resolve('plugins/test-react'), optional: true, }); }); diff --git a/packages/cli/src/lib/new/factories/scaffolderModule.test.ts b/packages/cli/src/lib/new/factories/scaffolderModule.test.ts index 38d1207a3f..b43946228b 100644 --- a/packages/cli/src/lib/new/factories/scaffolderModule.test.ts +++ b/packages/cli/src/lib/new/factories/scaffolderModule.test.ts @@ -15,34 +15,33 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; -import { sep, resolve as resolvePath } from 'path'; -import { paths } from '../../paths'; +import { sep } from 'path'; import { Task } from '../../tasks'; import { FactoryRegistry } from '../FactoryRegistry'; -import { createMockOutputStream, mockPaths } from './common/testUtils'; +import { + createMockOutputStream, + expectLogsToMatch, + mockPaths, +} from './common/testUtils'; import { scaffolderModule } from './scaffolderModule'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('scaffolderModule factory', () => { + const mockDir = createMockDirectory(); + beforeEach(() => { mockPaths({ - targetRoot: '/root', + targetRoot: mockDir.path, }); }); afterEach(() => { - mockFs.restore(); jest.resetAllMocks(); }); it('should create a scaffolder backend module package', async () => { - mockFs({ - '/root': { - plugins: mockFs.directory(), - }, - [paths.resolveOwn('templates')]: mockFs.load( - paths.resolveOwn('templates'), - ), + mockDir.setContent({ + plugins: {}, }); const options = await FactoryRegistry.populateOptions(scaffolderModule, { @@ -67,8 +66,7 @@ describe('scaffolderModule factory', () => { expect(modified).toBe(true); - expect(output).toEqual([ - '', + expectLogsToMatch(output, [ 'Creating module backstage-plugin-scaffolder-backend-module-test', 'Checking Prerequisites:', `availability plugins${sep}scaffolder-backend-module-test`, @@ -87,7 +85,9 @@ describe('scaffolderModule factory', () => { ]); await expect( - fs.readJson('/root/plugins/scaffolder-backend-module-test/package.json'), + fs.readJson( + mockDir.resolve('plugins/scaffolder-backend-module-test/package.json'), + ), ).resolves.toEqual( expect.objectContaining({ name: 'backstage-plugin-scaffolder-backend-module-test', @@ -99,11 +99,11 @@ describe('scaffolderModule factory', () => { expect(Task.forCommand).toHaveBeenCalledTimes(2); expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { - cwd: resolvePath('/root/plugins/scaffolder-backend-module-test'), + cwd: mockDir.resolve('plugins/scaffolder-backend-module-test'), optional: true, }); expect(Task.forCommand).toHaveBeenCalledWith('yarn lint --fix', { - cwd: resolvePath('/root/plugins/scaffolder-backend-module-test'), + cwd: mockDir.resolve('plugins/scaffolder-backend-module-test'), optional: true, }); }); diff --git a/packages/cli/src/lib/new/factories/webLibraryPackage.test.ts b/packages/cli/src/lib/new/factories/webLibraryPackage.test.ts index 50fef44a67..b0c8461189 100644 --- a/packages/cli/src/lib/new/factories/webLibraryPackage.test.ts +++ b/packages/cli/src/lib/new/factories/webLibraryPackage.test.ts @@ -15,36 +15,35 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; -import { resolve as resolvePath, join as joinPath } from 'path'; -import { paths } from '../../paths'; +import { join as joinPath } from 'path'; import { Task } from '../../tasks'; import { FactoryRegistry } from '../FactoryRegistry'; -import { createMockOutputStream, mockPaths } from './common/testUtils'; +import { + createMockOutputStream, + expectLogsToMatch, + mockPaths, +} from './common/testUtils'; import { webLibraryPackage } from './webLibraryPackage'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('webLibraryPackage factory', () => { + const mockDir = createMockDirectory(); + beforeEach(() => { mockPaths({ - targetRoot: '/root', + targetRoot: mockDir.path, }); }); afterEach(() => { - mockFs.restore(); jest.resetAllMocks(); }); it('should create a web library package', async () => { const expectedwebLibraryPackageName = 'test'; - mockFs({ - '/root': { - packages: mockFs.directory(), - }, - [paths.resolveOwn('templates')]: mockFs.load( - paths.resolveOwn('templates'), - ), + mockDir.setContent({ + packages: {}, }); const options = await FactoryRegistry.populateOptions(webLibraryPackage, { @@ -69,8 +68,7 @@ describe('webLibraryPackage factory', () => { expect(modified).toBe(true); - expect(output).toEqual([ - '', + expectLogsToMatch(output, [ `Creating web-library package ${expectedwebLibraryPackageName}`, 'Checking Prerequisites:', `availability ${joinPath('packages', expectedwebLibraryPackageName)}`, @@ -87,7 +85,11 @@ describe('webLibraryPackage factory', () => { await expect( fs.readJson( - `/root/packages/${expectedwebLibraryPackageName}/package.json`, + mockDir.resolve( + 'packages', + expectedwebLibraryPackageName, + 'package.json', + ), ), ).resolves.toEqual( expect.objectContaining({ @@ -99,11 +101,11 @@ describe('webLibraryPackage factory', () => { expect(Task.forCommand).toHaveBeenCalledTimes(2); expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { - cwd: resolvePath(`/root/packages/${expectedwebLibraryPackageName}`), + cwd: mockDir.resolve('packages', expectedwebLibraryPackageName), optional: true, }); expect(Task.forCommand).toHaveBeenCalledWith('yarn lint --fix', { - cwd: resolvePath(`/root/packages/${expectedwebLibraryPackageName}`), + cwd: mockDir.resolve('packages', expectedwebLibraryPackageName), optional: true, }); }); @@ -111,14 +113,9 @@ describe('webLibraryPackage factory', () => { it('should create a web library plugin with options and codeowners', async () => { const expectedwebLibraryPackageName = 'test'; - mockFs({ - '/root': { - CODEOWNERS: '', - packages: mockFs.directory(), - }, - [paths.resolveOwn('templates')]: mockFs.load( - paths.resolveOwn('templates'), - ), + mockDir.setContent({ + CODEOWNERS: '', + packages: {}, }); const options = await FactoryRegistry.populateOptions(webLibraryPackage, { @@ -141,11 +138,11 @@ describe('webLibraryPackage factory', () => { expect(Task.forCommand).toHaveBeenCalledTimes(2); expect(Task.forCommand).toHaveBeenCalledWith('yarn install', { - cwd: resolvePath(`/root/${expectedwebLibraryPackageName}`), + cwd: mockDir.resolve(expectedwebLibraryPackageName), optional: true, }); expect(Task.forCommand).toHaveBeenCalledWith('yarn lint --fix', { - cwd: resolvePath(`/root/${expectedwebLibraryPackageName}`), + cwd: mockDir.resolve(expectedwebLibraryPackageName), optional: true, }); }); diff --git a/packages/cli/src/lib/role.test.ts b/packages/cli/src/lib/role.test.ts index adca2d70b8..8163512b76 100644 --- a/packages/cli/src/lib/role.test.ts +++ b/packages/cli/src/lib/role.test.ts @@ -14,10 +14,20 @@ * limitations under the License. */ -import mockFs from 'mock-fs'; +import { createMockDirectory } from '@backstage/backend-test-utils'; import { Command } from 'commander'; import { findRoleFromCommand } from './role'; +const mockDir = createMockDirectory(); + +jest.mock('./paths', () => ({ + paths: { + resolveTarget(filename: string) { + return mockDir.resolve(filename); + }, + }, +})); + describe('findRoleFromCommand', () => { function mkCommand(args: string) { const parsed = new Command() @@ -27,7 +37,7 @@ describe('findRoleFromCommand', () => { } beforeEach(() => { - mockFs({ + mockDir.setContent({ 'package.json': JSON.stringify({ name: 'test', backstage: { @@ -37,10 +47,6 @@ describe('findRoleFromCommand', () => { }); }); - afterEach(() => { - mockFs.restore(); - }); - it('provides role info by role', async () => { await expect(findRoleFromCommand(mkCommand(''))).resolves.toEqual( 'web-library', diff --git a/packages/cli/src/lib/svgrTemplate.ts b/packages/cli/src/lib/svgrTemplate.ts index b583004f81..5407dc4c62 100644 --- a/packages/cli/src/lib/svgrTemplate.ts +++ b/packages/cli/src/lib/svgrTemplate.ts @@ -34,6 +34,8 @@ export function svgrTemplate( ${imports} import SvgIcon from '@material-ui/core/SvgIcon'; +console.log('DEPRECATION WARNING: The .icon.svg extension is deprecated, inline the SVG elements in a MUI SvgIcon instead.', Object.assign(new Error(), {name: 'Warning'}).stack); + ${interfaces} const ${name} = (${props}) => React.createElement(SvgIcon, ${props}, ${jsx.children}); diff --git a/packages/cli/src/lib/tasks.test.ts b/packages/cli/src/lib/tasks.test.ts index fb1f38536f..1119adb7f7 100644 --- a/packages/cli/src/lib/tasks.test.ts +++ b/packages/cli/src/lib/tasks.test.ts @@ -15,14 +15,11 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; -import { resolve as resolvePath } from 'path'; import { templatingTask } from './tasks'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('templatingTask', () => { - afterEach(() => { - mockFs.restore(); - }); + const mockDir = createMockDirectory(); it('should template a directory with mix of regular files and templates', async () => { // Testing template directory @@ -36,7 +33,7 @@ describe('templatingTask', () => { const testVersionFileContent = "version: {{pluginVersion}} {{versionQuery 'mock-pkg'}}"; - mockFs({ + mockDir.setContent({ [tmplDir]: { sub: { 'version.txt.hbs': testVersionFileContent, @@ -47,8 +44,8 @@ describe('templatingTask', () => { }); await templatingTask( - tmplDir, - destDir, + mockDir.resolve(tmplDir), + mockDir.resolve(destDir), { pluginVersion: '0.0.0', }, @@ -57,10 +54,10 @@ describe('templatingTask', () => { ); await expect( - fs.readFile(resolvePath(destDir, 'test.txt'), 'utf8'), + fs.readFile(mockDir.resolve(destDir, 'test.txt'), 'utf8'), ).resolves.toBe(testFileContent); await expect( - fs.readFile(resolvePath(destDir, 'sub/version.txt'), 'utf8'), + fs.readFile(mockDir.resolve(destDir, 'sub/version.txt'), 'utf8'), ).resolves.toBe('version: 0.0.0 ^0.1.2'); }); }); diff --git a/packages/cli/src/lib/version.test.ts b/packages/cli/src/lib/version.test.ts index 604129679b..6b1aa391d5 100644 --- a/packages/cli/src/lib/version.test.ts +++ b/packages/cli/src/lib/version.test.ts @@ -14,15 +14,13 @@ * limitations under the License. */ -import mockFs from 'mock-fs'; import { packageVersions, createPackageVersionProvider } from './version'; import { Lockfile } from './versioning'; import corePluginApiPkg from '@backstage/core-plugin-api/package.json'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('createPackageVersionProvider', () => { - afterEach(() => { - mockFs.restore(); - }); + const mockDir = createMockDirectory(); const HEADER = `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 @@ -30,7 +28,7 @@ describe('createPackageVersionProvider', () => { `; it('should provide package versions', async () => { - mockFs({ + mockDir.setContent({ 'yarn.lock': `${HEADER} "a@^0.1.0": version "0.1.5" @@ -55,7 +53,8 @@ describe('createPackageVersionProvider', () => { `, }); - const lockfile = await Lockfile.load('yarn.lock'); + const lockfilePath = mockDir.resolve('yarn.lock'); + const lockfile = await Lockfile.load(lockfilePath); const provider = createPackageVersionProvider(lockfile); expect(provider('a', '0.1.5')).toBe('^0.1.0'); diff --git a/packages/cli/src/lib/versioning/Lockfile.test.ts b/packages/cli/src/lib/versioning/Lockfile.test.ts index 909f8be9aa..a4267acdb7 100644 --- a/packages/cli/src/lib/versioning/Lockfile.test.ts +++ b/packages/cli/src/lib/versioning/Lockfile.test.ts @@ -15,9 +15,9 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; import { BackstagePackage } from '@backstage/cli-node'; import { Lockfile } from './Lockfile'; +import { createMockDirectory } from '@backstage/backend-test-utils'; const LEGACY_HEADER = `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 @@ -76,16 +76,14 @@ const mockBDedup = `${LEGACY_HEADER} `; describe('Lockfile', () => { - afterEach(() => { - mockFs.restore(); - }); + const mockDir = createMockDirectory(); it('should load and serialize mockA', async () => { - mockFs({ - '/yarn.lock': mockA, + mockDir.setContent({ + 'yarn.lock': mockA, }); - const lockfile = await Lockfile.load('/yarn.lock'); + const lockfile = await Lockfile.load(mockDir.resolve('yarn.lock')); expect(lockfile.get('a')).toEqual([ { range: '^1', version: '1.0.1', dataKey: 'a@^1' }, ]); @@ -97,11 +95,12 @@ describe('Lockfile', () => { }); it('should deduplicate and save mockA', async () => { - mockFs({ - '/yarn.lock': mockA, + mockDir.setContent({ + 'yarn.lock': mockA, }); - const lockfile = await Lockfile.load('/yarn.lock'); + const lockfilePath = mockDir.resolve('yarn.lock'); + const lockfile = await Lockfile.load(lockfilePath); const result = lockfile.analyze({ localPackages: new Map() }); expect(result).toEqual({ invalidRanges: [], @@ -120,17 +119,17 @@ describe('Lockfile', () => { lockfile.replaceVersions(result.newVersions); expect(lockfile.toString()).toBe(mockADedup); - await expect(fs.readFile('/yarn.lock', 'utf8')).resolves.toBe(mockA); - await expect(lockfile.save('/yarn.lock')).resolves.toBeUndefined(); - await expect(fs.readFile('/yarn.lock', 'utf8')).resolves.toBe(mockADedup); + await expect(fs.readFile(lockfilePath, 'utf8')).resolves.toBe(mockA); + await expect(lockfile.save(lockfilePath)).resolves.toBeUndefined(); + await expect(fs.readFile(lockfilePath, 'utf8')).resolves.toBe(mockADedup); }); it('should deduplicate mockB', async () => { - mockFs({ - '/yarn.lock': mockB, + mockDir.setContent({ + 'yarn.lock': mockB, }); - const lockfile = await Lockfile.load('/yarn.lock'); + const lockfile = await Lockfile.load(mockDir.resolve('yarn.lock')); const result = lockfile.analyze({ localPackages: new Map() }); expect(result).toEqual({ invalidRanges: [], @@ -226,16 +225,14 @@ b@^2: `; describe('New Lockfile', () => { - afterEach(() => { - mockFs.restore(); - }); + const mockDir = createMockDirectory(); it('should load and serialize mockANew', async () => { - mockFs({ - '/yarn.lock': mockANew, + mockDir.setContent({ + 'yarn.lock': mockANew, }); - const lockfile = await Lockfile.load('/yarn.lock'); + const lockfile = await Lockfile.load(mockDir.resolve('yarn.lock')); expect(lockfile.get('a')).toEqual([ { range: '^1', version: '1.0.1', dataKey: 'a@^1' }, ]); @@ -248,11 +245,12 @@ describe('New Lockfile', () => { }); it('should deduplicate and save mockANew', async () => { - mockFs({ - '/yarn.lock': mockANew, + mockDir.setContent({ + 'yarn.lock': mockANew, }); - const lockfile = await Lockfile.load('/yarn.lock'); + const lockfilePath = mockDir.resolve('yarn.lock'); + const lockfile = await Lockfile.load(lockfilePath); const result = lockfile.analyze({ localPackages: new Map() }); expect(result).toEqual({ invalidRanges: [], @@ -271,19 +269,20 @@ describe('New Lockfile', () => { lockfile.replaceVersions(result.newVersions); expect(lockfile.toString()).toBe(mockANewDedup); - await expect(fs.readFile('/yarn.lock', 'utf8')).resolves.toBe(mockANew); - await expect(lockfile.save('/yarn.lock')).resolves.toBeUndefined(); - await expect(fs.readFile('/yarn.lock', 'utf8')).resolves.toBe( + await expect(fs.readFile(lockfilePath, 'utf8')).resolves.toBe(mockANew); + await expect(lockfile.save(lockfilePath)).resolves.toBeUndefined(); + await expect(fs.readFile(lockfilePath, 'utf8')).resolves.toBe( mockANewDedup, ); }); it('should deduplicate and save mockANewLocal', async () => { - mockFs({ - '/yarn.lock': mockANewLocal, + mockDir.setContent({ + 'yarn.lock': mockANewLocal, }); - const lockfile = await Lockfile.load('/yarn.lock'); + const lockfilePath = mockDir.resolve('yarn.lock'); + const lockfile = await Lockfile.load(lockfilePath); const result = lockfile.analyze({ localPackages: new Map([ [ @@ -311,11 +310,11 @@ describe('New Lockfile', () => { lockfile.replaceVersions(result.newVersions); expect(lockfile.toString()).toBe(mockANewLocalDedup); - await expect(fs.readFile('/yarn.lock', 'utf8')).resolves.toBe( + await expect(fs.readFile(lockfilePath, 'utf8')).resolves.toBe( mockANewLocal, ); - await expect(lockfile.save('/yarn.lock')).resolves.toBeUndefined(); - await expect(fs.readFile('/yarn.lock', 'utf8')).resolves.toBe( + await expect(lockfile.save(lockfilePath)).resolves.toBeUndefined(); + await expect(fs.readFile(lockfilePath, 'utf8')).resolves.toBe( mockANewLocalDedup, ); }); diff --git a/packages/cli/src/lib/versioning/packages.test.ts b/packages/cli/src/lib/versioning/packages.test.ts index 5a255532f9..23ff927c48 100644 --- a/packages/cli/src/lib/versioning/packages.test.ts +++ b/packages/cli/src/lib/versioning/packages.test.ts @@ -14,12 +14,11 @@ * limitations under the License. */ -import mockFs from 'mock-fs'; -import path from 'path'; import * as runObj from '../run'; import * as yarn from '../yarn'; import { fetchPackageInfo, mapDependencies } from './packages'; import { NotFoundError } from '../errors'; +import { createMockDirectory } from '@backstage/backend-test-utils'; jest.mock('../run', () => { return { @@ -96,34 +95,41 @@ describe('fetchPackageInfo', () => { }); describe('mapDependencies', () => { + const mockDir = createMockDirectory(); + afterEach(() => { - mockFs.restore(); jest.resetAllMocks(); }); it('should read dependencies', async () => { - mockFs({ - '/root/package.json': JSON.stringify({ + mockDir.setContent({ + 'package.json': JSON.stringify({ workspaces: { packages: ['pkgs/*'], }, }), - '/root/pkgs/a/package.json': JSON.stringify({ - name: 'a', - dependencies: { - '@backstage/core': '1 || 2', + pkgs: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '1 || 2', + }, + }), }, - }), - '/root/pkgs/b/package.json': JSON.stringify({ - name: 'b', - dependencies: { - '@backstage/core': '3', - '@backstage/cli': '^0', + b: { + 'package.json': JSON.stringify({ + name: 'b', + dependencies: { + '@backstage/core': '3', + '@backstage/cli': '^0', + }, + }), }, - }), + }, }); - const dependencyMap = await mapDependencies('/root', '@backstage/*'); + const dependencyMap = await mapDependencies(mockDir.path, '@backstage/*'); expect(Array.from(dependencyMap)).toEqual([ [ '@backstage/core', @@ -131,12 +137,12 @@ describe('mapDependencies', () => { { name: 'a', range: '1 || 2', - location: path.resolve('/root/pkgs/a'), + location: mockDir.resolve('pkgs/a'), }, { name: 'b', range: '3', - location: path.resolve('/root/pkgs/b'), + location: mockDir.resolve('pkgs/b'), }, ], ], @@ -146,7 +152,7 @@ describe('mapDependencies', () => { { name: 'b', range: '^0', - location: path.resolve('/root/pkgs/b'), + location: mockDir.resolve('pkgs/b'), }, ], ], diff --git a/packages/cli/templates/scaffolder-module/src/actions/example/example.test.ts b/packages/cli/templates/scaffolder-module/src/actions/example/example.test.ts index 3f91a8f49d..242f93c2f3 100644 --- a/packages/cli/templates/scaffolder-module/src/actions/example/example.test.ts +++ b/packages/cli/templates/scaffolder-module/src/actions/example/example.test.ts @@ -22,7 +22,7 @@ describe('acme:example', () => { logStream: new PassThrough(), output: jest.fn(), createTemporaryDirectory() { - // Usage of mock-fs is recommended for testing of filesystem operations + // Usage of createMockDirectory is recommended for testing of filesystem operations throw new Error('Not implemented'); }, }); diff --git a/packages/codemods/CHANGELOG.md b/packages/codemods/CHANGELOG.md index 7db642945f..133da12a64 100644 --- a/packages/codemods/CHANGELOG.md +++ b/packages/codemods/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/codemods +## 0.1.46 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- Updated dependencies + - @backstage/cli-common@0.1.13 + ## 0.1.46-next.0 ### Patch Changes diff --git a/packages/codemods/package.json b/packages/codemods/package.json index 34f4b5d748..d469ad47ea 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/codemods", "description": "A collection of codemods for Backstage projects", - "version": "0.1.46-next.0", + "version": "0.1.46", "publishConfig": { "access": "public", "main": "dist/index.cjs.js" diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index 1ee39cb9c6..b0d59d8a8b 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/config-loader +## 1.5.1 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 30c553c1d2: Updated dependency `typescript-json-schema` to `^0.61.0`. +- 773ea341d2: The `FileConfigSource` will now retry file reading after a short delay if it reads an empty file. This is to avoid flakiness during watch mode where change events can trigger before the file content has been written. +- a4617c422a: Added `watch` option to configuration loaders that can be used to disable file watching by setting it to `false`. +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 1.5.1-next.1 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 30c553c1d2: Updated dependency `typescript-json-schema` to `^0.61.0`. +- a4617c422a: Added `watch` option to configuration loaders that can be used to disable file watching by setting it to `false`. +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + ## 1.5.1-next.0 ### Patch Changes diff --git a/packages/config-loader/api-report.md b/packages/config-loader/api-report.md index 8cd469d4d7..9f55a27bf7 100644 --- a/packages/config-loader/api-report.md +++ b/packages/config-loader/api-report.md @@ -27,6 +27,8 @@ export interface BaseConfigSourcesOptions { rootDir?: string; // (undocumented) substitutionFunc?: EnvFunc; + // (undocumented) + watch?: boolean; } // @public @@ -142,6 +144,7 @@ export class FileConfigSource implements ConfigSource { export interface FileConfigSourceOptions { path: string; substitutionFunc?: EnvFunc; + watch?: boolean; } // @public @deprecated diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index fb17d00378..fa2ad992c6 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.1-next.0", + "version": "1.5.1", "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -47,17 +47,14 @@ "lodash": "^4.17.21", "minimist": "^1.2.5", "node-fetch": "^2.6.7", - "typescript-json-schema": "^0.55.0", - "yaml": "^2.0.0", - "yup": "^0.32.9" + "typescript-json-schema": "^0.61.0", + "yaml": "^2.0.0" }, "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/json-schema-merge-allof": "^0.6.0", "@types/mock-fs": "^4.10.0", - "@types/yup": "^0.29.13", - "mock-fs": "^5.2.0", "msw": "^1.0.0", "zen-observable": "^0.10.0" }, diff --git a/packages/config-loader/src/loader.test.ts b/packages/config-loader/src/loader.test.ts index 9554e8767e..a8299962b7 100644 --- a/packages/config-loader/src/loader.test.ts +++ b/packages/config-loader/src/loader.test.ts @@ -16,15 +16,62 @@ import { AppConfig } from '@backstage/config'; import { loadConfig } from './loader'; -import mockFs from 'mock-fs'; import fs from 'fs-extra'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; -import { resolve as resolvePath, sep } from 'path'; - -const root = resolvePath('/'); +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('loadConfig', () => { + const mockDir = createMockDirectory({ + content: { + 'app-config.yaml': ` + app: + title: Example App + sessionKey: + $file: secrets/session-key.txt + escaped: \$\${Escaped} + `, + 'app-config2.yaml': ` + app: + title: Example App 2 + sessionKey: + $file: secrets/session-key.txt + escaped: \$\${Escaped} + `, + 'app-config.development.yaml': ` + app: + sessionKey: development-key + backend: + $include: ./included.yaml + other: + $include: secrets/included.yaml + `, + 'secrets/session-key.txt': 'abc123', + 'secrets/included.yaml': ` + secret: + $file: session-key.txt + `, + 'included.yaml': ` + foo: + bar: token \${MY_SECRET} + `, + 'app-config.substitute.yaml': ` + app: + someConfig: + $include: \${SUBSTITUTE_ME}.yaml + noSubstitute: + $file: \$\${ESCAPE_ME}.txt + `, + 'substituted.yaml': ` + secret: + $file: secrets/\${SUBSTITUTE_ME}.txt + `, + 'secrets/substituted.txt': '123abc', + '${ESCAPE_ME}.txt': 'notSubstituted', + 'empty.yaml': '# just a comment', + }, + }); + const server = setupServer(); const initialLoaderHandler = rest.get( `https://some.domain.io/app-config.yaml`, @@ -61,58 +108,9 @@ describe('loadConfig', () => { beforeEach(() => { process.env.MY_SECRET = 'is-secret'; process.env.SUBSTITUTE_ME = 'substituted'; - - mockFs({ - '/root/app-config.yaml': ` - app: - title: Example App - sessionKey: - $file: secrets/session-key.txt - escaped: \$\${Escaped} - `, - '/root/app-config2.yaml': ` - app: - title: Example App 2 - sessionKey: - $file: secrets/session-key.txt - escaped: \$\${Escaped} - `, - '/root/app-config.development.yaml': ` - app: - sessionKey: development-key - backend: - $include: ./included.yaml - other: - $include: secrets/included.yaml - `, - '/root/secrets/session-key.txt': 'abc123', - '/root/secrets/included.yaml': ` - secret: - $file: session-key.txt - `, - '/root/included.yaml': ` - foo: - bar: token \${MY_SECRET} - `, - '/root/app-config.substitute.yaml': ` - app: - someConfig: - $include: \${SUBSTITUTE_ME}.yaml - noSubstitute: - $file: \$\${ESCAPE_ME}.txt - `, - '/root/substituted.yaml': ` - secret: - $file: secrets/\${SUBSTITUTE_ME}.txt - `, - '/root/secrets/substituted.txt': '123abc', - '/root/${ESCAPE_ME}.txt': 'notSubstituted', - '/root/empty.yaml': '# just a comment', - }); }); afterEach(() => { - mockFs.restore(); server.resetHandlers(); }); @@ -121,7 +119,7 @@ describe('loadConfig', () => { it('load config from default path', async () => { await expect( loadConfig({ - configRoot: '/root', + configRoot: mockDir.path, configTargets: [], }), ).resolves.toEqual({ @@ -135,7 +133,7 @@ describe('loadConfig', () => { escaped: '${Escaped}', }, }, - path: `${root}root${sep}app-config.yaml`, + path: mockDir.resolve('app-config.yaml'), }, ], }); @@ -148,7 +146,7 @@ describe('loadConfig', () => { await expect( loadConfig({ - configRoot: '/root', + configRoot: mockDir.path, configTargets: [{ url: configUrl }], remote: { reloadIntervalSeconds: 30, @@ -173,10 +171,10 @@ describe('loadConfig', () => { it('loads config with secrets from two different files', async () => { await expect( loadConfig({ - configRoot: '/root', + configRoot: mockDir.path, configTargets: [ - { path: '/root/app-config.yaml' }, - { path: '/root/app-config2.yaml' }, + { path: mockDir.resolve('app-config.yaml') }, + { path: mockDir.resolve('app-config2.yaml') }, ], }), ).resolves.toEqual({ @@ -190,7 +188,7 @@ describe('loadConfig', () => { escaped: '${Escaped}', }, }, - path: '/root/app-config.yaml', + path: mockDir.resolve('app-config.yaml'), }, { context: 'app-config2.yaml', @@ -201,7 +199,7 @@ describe('loadConfig', () => { escaped: '${Escaped}', }, }, - path: '/root/app-config2.yaml', + path: mockDir.resolve('app-config2.yaml'), }, ], }); @@ -210,8 +208,8 @@ describe('loadConfig', () => { it('loads config with secrets from single file', async () => { await expect( loadConfig({ - configRoot: '/root', - configTargets: [{ path: '/root/app-config.yaml' }], + configRoot: mockDir.path, + configTargets: [{ path: mockDir.resolve('app-config.yaml') }], }), ).resolves.toEqual({ appConfigs: [ @@ -224,7 +222,7 @@ describe('loadConfig', () => { escaped: '${Escaped}', }, }, - path: '/root/app-config.yaml', + path: mockDir.resolve('app-config.yaml'), }, ], }); @@ -233,10 +231,10 @@ describe('loadConfig', () => { it('loads development config with secrets', async () => { await expect( loadConfig({ - configRoot: '/root', + configRoot: mockDir.path, configTargets: [ - { path: '/root/app-config.yaml' }, - { path: '/root/app-config.development.yaml' }, + { path: mockDir.resolve('app-config.yaml') }, + { path: mockDir.resolve('app-config.development.yaml') }, ], }), ).resolves.toEqual({ @@ -250,7 +248,7 @@ describe('loadConfig', () => { escaped: '${Escaped}', }, }, - path: '/root/app-config.yaml', + path: mockDir.resolve('app-config.yaml'), }, { context: 'app-config.development.yaml', @@ -267,7 +265,7 @@ describe('loadConfig', () => { secret: 'abc123', }, }, - path: '/root/app-config.development.yaml', + path: mockDir.resolve('app-config.development.yaml'), }, ], }); @@ -276,8 +274,10 @@ describe('loadConfig', () => { it('loads deep substituted config', async () => { await expect( loadConfig({ - configRoot: '/root', - configTargets: [{ path: '/root/app-config.substitute.yaml' }], + configRoot: mockDir.path, + configTargets: [ + { path: mockDir.resolve('app-config.substitute.yaml') }, + ], }), ).resolves.toEqual({ appConfigs: [ @@ -291,7 +291,7 @@ describe('loadConfig', () => { noSubstitute: 'notSubstituted', }, }, - path: '/root/app-config.substitute.yaml', + path: mockDir.resolve('app-config.substitute.yaml'), }, ], }); @@ -303,7 +303,7 @@ describe('loadConfig', () => { await expect( loadConfig({ - configRoot: '/root', + configRoot: mockDir.path, configTargets: [], watch: { onChange: onChange.resolve, @@ -321,12 +321,12 @@ describe('loadConfig', () => { escaped: '${Escaped}', }, }, - path: `${root}root${sep}app-config.yaml`, + path: mockDir.resolve('app-config.yaml'), }, ], }); - await fs.writeJson('/root/app-config.yaml', { + await fs.writeJson(mockDir.resolve('app-config.yaml'), { app: { title: 'New Title', }, @@ -339,7 +339,7 @@ describe('loadConfig', () => { title: 'New Title', }, }, - path: `${root}root${sep}app-config.yaml`, + path: mockDir.resolve('app-config.yaml'), }, ]); @@ -352,8 +352,10 @@ describe('loadConfig', () => { await expect( loadConfig({ - configRoot: '/root', - configTargets: [{ path: '/root/app-config.development.yaml' }], + configRoot: mockDir.path, + configTargets: [ + { path: mockDir.resolve('app-config.development.yaml') }, + ], watch: { onChange: onChange.resolve, stopSignal: stopSignal.promise, @@ -376,14 +378,14 @@ describe('loadConfig', () => { secret: 'abc123', }, }, - path: '/root/app-config.development.yaml', + path: mockDir.resolve('app-config.development.yaml'), }, ], }); // session-key is indirectly included in app-config.development.yaml // via included.yaml - await fs.writeFile('/root/secrets/session-key.txt', 'abc234'); + await fs.writeFile(mockDir.resolve('secrets/session-key.txt'), 'abc234'); await expect(onChange.promise).resolves.toEqual([ { @@ -401,7 +403,7 @@ describe('loadConfig', () => { secret: 'abc234', }, }, - path: '/root/app-config.development.yaml', + path: mockDir.resolve('app-config.development.yaml'), }, ]); @@ -417,7 +419,7 @@ describe('loadConfig', () => { const configUrl = 'https://some.domain.io/app-config.yaml'; await expect( loadConfig({ - configRoot: '/root', + configRoot: mockDir.path, configTargets: [{ url: configUrl }], watch: { onChange: onChange.resolve, @@ -464,7 +466,7 @@ describe('loadConfig', () => { const stopSignal = defer<void>(); await loadConfig({ - configRoot: '/root', + configRoot: mockDir.path, configTargets: [], watch: { onChange: () => { @@ -476,7 +478,7 @@ describe('loadConfig', () => { stopSignal.resolve(); - await fs.writeJson('/root/app-config.yaml', { + await fs.writeJson(mockDir.resolve('app-config.yaml'), { app: { title: 'New Title', }, @@ -487,8 +489,8 @@ describe('loadConfig', () => { it('handles empty files gracefully', async () => { await expect( loadConfig({ - configRoot: '/root', - configTargets: [{ path: '/root/empty.yaml' }], + configRoot: mockDir.path, + configTargets: [{ path: mockDir.resolve('empty.yaml') }], }), ).resolves.toEqual({ appConfigs: [], diff --git a/packages/config-loader/src/loader.ts b/packages/config-loader/src/loader.ts index 8b6fd2a953..55cf123f11 100644 --- a/packages/config-loader/src/loader.ts +++ b/packages/config-loader/src/loader.ts @@ -107,6 +107,7 @@ export async function loadConfig( remote: options.remote && { reloadInterval: { seconds: options.remote.reloadIntervalSeconds }, }, + watch: Boolean(options.watch), rootDir: options.configRoot, argv: options.configTargets.flatMap(t => [ '--config', diff --git a/packages/config-loader/src/schema/collect.test.ts b/packages/config-loader/src/schema/collect.test.ts index 2754f788dd..f513253619 100644 --- a/packages/config-loader/src/schema/collect.test.ts +++ b/packages/config-loader/src/schema/collect.test.ts @@ -14,10 +14,16 @@ * limitations under the License. */ -import mockFs from 'mock-fs'; +import { createMockDirectory } from '@backstage/backend-test-utils'; import { collectConfigSchemas } from './collect'; import path from 'path'; +// cwd must be restored +const origDir = process.cwd(); +afterAll(() => { + process.chdir(origDir); +}); + const mockSchema = { type: 'object', properties: { @@ -28,25 +34,15 @@ const mockSchema = { }, }; -// Gotta make sure this is in the compiler cache before we start mocking the filesystem -require('typescript-json-schema'); - -// We need to load in actual TS libraries when using mock-fs. -// This lookup is to allow the `typescript` dependency to exist either -// at top level or inside node_modules of typescript-json-schema -const typescriptModuleDir = path.dirname( - require.resolve('typescript/package.json', { - paths: [require.resolve('typescript-json-schema')], - }), -); - describe('collectConfigSchemas', () => { + const mockDir = createMockDirectory(); + afterEach(() => { - mockFs.restore(); + mockDir.clear(); }); it('should not find any schemas without packages', async () => { - mockFs({ + mockDir.setContent({ 'lerna.json': JSON.stringify({ packages: ['packages/*'], }), @@ -56,7 +52,7 @@ describe('collectConfigSchemas', () => { }); it('should find schema in a local package', async () => { - mockFs({ + mockDir.setContent({ node_modules: { a: { 'package.json': JSON.stringify({ @@ -66,6 +62,7 @@ describe('collectConfigSchemas', () => { }, }, }); + process.chdir(mockDir.path); await expect(collectConfigSchemas(['a'], [])).resolves.toEqual([ { @@ -76,7 +73,7 @@ describe('collectConfigSchemas', () => { }); it('should find schema at explicit package path', async () => { - mockFs({ + mockDir.setContent({ root: { 'package.json': JSON.stringify({ name: 'root', @@ -84,6 +81,7 @@ describe('collectConfigSchemas', () => { }), }, }); + process.chdir(mockDir.path); await expect( collectConfigSchemas([], [path.join('root', 'package.json')]), @@ -96,7 +94,7 @@ describe('collectConfigSchemas', () => { }); it('should find schema in transitive dependencies and explicit path', async () => { - mockFs({ + mockDir.setContent({ root: { 'package.json': JSON.stringify({ name: 'root', @@ -152,6 +150,7 @@ describe('collectConfigSchemas', () => { }, }, }); + process.chdir(mockDir.path); await expect( collectConfigSchemas(['a'], [path.join('root', 'package.json')]), @@ -178,7 +177,7 @@ describe('collectConfigSchemas', () => { }); it('should schema of different types', async () => { - mockFs({ + mockDir.setContent({ node_modules: { a: { 'package.json': JSON.stringify({ @@ -198,15 +197,16 @@ describe('collectConfigSchemas', () => { name: 'c', configSchema: 'schema.d.ts', }), - 'schema.d.ts': `export interface Config { + 'schema.d.ts': ` + export interface Config { /** @visibility secret */ tsKey: string - }`, + } + `, }, }, - // TypeScript compilation needs to load some real files inside the typescript dir - [typescriptModuleDir]: (mockFs as any).load(typescriptModuleDir), }); + process.chdir(mockDir.path); await expect(collectConfigSchemas(['a', 'b', 'c'], [])).resolves.toEqual([ { @@ -235,7 +235,7 @@ describe('collectConfigSchemas', () => { }); it('should load schema from different package versions', async () => { - mockFs({ + mockDir.setContent({ node_modules: { a: { 'package.json': JSON.stringify({ @@ -275,6 +275,7 @@ describe('collectConfigSchemas', () => { }, }, }); + process.chdir(mockDir.path); await expect(collectConfigSchemas(['a'], [])).resolves.toEqual([ { @@ -303,7 +304,7 @@ describe('collectConfigSchemas', () => { }); it('should not allow unknown schema file types', async () => { - mockFs({ + mockDir.setContent({ node_modules: { a: { 'package.json': JSON.stringify({ @@ -314,6 +315,7 @@ describe('collectConfigSchemas', () => { }, }, }); + process.chdir(mockDir.path); await expect(collectConfigSchemas(['a'], [])).rejects.toThrow( 'Config schema files must be .json or .d.ts, got schema.yaml', @@ -321,7 +323,7 @@ describe('collectConfigSchemas', () => { }); it('should reject typescript config declaration without a Config type', async () => { - mockFs({ + mockDir.setContent({ node_modules: { a: { 'package.json': JSON.stringify({ @@ -331,9 +333,8 @@ describe('collectConfigSchemas', () => { 'schema.d.ts': `export interface NotConfig {}`, }, }, - // TypeScript compilation needs to load some real files inside the typescript dir - [typescriptModuleDir]: (mockFs as any).load(typescriptModuleDir), }); + process.chdir(mockDir.path); await expect(collectConfigSchemas(['a'], [])).rejects.toThrow( `Invalid schema in ${path.join( diff --git a/packages/config-loader/src/schema/load.test.ts b/packages/config-loader/src/schema/load.test.ts index d84bb3871b..525565f3d5 100644 --- a/packages/config-loader/src/schema/load.test.ts +++ b/packages/config-loader/src/schema/load.test.ts @@ -14,16 +14,24 @@ * limitations under the License. */ -import mockFs from 'mock-fs'; +import { createMockDirectory } from '@backstage/backend-test-utils'; import { loadConfigSchema } from './load'; +// cwd must be restored +const origDir = process.cwd(); +afterAll(() => { + process.chdir(origDir); +}); + describe('loadConfigSchema', () => { + const mockDir = createMockDirectory(); + afterEach(() => { - mockFs.restore(); + mockDir.clear(); }); it('should load schema from packages or data', async () => { - mockFs({ + mockDir.setContent({ node_modules: { a: { 'package.json': JSON.stringify({ @@ -53,6 +61,7 @@ describe('loadConfigSchema', () => { }, }, }); + process.chdir(mockDir.path); const schema = await loadConfigSchema({ dependencies: ['a'], @@ -119,7 +128,7 @@ describe('loadConfigSchema', () => { describe('should consider schema', () => { it('when filtering simple config', async () => { - mockFs({ + mockDir.setContent({ 'package.json': JSON.stringify({ name: 'a', configSchema: { @@ -131,6 +140,7 @@ describe('loadConfigSchema', () => { }, }), }); + process.chdir(mockDir.path); const schema = await loadConfigSchema({ packagePaths: ['package.json'], @@ -156,7 +166,7 @@ describe('loadConfigSchema', () => { }); it('when filtering nested config', async () => { - mockFs({ + mockDir.setContent({ 'package.json': JSON.stringify({ name: 'a', configSchema: { @@ -185,6 +195,7 @@ describe('loadConfigSchema', () => { }, }), }); + process.chdir(mockDir.path); const schema = await loadConfigSchema({ packagePaths: ['package.json'], @@ -244,7 +255,7 @@ describe('loadConfigSchema', () => { }); it('when filtering config with required values', async () => { - mockFs({ + mockDir.setContent({ 'package.json': JSON.stringify({ name: 'a', configSchema: { @@ -261,6 +272,7 @@ describe('loadConfigSchema', () => { }, }), }); + process.chdir(mockDir.path); const schema = await loadConfigSchema({ packagePaths: ['package.json'], diff --git a/packages/config-loader/src/sources/ConfigSources.ts b/packages/config-loader/src/sources/ConfigSources.ts index d60e9d53e9..43123f87ea 100644 --- a/packages/config-loader/src/sources/ConfigSources.ts +++ b/packages/config-loader/src/sources/ConfigSources.ts @@ -71,6 +71,7 @@ export interface ClosableConfig extends Config { * @public */ export interface BaseConfigSourcesOptions { + watch?: boolean; rootDir?: string; remote?: Pick<RemoteConfigSourceOptions, 'reloadInterval'>; substitutionFunc?: SubstitutionFunc; @@ -159,6 +160,7 @@ export class ConfigSources { }); } return FileConfigSource.create({ + watch: options.watch, path: arg.target, substitutionFunc: options.substitutionFunc, }); @@ -170,6 +172,7 @@ export class ConfigSources { argSources.push( FileConfigSource.create({ + watch: options.watch, path: defaultPath, substitutionFunc: options.substitutionFunc, }), @@ -177,6 +180,7 @@ export class ConfigSources { if (fs.pathExistsSync(localPath)) { argSources.push( FileConfigSource.create({ + watch: options.watch, path: localPath, substitutionFunc: options.substitutionFunc, }), diff --git a/packages/config-loader/src/sources/FileConfigSource.ts b/packages/config-loader/src/sources/FileConfigSource.ts index 1de0fbf2d8..74266de227 100644 --- a/packages/config-loader/src/sources/FileConfigSource.ts +++ b/packages/config-loader/src/sources/FileConfigSource.ts @@ -39,6 +39,11 @@ export interface FileConfigSourceOptions { */ path: string; + /** + * Set to `false` to disable file watching, defaults to `true`. + */ + watch?: boolean; + /** * A substitution function to use instead of the default environment substitution. */ @@ -89,10 +94,12 @@ export class FileConfigSource implements ConfigSource { readonly #path: string; readonly #substitutionFunc?: SubstitutionFunc; + readonly #watch?: boolean; private constructor(options: FileConfigSourceOptions) { this.#path = options.path; this.#substitutionFunc = options.substitutionFunc; + this.#watch = options.watch ?? true; } // Work is duplicated across each read, in practice that should not @@ -104,20 +111,27 @@ export class FileConfigSource implements ConfigSource { const signal = options?.signal; const configFileName = basename(this.#path); - // Keep track of watched paths, since this is simpler than resetting the watcher - const watchedPaths = new Array<string>(); - const watcher = chokidar.watch(this.#path, { - usePolling: process.env.NODE_ENV === 'test', - }); + let watchedPaths: Array<string> | null = null; + let watcher: FSWatcher | null = null; + + if (this.#watch) { + // Keep track of watched paths, since this is simpler than resetting the watcher + watchedPaths = new Array<string>(); + watcher = chokidar.watch(this.#path, { + usePolling: process.env.NODE_ENV === 'test', + }); + } const dir = dirname(this.#path); const transformer = createConfigTransformer({ substitutionFunc: this.#substitutionFunc, readFile: async path => { const fullPath = resolvePath(dir, path); - // Any files discovered while reading this config should be watched too - watcher.add(fullPath); - watchedPaths.push(fullPath); + if (watcher && watchedPaths) { + // Any files discovered while reading this config should be watched too + watcher.add(fullPath); + watchedPaths.push(fullPath); + } const data = await readFile(fullPath); if (data === undefined) { @@ -131,12 +145,15 @@ export class FileConfigSource implements ConfigSource { // This is the entry point for reading the file, called initially and on change const readConfigFile = async (): Promise<ConfigSourceData[]> => { - // We clear the watched files every time we initiate a new read - watcher.unwatch(watchedPaths); - watchedPaths.length = 0; + if (watcher && watchedPaths) { + // We clear the watched files every time we initiate a new read + watcher.unwatch(watchedPaths); + watchedPaths.length = 0; + + watcher.add(this.#path); + watchedPaths.push(this.#path); + } - watcher.add(this.#path); - watchedPaths.push(this.#path); const content = await readFile(this.#path); if (content === undefined) { throw new NotFoundError(`Config file "${this.#path}" does not exist`); @@ -157,18 +174,20 @@ export class FileConfigSource implements ConfigSource { const onAbort = () => { signal?.removeEventListener('abort', onAbort); - watcher.close(); + if (watcher) watcher.close(); }; signal?.addEventListener('abort', onAbort); yield { configs: await readConfigFile() }; - for (;;) { - const event = await this.#waitForEvent(watcher, signal); - if (event === 'abort') { - return; + if (watcher) { + for (;;) { + const event = await this.#waitForEvent(watcher, signal); + if (event === 'abort') { + return; + } + yield { configs: await readConfigFile() }; } - yield { configs: await readConfigFile() }; } } diff --git a/packages/config/CHANGELOG.md b/packages/config/CHANGELOG.md index a5dfb07366..1ba8b45805 100644 --- a/packages/config/CHANGELOG.md +++ b/packages/config/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/config +## 1.1.1 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + +## 1.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + - @backstage/types@1.1.1 + ## 1.1.0 ### Minor Changes diff --git a/packages/config/package.json b/packages/config/package.json index d917df849b..d7127b8c05 100644 --- a/packages/config/package.json +++ b/packages/config/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/config", "description": "Config API used by Backstage core, backend, and CLI", - "version": "1.1.0", + "version": "1.1.1", "publishConfig": { "access": "public", "main": "dist/index.cjs.js", diff --git a/packages/core-app-api/CHANGELOG.md b/packages/core-app-api/CHANGELOG.md index 20c6013ee0..bce1da4c9d 100644 --- a/packages/core-app-api/CHANGELOG.md +++ b/packages/core-app-api/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/core-app-api +## 1.11.0 + +### Minor Changes + +- c9d9bfeca2: URL encode some well known unsafe characters in `RouteResolver` (and therefore `useRouteRef`) + +### Patch Changes + +- 29e4d8b76b: Fixed bug in `AppRouter` to determine the correct `signOutTargetUrl` if `app.baseUrl` contains a `basePath` +- acca17e91a: Wrap entire app in `<Suspense>`, enabling support for using translations outside plugins. +- 1a0616fa10: Add missing resource and template app icons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- f1b349cfba: Fixed a bug in `TranslationApi` implementation where in some cases it wouldn't notify subscribers of language changes. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/version-bridge@1.0.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 1.11.0-next.2 + +### Minor Changes + +- c9d9bfeca2: URL encode some well known unsafe characters in `RouteResolver` (and therefore `useRouteRef`) + +### Patch Changes + +- acca17e91a: Wrap entire app in `<Suspense>`, enabling support for using translations outside plugins. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + ## 1.10.1-next.1 ### Patch Changes diff --git a/packages/core-app-api/package.json b/packages/core-app-api/package.json index 5852076136..e6792a3402 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.10.1-next.1", + "version": "1.11.0", "publishConfig": { "access": "public" }, @@ -57,16 +57,16 @@ "zod": "^3.21.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@testing-library/dom": "^9.0.0", + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0", "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/zen-observable": "^0.8.0", diff --git a/packages/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.test.ts b/packages/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.test.ts index 224430752c..d5b812c5d7 100644 --- a/packages/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.test.ts +++ b/packages/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.test.ts @@ -377,8 +377,7 @@ describe('I18nextTranslationApi', () => { }, }); }); - - expect(translations).toEqual(['foo', null, 'Föö', null, 'Føø']); + expect(translations).toEqual(['foo', 'Föö', 'Føø']); }); describe('formatting', () => { diff --git a/packages/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.ts b/packages/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.ts index 01e75d6df2..d0ef35568f 100644 --- a/packages/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.ts +++ b/packages/core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi.ts @@ -241,7 +241,6 @@ export class I18nextTranslationApi implements TranslationApi { return new ObservableImpl<TranslationSnapshot<TMessages>>(subscriber => { let loadTicket = {}; // To check for stale loads - let lastSnapshotWasReady = false; const loadResource = () => { loadTicket = {}; @@ -250,8 +249,7 @@ export class I18nextTranslationApi implements TranslationApi { () => { if (ticket === loadTicket) { const snapshot = this.#createSnapshot(internalRef); - if (snapshot.ready || lastSnapshotWasReady) { - lastSnapshotWasReady = snapshot.ready; + if (snapshot.ready) { subscriber.next(snapshot); } } @@ -266,12 +264,9 @@ export class I18nextTranslationApi implements TranslationApi { const onChange = () => { const snapshot = this.#createSnapshot(internalRef); - if (lastSnapshotWasReady && !snapshot.ready) { - lastSnapshotWasReady = snapshot.ready; + if (snapshot.ready) { subscriber.next(snapshot); - } - - if (!snapshot.ready) { + } else { loadResource(); } }; diff --git a/packages/core-app-api/src/apis/system/ApiProvider.test.tsx b/packages/core-app-api/src/apis/system/ApiProvider.test.tsx index a6118f0f68..6460e12900 100644 --- a/packages/core-app-api/src/apis/system/ApiProvider.test.tsx +++ b/packages/core-app-api/src/apis/system/ApiProvider.test.tsx @@ -118,6 +118,10 @@ describe('ApiProvider', () => { }).toThrow(/^API context is not available/); }).error, ).toEqual([ + expect.objectContaining({ + detail: new Error('API context is not available'), + type: 'unhandled exception', + }), expect.objectContaining({ detail: new Error('API context is not available'), type: 'unhandled exception', @@ -134,6 +138,10 @@ describe('ApiProvider', () => { }).toThrow(/^API context is not available/); }).error, ).toEqual([ + expect.objectContaining({ + detail: new Error('API context is not available'), + type: 'unhandled exception', + }), expect.objectContaining({ detail: new Error('API context is not available'), type: 'unhandled exception', @@ -156,6 +164,10 @@ describe('ApiProvider', () => { }).toThrow('No implementation available for apiRef{x}'); }).error, ).toEqual([ + expect.objectContaining({ + detail: new Error('No implementation available for apiRef{x}'), + type: 'unhandled exception', + }), expect.objectContaining({ detail: new Error('No implementation available for apiRef{x}'), type: 'unhandled exception', @@ -176,6 +188,10 @@ describe('ApiProvider', () => { }).toThrow('No implementation available for apiRef{x}'); }).error, ).toEqual([ + expect.objectContaining({ + detail: new Error('No implementation available for apiRef{x}'), + type: 'unhandled exception', + }), expect.objectContaining({ detail: new Error('No implementation available for apiRef{x}'), type: 'unhandled exception', diff --git a/packages/core-app-api/src/app/AppContext.test.tsx b/packages/core-app-api/src/app/AppContext.test.tsx index ee7b90533f..a011b5966b 100644 --- a/packages/core-app-api/src/app/AppContext.test.tsx +++ b/packages/core-app-api/src/app/AppContext.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useVersionedContext } from '@backstage/version-bridge'; import { AppContext as AppContextV1 } from './types'; import { AppContextProvider } from './AppContext'; diff --git a/packages/core-app-api/src/app/AppManager.test.tsx b/packages/core-app-api/src/app/AppManager.test.tsx index 3d0c47c4d5..fe8d2fa91a 100644 --- a/packages/core-app-api/src/app/AppManager.test.tsx +++ b/packages/core-app-api/src/app/AppManager.test.tsx @@ -639,26 +639,24 @@ describe('Integration Test', () => { const Provider = app.getProvider(); const Router = app.getRouter(); const { error: errorLogs } = withLogCollector(() => { - expect(() => - render( - <Provider> - <Router> - <Routes> - <Route path="/test/:thing" element={<ExposedComponent />}> - <Route path="/some/:thing" element={<HiddenComponent />} /> - </Route> - </Routes> - </Router> - </Provider>, - ), - ).toThrow( - 'Parameter :thing is duplicated in path test/:thing/some/:thing', + render( + <Provider> + <Router> + <Routes> + <Route path="/test/:thing" element={<ExposedComponent />}> + <Route path="/some/:thing" element={<HiddenComponent />} /> + </Route> + </Routes> + </Router> + </Provider>, ); }); expect(errorLogs).toEqual([ - expect.stringContaining( - 'The above error occurred in the <Provider> component', - ), + expect.objectContaining({ + message: expect.stringContaining( + 'Parameter :thing is duplicated in path test/:thing/some/:thing', + ), + }), ]); }); @@ -676,24 +674,22 @@ describe('Integration Test', () => { const Provider = app.getProvider(); const Router = app.getRouter(); const { error: errorLogs } = withLogCollector(() => { - expect(() => - render( - <Provider> - <Router> - <Routes> - <Route path="/test/:thing" element={<ExposedComponent />} /> - </Routes> - </Router> - </Provider>, - ), - ).toThrow( - /^External route 'extRouteRef1' of the 'blob' plugin must be bound to a target route/, + render( + <Provider> + <Router> + <Routes> + <Route path="/test/:thing" element={<ExposedComponent />} /> + </Routes> + </Router> + </Provider>, ); }); expect(errorLogs).toEqual([ - expect.stringContaining( - 'The above error occurred in the <Provider> component', - ), + expect.objectContaining({ + message: expect.stringMatching( + /^External route 'extRouteRef1' of the 'blob' plugin must be bound to a target route/, + ), + }), ]); }); diff --git a/packages/core-app-api/src/app/AppRouter.tsx b/packages/core-app-api/src/app/AppRouter.tsx index b799983a3b..9d07be1ffd 100644 --- a/packages/core-app-api/src/app/AppRouter.tsx +++ b/packages/core-app-api/src/app/AppRouter.tsx @@ -70,7 +70,7 @@ function SignInPageWrapper({ }) { const [identityApi, setIdentityApi] = useState<IdentityApi>(); const configApi = useApi(configApiRef); - const basePath = getBasePath(configApi); + const basePath = readBasePath(configApi); if (!identityApi) { return <Component onSignInSuccess={setIdentityApi} />; diff --git a/packages/core-app-api/src/routing/FlatRoutes.beta.test.tsx b/packages/core-app-api/src/routing/FlatRoutes.beta.test.tsx index 30be04d2d4..8d4d10c52a 100644 --- a/packages/core-app-api/src/routing/FlatRoutes.beta.test.tsx +++ b/packages/core-app-api/src/routing/FlatRoutes.beta.test.tsx @@ -56,7 +56,7 @@ function makeRouteRenderer(node: ReactNode) { ); if (rendered) { rendered.unmount(); - rendered.rerender(content); + rendered = render(content); } else { rendered = render(content); } diff --git a/packages/core-app-api/src/routing/FlatRoutes.compat.test.tsx b/packages/core-app-api/src/routing/FlatRoutes.compat.test.tsx index 5d2ca15672..c32b306387 100644 --- a/packages/core-app-api/src/routing/FlatRoutes.compat.test.tsx +++ b/packages/core-app-api/src/routing/FlatRoutes.compat.test.tsx @@ -83,7 +83,7 @@ describe.each(['beta', 'stable'])('FlatRoutes %s', rrVersion => { ); if (rendered) { rendered.unmount(); - rendered.rerender(content); + rendered = render(content); } else { rendered = render(content); } diff --git a/packages/core-app-api/src/routing/FlatRoutes.stable.test.tsx b/packages/core-app-api/src/routing/FlatRoutes.stable.test.tsx index 93297edc4c..ece6c22ff2 100644 --- a/packages/core-app-api/src/routing/FlatRoutes.stable.test.tsx +++ b/packages/core-app-api/src/routing/FlatRoutes.stable.test.tsx @@ -56,7 +56,7 @@ function makeRouteRenderer(node: ReactNode) { ); if (rendered) { rendered.unmount(); - rendered.rerender(content); + rendered = render(content); } else { rendered = render(content); } diff --git a/packages/core-app-api/src/routing/RouteResolver.beta.test.ts b/packages/core-app-api/src/routing/RouteResolver.beta.test.ts index c0ee452d28..09e6389e7f 100644 --- a/packages/core-app-api/src/routing/RouteResolver.beta.test.ts +++ b/packages/core-app-api/src/routing/RouteResolver.beta.test.ts @@ -31,9 +31,8 @@ jest.mock('react-router-dom', () => jest.requireActual('react-router-dom-beta'), ); -const element = () => null; const rest = { - element, + element: null, caseSensitive: false, children: [MATCH_ALL_ROUTE], plugins: new Set<BackstagePlugin>(), diff --git a/packages/core-app-api/src/routing/RouteResolver.compat.test.ts b/packages/core-app-api/src/routing/RouteResolver.compat.test.ts index 0b4bf588a2..39949b4cd6 100644 --- a/packages/core-app-api/src/routing/RouteResolver.compat.test.ts +++ b/packages/core-app-api/src/routing/RouteResolver.compat.test.ts @@ -25,9 +25,8 @@ import { } from '@backstage/core-plugin-api'; import { MATCH_ALL_ROUTE } from './collectors'; -const element = () => null; const rest = { - element, + element: null, caseSensitive: false, children: [MATCH_ALL_ROUTE], plugins: new Set<BackstagePlugin>(), diff --git a/packages/core-app-api/src/routing/RouteResolver.stable.test.ts b/packages/core-app-api/src/routing/RouteResolver.stable.test.ts index 05f7678078..f1f9ec7137 100644 --- a/packages/core-app-api/src/routing/RouteResolver.stable.test.ts +++ b/packages/core-app-api/src/routing/RouteResolver.stable.test.ts @@ -31,9 +31,8 @@ jest.mock('react-router-dom', () => jest.requireActual('react-router-dom-stable'), ); -const element = () => null; const rest = { - element, + element: null, caseSensitive: false, children: [MATCH_ALL_ROUTE], plugins: new Set<BackstagePlugin>(), diff --git a/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx b/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx index c3a5bab89e..ca089d0014 100644 --- a/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx +++ b/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx @@ -17,7 +17,7 @@ import React, { PropsWithChildren, ReactElement } from 'react'; import { MemoryRouter, Routes } from 'react-router-dom'; import { render } from '@testing-library/react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useVersionedContext } from '@backstage/version-bridge'; import { childDiscoverer, @@ -353,7 +353,7 @@ describe('v1 consumer', () => { initialProps: { routeRef: routeRef1 as AnyRouteRef, }, - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + wrapper: ({ children }) => ( <RoutingProvider routePaths={ new Map<RouteRef<any>, string>([ diff --git a/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx b/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx index 84a33842c9..df0ce32e2b 100644 --- a/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx +++ b/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx @@ -17,7 +17,7 @@ import React, { PropsWithChildren, ReactElement } from 'react'; import { MemoryRouter, Routes, Route, useOutlet } from 'react-router-dom'; import { render } from '@testing-library/react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useVersionedContext } from '@backstage/version-bridge'; import { childDiscoverer, @@ -385,7 +385,7 @@ describe('v1 consumer', () => { initialProps: { routeRef: routeRef1 as AnyRouteRef, }, - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + wrapper: ({ children }) => ( <RoutingProvider routePaths={ new Map<RouteRef<any>, string>([ diff --git a/packages/core-compat-api/.eslintrc.js b/packages/core-compat-api/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/packages/core-compat-api/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/packages/core-compat-api/README.md b/packages/core-compat-api/README.md new file mode 100644 index 0000000000..5faa299f03 --- /dev/null +++ b/packages/core-compat-api/README.md @@ -0,0 +1,12 @@ +# @backstage/core-compat-api + +_This package was created through the Backstage CLI_. + +## Installation + +Install the package via Yarn: + +```sh +cd <package-dir> # if within a monorepo +yarn add @backstage/core-compat-api +``` diff --git a/packages/core-compat-api/api-report.md b/packages/core-compat-api/api-report.md new file mode 100644 index 0000000000..5175c76ac8 --- /dev/null +++ b/packages/core-compat-api/api-report.md @@ -0,0 +1,16 @@ +## API Report File for "@backstage/core-compat-api" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// <reference types="react" /> + +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; + +// @public (undocumented) +export function collectLegacyRoutes( + flatRoutesElement: JSX.Element, +): BackstagePlugin[]; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/core-compat-api/catalog-info.yaml b/packages/core-compat-api/catalog-info.yaml new file mode 100644 index 0000000000..f20f0543a0 --- /dev/null +++ b/packages/core-compat-api/catalog-info.yaml @@ -0,0 +1,9 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-core-compat-api + title: '@backstage/core-compat-api' +spec: + lifecycle: experimental + type: backstage-web-library + owner: maintainers diff --git a/packages/core-compat-api/package.json b/packages/core-compat-api/package.json new file mode 100644 index 0000000000..d27049c2a4 --- /dev/null +++ b/packages/core-compat-api/package.json @@ -0,0 +1,45 @@ +{ + "name": "@backstage/core-compat-api", + "version": "0.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "private": true, + "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:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/plugin-puppetdb": "workspace:^", + "@backstage/plugin-stackstorm": "workspace:^", + "@oriflame/backstage-plugin-score-card": "^0.7.0", + "@testing-library/jest-dom": "^6.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-plugin-api": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^" + } +} diff --git a/packages/core-compat-api/src/collectLegacyRoutes.test.tsx b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx new file mode 100644 index 0000000000..486c373991 --- /dev/null +++ b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx @@ -0,0 +1,97 @@ +/* + * 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 { FlatRoutes } from '@backstage/core-app-api'; +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 { collectLegacyRoutes } from './collectLegacyRoutes'; + +describe('collectLegacyRoutes', () => { + it('should collect legacy routes', () => { + const collected = collectLegacyRoutes( + <FlatRoutes> + <Route path="/score-board" element={<ScoreBoardPage />} /> + <Route path="/stackstorm" element={<StackstormPage />} /> + <Route path="/puppetdb" element={<PuppetDbPage />} /> + </FlatRoutes>, + ); + + expect( + collected.map(p => ({ + id: p.id, + extensions: p.extensions.map(e => ({ + id: e.id, + attachTo: e.attachTo, + disabled: e.disabled, + defaultConfig: e.configSchema?.parse({}), + })), + })), + ).toEqual([ + { + id: 'score-card', + extensions: [ + { + id: 'plugin.score-card.page', + attachTo: { id: 'core.routes', input: 'routes' }, + disabled: false, + defaultConfig: { path: 'score-board' }, + }, + { + id: 'apis.plugin.scoringdata.service', + attachTo: { id: 'core', input: 'apis' }, + disabled: false, + }, + ], + }, + { + id: 'stackstorm', + extensions: [ + { + id: 'plugin.stackstorm.page', + attachTo: { id: 'core.routes', input: 'routes' }, + disabled: false, + defaultConfig: { path: 'stackstorm' }, + }, + { + id: 'apis.plugin.stackstorm.service', + attachTo: { id: 'core', input: 'apis' }, + disabled: false, + }, + ], + }, + { + id: 'puppetDb', + extensions: [ + { + id: 'plugin.puppetDb.page', + attachTo: { id: 'core.routes', input: 'routes' }, + disabled: false, + defaultConfig: { path: 'puppetdb' }, + }, + { + id: 'apis.plugin.puppetdb.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 new file mode 100644 index 0000000000..2b149e6285 --- /dev/null +++ b/packages/core-compat-api/src/collectLegacyRoutes.tsx @@ -0,0 +1,137 @@ +/* + * 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, { ReactNode } from 'react'; +import { + Extension, + createApiExtension, + createPageExtension, + createPlugin, + BackstagePlugin, +} from '@backstage/frontend-plugin-api'; +import { Route, Routes } from 'react-router-dom'; +import { + BackstagePlugin as LegacyBackstagePlugin, + RouteRef, + getComponentData, +} from '@backstage/core-plugin-api'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; + +/* + +# Legacy interoperability + +Use-cases (prioritized): + 1. Slowly migrate over an existing app to DI, piece by piece + 2. Use a legacy plugin in a new DI app + 3. Use DI in an existing legacy app + +Starting point: use-case #1 + +Potential solutions: + 1. Codemods (we're not considering this for now) + 2. Legacy apps are migrated bottom-up, i.e. keep legacy root, replace pages with DI + 3. Legacy apps are migrated top-down i.e. switch out base to DI, legacy adapter allows for usage of existing app structure + +Chosen path: #3 + +Existing tasks: + - Adopters can migrate their existing app gradually (~4) + - Example-app uses legacy base with DI adapters + - Create an API that lets you inject DI into existing apps - working assumption is that this is enough + - Adopters can use legacy plugins in DI through adapters (~8) + - App-next uses DI base with legacy adapters + - Create a legacy adapter that is able to take an existing extension tree + +*/ + +/** @public */ +export function collectLegacyRoutes( + flatRoutesElement: JSX.Element, +): BackstagePlugin[] { + const results = new Array<BackstagePlugin>(); + + 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) { + return; + } + + const routeElement = route.props.element; + + // TODO: to support deeper extension component, e.g. hidden within <RequirePermission>, use https://github.com/backstage/backstage/blob/518a34646b79ec2028cc0ed6bc67d4366c51c4d6/packages/core-app-api/src/routing/collectors.tsx#L69 + const plugin = getComponentData<LegacyBackstagePlugin>( + routeElement, + 'core.plugin', + ); + if (!plugin) { + return; + } + + const routeRef = getComponentData<RouteRef>( + routeElement, + 'core.mountPoint', + ); + + const pluginId = plugin.getId(); + const path: string = route.props.path; + + const detectedExtensions = new Array<Extension<unknown>>(); + + detectedExtensions.push( + createPageExtension({ + id: `plugin.${pluginId}.page`, + defaultPath: path[0] === '/' ? path.slice(1) : path, + routeRef: routeRef ? convertLegacyRouteRef(routeRef) : undefined, + + loader: async () => + route.props.children ? ( + <Routes> + <Route path="*" element={routeElement}> + <Route path="*" element={route.props.children} /> + </Route> + </Routes> + ) : ( + routeElement + ), + }), + ); + + detectedExtensions.push( + ...Array.from(plugin.getApis()).map(factory => + createApiExtension({ + factory, + }), + ), + ); + + results.push( + createPlugin({ + id: plugin.getId(), + extensions: detectedExtensions, + }), + ); + }, + ); + + return results; +} diff --git a/packages/core-compat-api/src/index.ts b/packages/core-compat-api/src/index.ts new file mode 100644 index 0000000000..2181b2fa9a --- /dev/null +++ b/packages/core-compat-api/src/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { collectLegacyRoutes } from './collectLegacyRoutes'; diff --git a/packages/core-compat-api/src/setupTests.ts b/packages/core-compat-api/src/setupTests.ts new file mode 100644 index 0000000000..865308e634 --- /dev/null +++ b/packages/core-compat-api/src/setupTests.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import '@testing-library/jest-dom'; diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index 1cab780f55..3ee6eae062 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/core-components +## 0.13.6 + +### Patch Changes + +- 4eab5cf901: The `TabbedLayout` component will now also navigate when clicking the active tab, which allows for navigation back from any sub routes. +- 0b55f773a7: Removed some unused dependencies +- 8a15360bb4: Fixed overflowing messages in `WarningPanel`. +- 997a71850c: Changed SupportButton menuitems to support text wrap +- 0296f272b4: Fixed the type declaration of `DependencyGraphProps`, the `defs` prop now expects `JSX.Element`s. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 16126dbe6a: Change overlay header colors in the mobile menu to use navigation color from the theme +- d19a827ef1: MissingAnnotationEmptyState component can now dynamically generate a YAML example based off the current entity being used. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## 0.13.6-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 8a15360bb4: Fixed overflowing messages in `WarningPanel`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/version-bridge@1.0.5 + ## 0.13.6-next.1 ### Patch Changes diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index 44a8b33e04..d40179dc62 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -249,7 +249,7 @@ export interface DependencyGraphProps<NodeData, EdgeData> acyclicer?: 'greedy'; align?: DependencyGraphTypes.Alignment; curve?: 'curveStepBefore' | 'curveMonotoneX'; - defs?: SVGDefsElement | SVGDefsElement[]; + defs?: JSX.Element | JSX.Element[]; direction?: DependencyGraphTypes.Direction; edgeMargin?: number; edgeRanks?: number; diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 155f0a09c4..842a52df43 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/core-components", "description": "Core components used by Backstage plugins and apps", - "version": "0.13.6-next.1", + "version": "0.13.6", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -61,7 +61,6 @@ "linkifyjs": "4.1.1", "lodash": "^4.17.21", "pluralize": "^8.0.0", - "prop-types": "^15.7.2", "qs": "^6.9.4", "rc-progress": "3.5.1", "react-helmet": "6.1.0", @@ -79,18 +78,17 @@ "zod": "^3.21.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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", diff --git a/packages/core-components/src/components/AutoLogout/disconnectedUsers.test.ts b/packages/core-components/src/components/AutoLogout/disconnectedUsers.test.ts index 87d6369eda..3d097dcc7f 100644 --- a/packages/core-components/src/components/AutoLogout/disconnectedUsers.test.ts +++ b/packages/core-components/src/components/AutoLogout/disconnectedUsers.test.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { act } from 'react-dom/test-utils'; import { diff --git a/packages/core-components/src/components/Avatar/util.test.ts b/packages/core-components/src/components/Avatar/util.test.ts index 6581df8b9a..98d0bd2550 100644 --- a/packages/core-components/src/components/Avatar/util.test.ts +++ b/packages/core-components/src/components/Avatar/util.test.ts @@ -17,25 +17,29 @@ import { extractInitials, stringToColor } from './utils'; describe('stringToColor', () => { - it('extract color', async () => { + it('extract color', () => { expect(stringToColor('Jenny Doe')).toEqual('#7809fa'); }); }); describe('extractInitials', () => { - it('extract initials', async () => { + it('extract initials', () => { expect(extractInitials('Jenny Doe')).toEqual('JD'); }); - it('extract unicode initials', async () => { + it('extract unicode initials', () => { expect(extractInitials('Petr Čech')).toEqual('PČ'); }); - it('extract single letter for short name', async () => { + it('extract single letter for short name', () => { expect(extractInitials('Doe')).toEqual('D'); }); - it('limit the initials to two letters', async () => { - expect(extractInitials('John Jonathan Doe')).toEqual('JJ'); + it('limit the initials to two letters', () => { + expect(extractInitials('John Jonathan Doe')).toEqual('JD'); + }); + + it('removes spaces from beginning or the end', () => { + expect(extractInitials(' John Jonathan Doe ')).toEqual('JD'); }); }); diff --git a/packages/core-components/src/components/Avatar/utils.ts b/packages/core-components/src/components/Avatar/utils.ts index 79627d5996..65e2be6afa 100644 --- a/packages/core-components/src/components/Avatar/utils.ts +++ b/packages/core-components/src/components/Avatar/utils.ts @@ -27,9 +27,11 @@ export function stringToColor(str: string) { return color; } -export function extractInitials(value: string) { - return value - .match(/(?<!\p{L})\p{L}/gu) - ?.join('') - .slice(0, 2); +export function extractInitials(name: string) { + const names = name.trim().split(' '); + const firstName = names[0] ?? ''; + const lastName = names.length > 1 ? names[names.length - 1] : ''; + return firstName && lastName + ? `${firstName.charAt(0)}${lastName.charAt(0)}` + : firstName.charAt(0); } diff --git a/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx b/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx index 4928292424..3dd1025b8f 100644 --- a/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx +++ b/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx @@ -144,7 +144,7 @@ export interface DependencyGraphProps<NodeData, EdgeData> * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs | Defs} shared by rendered SVG to be used by * {@link DependencyGraphProps.renderNode} and/or {@link DependencyGraphProps.renderLabel} */ - defs?: SVGDefsElement | SVGDefsElement[]; + defs?: JSX.Element | JSX.Element[]; /** * Controls zoom behavior of graph * diff --git a/packages/core-components/src/components/Link/Link.test.tsx b/packages/core-components/src/components/Link/Link.test.tsx index f88d830479..42668b54c9 100644 --- a/packages/core-components/src/components/Link/Link.test.tsx +++ b/packages/core-components/src/components/Link/Link.test.tsx @@ -14,8 +14,8 @@ * limitations under the License. */ -import React from 'react'; -import { fireEvent, waitFor, screen } from '@testing-library/react'; +import React, { ComponentType } from 'react'; +import { fireEvent, waitFor, screen, renderHook } from '@testing-library/react'; import { MockAnalyticsApi, TestApiProvider, @@ -24,7 +24,6 @@ import { import { analyticsApiRef, configApiRef } from '@backstage/core-plugin-api'; import { isExternalUri, Link, useResolvedPath } from './Link'; import { Route, Routes } from 'react-router-dom'; -import { renderHook, WrapperComponent } from '@testing-library/react-hooks'; import { ConfigReader } from '@backstage/config'; describe('<Link />', () => { @@ -128,7 +127,7 @@ describe('<Link />', () => { }); describe('useResolvedPath', () => { - const wrapper: WrapperComponent<React.PropsWithChildren<{}>> = ({ + const wrapper: ComponentType<React.PropsWithChildren<{}>> = ({ children, }) => { const configApi = new ConfigReader({ diff --git a/packages/core-components/src/components/LogViewer/useLogViewerSearch.test.tsx b/packages/core-components/src/components/LogViewer/useLogViewerSearch.test.tsx index a64f22765b..1b54f552a5 100644 --- a/packages/core-components/src/components/LogViewer/useLogViewerSearch.test.tsx +++ b/packages/core-components/src/components/LogViewer/useLogViewerSearch.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import { applySearchFilter, useLogViewerSearch } from './useLogViewerSearch'; import { AnsiLine } from './AnsiProcessor'; diff --git a/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx b/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx index a828818ed5..6c6f7da71b 100644 --- a/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx +++ b/packages/core-components/src/components/LogViewer/useLogViewerSelection.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import { TestApiProvider, MockErrorApi } from '@backstage/test-utils'; import { errorApiRef } from '@backstage/core-plugin-api'; import { AnsiLine } from './AnsiProcessor'; diff --git a/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx b/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx index f5a059d615..c7109686d5 100644 --- a/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx +++ b/packages/core-components/src/components/TabbedLayout/TabbedLayout.test.tsx @@ -48,6 +48,11 @@ describe('TabbedLayout', () => { }); expect(error).toEqual([ + expect.objectContaining({ + detail: new Error( + 'Child of TabbedLayout must be an TabbedLayout.Route', + ), + }), expect.objectContaining({ detail: new Error( 'Child of TabbedLayout must be an TabbedLayout.Route', diff --git a/packages/core-components/src/components/Table/Table.tsx b/packages/core-components/src/components/Table/Table.tsx index 9f2b04c214..e4ee9b5995 100644 --- a/packages/core-components/src/components/Table/Table.tsx +++ b/packages/core-components/src/components/Table/Table.tsx @@ -455,7 +455,7 @@ export function Table<T extends object = {}>(props: TableProps<T>) { const hasFilters = !!filters?.length; const Toolbar = useCallback( - toolbarProps => { + (toolbarProps: any /* no type for this in material-table */) => { return ( <TableToolbar setSearch={setSearch} @@ -472,7 +472,7 @@ export function Table<T extends object = {}>(props: TableProps<T>) { const hasNoRows = typeof data !== 'function' && data.length === 0; const columnCount = columns.length; const Body = useCallback( - bodyProps => { + (bodyProps: any /* no type for this in material-table */) => { if (isLoading) { return ( <tbody data-testid="loading-indicator"> diff --git a/packages/core-components/src/components/WarningPanel/WarningPanel.tsx b/packages/core-components/src/components/WarningPanel/WarningPanel.tsx index 7e8248115f..f4dc298b1e 100644 --- a/packages/core-components/src/components/WarningPanel/WarningPanel.tsx +++ b/packages/core-components/src/components/WarningPanel/WarningPanel.tsx @@ -69,6 +69,9 @@ export type WarningPanelClassKey = const useStyles = makeStyles<BackstageTheme>( theme => ({ + content: { + lineBreak: 'anywhere', + }, panel: { backgroundColor: ({ severity }: WarningProps) => getWarningBackgroundColor( @@ -168,6 +171,7 @@ export function WarningPanel(props: WarningProps) { > <AccordionSummary expandIcon={<ExpandMoreIconStyled severity={severity} />} + classes={{ content: classes.content }} className={classes.summary} > <ErrorOutlineStyled severity={severity} /> diff --git a/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx b/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx index 6a16224a02..8bfb228f53 100644 --- a/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx +++ b/packages/core-components/src/layout/ErrorBoundary/ErrorBoundary.test.tsx @@ -67,6 +67,9 @@ describe('<ErrorBoundary/>', () => { }); expect(error).toEqual([ + expect.objectContaining({ + detail: new Error('Bomb'), + }), expect.objectContaining({ detail: new Error('Bomb'), }), @@ -75,6 +78,6 @@ describe('<ErrorBoundary/>', () => { ), expect.stringMatching(/^ErrorBoundary/), ]); - expect(error.length).toEqual(3); + expect(error.length).toEqual(4); }); }); diff --git a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx index ce5c572eef..f656696f8a 100644 --- a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx +++ b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx @@ -19,6 +19,7 @@ import Badge from '@material-ui/core/Badge'; import { makeStyles } from '@material-ui/core/styles'; import React from 'react'; import { HeaderTabs } from './HeaderTabs'; +import userEvent from '@testing-library/user-event'; const mockTabs = [ { id: 'overview', label: 'Overview' }, @@ -41,7 +42,7 @@ describe('<HeaderTabs />', () => { 'false', ); - rendered.getByText('Docs').click(); + await userEvent.click(rendered.getByText('Docs')); expect(rendered.getByText('Docs').parentElement).toHaveAttribute( 'aria-selected', diff --git a/packages/core-components/src/layout/Sidebar/Items.test.tsx b/packages/core-components/src/layout/Sidebar/Items.test.tsx index 9479180180..6c959bfd0d 100644 --- a/packages/core-components/src/layout/Sidebar/Items.test.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.test.tsx @@ -26,7 +26,7 @@ import HomeIcon from '@material-ui/icons/Home'; import CreateComponentIcon from '@material-ui/icons/AddCircleOutline'; import { Sidebar } from './Bar'; import { SidebarItem, SidebarSearchField, SidebarExpandButton } from './Items'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { makeStyles } from '@material-ui/core/styles'; import { analyticsApiRef } from '@backstage/core-plugin-api'; diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index c40d45f8b4..aba4c79181 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -312,7 +312,11 @@ const sidebarSubmenuType = React.createElement(SidebarSubmenu).type; // properly yet, matching for example /foobar with /foo. export const WorkaroundNavLink = React.forwardRef< HTMLAnchorElement, - NavLinkProps & { activeStyle?: CSSProperties; activeClassName?: string } + NavLinkProps & { + children?: ReactNode; + activeStyle?: CSSProperties; + activeClassName?: string; + } >(function WorkaroundNavLinkWithRef( { to, @@ -361,7 +365,10 @@ export const WorkaroundNavLink = React.forwardRef< /** * Common component used by SidebarItem & SidebarItemWithSubmenu */ -const SidebarItemBase = forwardRef<any, SidebarItemProps>((props, ref) => { +const SidebarItemBase = forwardRef< + any, + SidebarItemProps & { children: ReactNode } +>((props, ref) => { const { icon: Icon, text, @@ -553,7 +560,10 @@ const SidebarItemWithSubmenu = ({ * @remarks * If children contain a `SidebarSubmenu` component the `SidebarItem` will have a expandable submenu */ -export const SidebarItem = forwardRef<any, SidebarItemProps>((props, ref) => { +export const SidebarItem = forwardRef< + any, + SidebarItemProps & { children: ReactNode } +>((props, ref) => { // Filter children for SidebarSubmenu components const [submenu] = useElementFilter(props.children, elements => // Directly comparing child.type with SidebarSubmenu will not work with in diff --git a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx index e124036648..88d653cea5 100644 --- a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx +++ b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx @@ -25,7 +25,7 @@ import Typography from '@material-ui/core/Typography'; import CloseIcon from '@material-ui/icons/Close'; import MenuIcon from '@material-ui/icons/Menu'; import { orderBy } from 'lodash'; -import React, { useEffect, useState, useContext } from 'react'; +import React, { useEffect, useState, useContext, ReactNode } from 'react'; import { useLocation } from 'react-router-dom'; import { SidebarOpenStateProvider } from './SidebarOpenStateContext'; import { SidebarGroup } from './SidebarGroup'; @@ -206,8 +206,7 @@ export const MobileSidebar = (props: MobileSidebarProps) => { onClose={() => setSelectedMenuItemIndex(-1)} > {sidebarGroups[selectedMenuItemIndex] && - (sidebarGroups[selectedMenuItemIndex].props - .children as React.ReactChildren)} + (sidebarGroups[selectedMenuItemIndex].props.children as ReactNode)} </OverlayMenu> <BottomNavigation className={classes.root} diff --git a/packages/core-components/src/layout/Sidebar/Sidebar.stories.tsx b/packages/core-components/src/layout/Sidebar/Sidebar.stories.tsx index f647166250..342a9b2a29 100644 --- a/packages/core-components/src/layout/Sidebar/Sidebar.stories.tsx +++ b/packages/core-components/src/layout/Sidebar/Sidebar.stories.tsx @@ -59,7 +59,7 @@ const handleSearch = (input: string) => { export const SampleSidebar = () => ( <SidebarPage> <Sidebar> - <SidebarGroup label="Menu" icon={MenuIcon}> + <SidebarGroup label="Menu" icon={<MenuIcon />}> <SidebarSearchField onSearch={handleSearch} to="/search" /> <SidebarDivider /> <SidebarItem icon={HomeOutlinedIcon} to="#" text="Plugins" /> diff --git a/packages/core-components/src/layout/Sidebar/SidebarOpenStateContext.test.tsx b/packages/core-components/src/layout/Sidebar/SidebarOpenStateContext.test.tsx index f1900f025c..8cc6f7858c 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarOpenStateContext.test.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarOpenStateContext.test.tsx @@ -16,7 +16,7 @@ import React, { ReactNode, useContext } from 'react'; import { renderWithEffects } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { LegacySidebarContext, SidebarOpenStateProvider, diff --git a/packages/core-components/src/layout/Sidebar/SidebarPinStateContext.test.tsx b/packages/core-components/src/layout/Sidebar/SidebarPinStateContext.test.tsx index 8bd1597725..8f6660707d 100644 --- a/packages/core-components/src/layout/Sidebar/SidebarPinStateContext.test.tsx +++ b/packages/core-components/src/layout/Sidebar/SidebarPinStateContext.test.tsx @@ -16,7 +16,7 @@ import React, { ReactNode, useContext } from 'react'; import { renderWithEffects } from '@backstage/test-utils'; import { waitFor } from '@testing-library/react'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { LegacySidebarPinStateContext, SidebarPinStateProvider, diff --git a/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx b/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx index a09ea11b3d..4e75878a7d 100644 --- a/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx +++ b/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx @@ -96,7 +96,9 @@ export function TabbedCard(props: PropsWithChildren<Props>) { } else { React.Children.map(children, child => { if ( - React.isValidElement<{ children?: unknown; value?: unknown }>(child) && + React.isValidElement<{ children?: ReactNode; value?: unknown }>( + child, + ) && child?.props.value === value ) { selectedTabContent = child?.props.children; diff --git a/packages/core-plugin-api/CHANGELOG.md b/packages/core-plugin-api/CHANGELOG.md index d206487074..e35fd4d6a3 100644 --- a/packages/core-plugin-api/CHANGELOG.md +++ b/packages/core-plugin-api/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/core-plugin-api +## 1.7.0 + +### Minor Changes + +- 322bbcae24: Removed the exprimental plugin configuration API. The `__experimentalReconfigure()` from the plugin options as well as the `__experimentalConfigure()` method on plugin instances have both been removed. + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/version-bridge@1.0.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 1.7.0-next.1 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + ## 1.7.0-next.0 ### Minor Changes diff --git a/packages/core-plugin-api/alpha-api-report.md b/packages/core-plugin-api/alpha-api-report.md index ba3583142f..0284d691a9 100644 --- a/packages/core-plugin-api/alpha-api-report.md +++ b/packages/core-plugin-api/alpha-api-report.md @@ -3,8 +3,12 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { AnyRouteRefParams } from '@backstage/core-plugin-api'; import { ApiRef } from '@backstage/core-plugin-api'; +import { ExternalRouteRef } from '@backstage/core-plugin-api'; import { Observable } from '@backstage/types'; +import { RouteRef } from '@backstage/core-plugin-api'; +import { SubRouteRef } from '@backstage/core-plugin-api'; import { TranslationMessages as TranslationMessages_2 } from '@backstage/core-plugin-api/alpha'; import { TranslationRef as TranslationRef_2 } from '@backstage/core-plugin-api/alpha'; @@ -25,6 +29,24 @@ export type AppLanguageApi = { // @alpha (undocumented) export const appLanguageApiRef: ApiRef<AppLanguageApi>; +// @public +export function convertLegacyRouteRef<TParams extends AnyRouteRefParams>( + ref: RouteRef<TParams>, +): NewRouteRef<TParams>; + +// @public +export function convertLegacyRouteRef<TParams extends AnyRouteRefParams>( + ref: SubRouteRef<TParams>, +): NewSubRouteRef<TParams>; + +// @public +export function convertLegacyRouteRef< + TParams extends AnyRouteRefParams, + TOptional extends boolean, +>( + ref: ExternalRouteRef<TParams, TOptional>, +): NewExternalRouteRef<TParams, TOptional>; + // @alpha export function createTranslationMessages< TId extends string, diff --git a/packages/core-plugin-api/api-report.md b/packages/core-plugin-api/api-report.md index 7873b23f13..789fc2bfdc 100644 --- a/packages/core-plugin-api/api-report.md +++ b/packages/core-plugin-api/api-report.md @@ -95,8 +95,11 @@ export type AnyExternalRoutes = { [name: string]: ExternalRouteRef; }; +// @public @deprecated (undocumented) +export type AnyParams = AnyRouteRefParams; + // @public -export type AnyParams = +export type AnyRouteRefParams = | { [param in string]: string; } @@ -523,7 +526,7 @@ export type IdentityApi = { // @public export const identityApiRef: ApiRef<IdentityApi>; -// @public +// @public @deprecated export type MakeSubRouteRef< Params extends { [param in string]: string; @@ -533,7 +536,7 @@ export type MakeSubRouteRef< ? SubRouteRef<OptionalParams<MergeParams<Params, ParentParams>>> : never; -// @public +// @public @deprecated export type MergeParams< P1 extends { [param in string]: string; @@ -606,30 +609,30 @@ export type OpenIdConnectApi = { getIdToken(options?: AuthRequestOptions): Promise<string>; }; -// @public +// @public @deprecated export type OptionalParams< Params extends { [param in string]: string; }, > = Params[keyof Params] extends never ? undefined : Params; -// @public +// @public @deprecated export type ParamKeys<Params extends AnyParams> = keyof Params extends never ? [] : (keyof Params)[]; -// @public +// @public @deprecated export type ParamNames<S extends string> = S extends `${infer Part}/${infer Rest}` ? ParamPart<Part> | ParamNames<Rest> : ParamPart<S>; -// @public +// @public @deprecated export type ParamPart<S extends string> = S extends `:${infer Param}` ? Param : never; -// @public +// @public @deprecated export type PathParams<S extends string> = { [name in ParamNames<S>]: string; }; diff --git a/packages/core-plugin-api/package.json b/packages/core-plugin-api/package.json index 64fdd00915..42f3b8b4d4 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.7.0-next.0", + "version": "1.7.0", "publishConfig": { "access": "public" }, @@ -51,27 +51,21 @@ "@backstage/version-bridge": "workspace:^", "@types/react": "^16.13.1 || ^17.0.0", "history": "^5.0.0", - "i18next": "^22.4.15", - "prop-types": "^15.7.2", - "zen-observable": "^0.10.0" + "i18next": "^22.4.15" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.0.0", - "@testing-library/user-event": "^14.0.0", - "@types/prop-types": "^15.7.3", - "@types/zen-observable": "^0.8.0", - "msw": "^1.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" }, "files": [ "dist" diff --git a/packages/core-plugin-api/src/alpha.ts b/packages/core-plugin-api/src/alpha.ts index ebcbcf34c0..540b4ed22a 100644 --- a/packages/core-plugin-api/src/alpha.ts +++ b/packages/core-plugin-api/src/alpha.ts @@ -16,3 +16,4 @@ export * from './translation'; export * from './apis/alpha'; +export { convertLegacyRouteRef } from './routing/convertLegacyRouteRef'; diff --git a/packages/core-plugin-api/src/analytics/AnalyticsContext.test.tsx b/packages/core-plugin-api/src/analytics/AnalyticsContext.test.tsx index 88e8afa6ef..c29ec5b3ca 100644 --- a/packages/core-plugin-api/src/analytics/AnalyticsContext.test.tsx +++ b/packages/core-plugin-api/src/analytics/AnalyticsContext.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { render } from '@testing-library/react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { AnalyticsContext, useAnalyticsContext } from './AnalyticsContext'; const AnalyticsSpy = () => { diff --git a/packages/core-plugin-api/src/analytics/useAnalytics.test.tsx b/packages/core-plugin-api/src/analytics/useAnalytics.test.tsx index 22021026af..037e585430 100644 --- a/packages/core-plugin-api/src/analytics/useAnalytics.test.tsx +++ b/packages/core-plugin-api/src/analytics/useAnalytics.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useAnalytics } from './useAnalytics'; import { useApi } from '../apis'; diff --git a/packages/core-plugin-api/src/apis/system/useApi.test.tsx b/packages/core-plugin-api/src/apis/system/useApi.test.tsx index 6f473d8f59..4b9d80fb62 100644 --- a/packages/core-plugin-api/src/apis/system/useApi.test.tsx +++ b/packages/core-plugin-api/src/apis/system/useApi.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { createVersionedContextForTesting } from '@backstage/version-bridge'; import { createApiRef } from './ApiRef'; import { useApi } from './useApi'; diff --git a/packages/core-plugin-api/src/app/useApp.test.tsx b/packages/core-plugin-api/src/app/useApp.test.tsx index f2e330e847..34c956138e 100644 --- a/packages/core-plugin-api/src/app/useApp.test.tsx +++ b/packages/core-plugin-api/src/app/useApp.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { createVersionedContextForTesting } from '@backstage/version-bridge'; import { useApp } from './useApp'; diff --git a/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx b/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx index 8795ecdded..8597274e35 100644 --- a/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx +++ b/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx @@ -15,7 +15,7 @@ */ import React, { ReactNode } from 'react'; import { useElementFilter } from './useElementFilter'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { attachComponentData } from './componentData'; import { featureFlagsApiRef } from '../apis'; import { LocalStorageFeatureFlags } from '@backstage/core-app-api'; @@ -41,7 +41,12 @@ const FeatureFlagComponent = (_props: { }) => null; attachComponentData(FeatureFlagComponent, 'core.featureFlagged', true); const mockFeatureFlagsApi = new LocalStorageFeatureFlags(); -const Wrapper = ({ children }: { children?: React.ReactNode }) => ( +const Wrapper = ({ + children, +}: { + children?: React.ReactNode; + tree?: ReactNode; +}) => ( <TestApiProvider apis={[[featureFlagsApiRef, mockFeatureFlagsApi]]}> {children} </TestApiProvider> @@ -311,23 +316,23 @@ describe('useElementFilter', () => { </MockComponent> ); - const { result } = renderHook( - props => - useElementFilter(props.tree, elements => - elements - .selectByComponentData({ - key: WRAPPING_COMPONENT_KEY, - withStrictError: 'Could not find component', - }) - .findComponentData({ key: INNER_COMPONENT_KEY }), - ), - { - initialProps: { tree }, - wrapper: Wrapper, - }, - ); - - expect(result.error?.message).toEqual('Could not find component'); + expect(() => + renderHook( + props => + useElementFilter(props.tree, elements => + elements + .selectByComponentData({ + key: WRAPPING_COMPONENT_KEY, + withStrictError: 'Could not find component', + }) + .findComponentData({ key: INNER_COMPONENT_KEY }), + ), + { + initialProps: { tree }, + wrapper: Wrapper, + }, + ), + ).toThrow('Could not find component'); }); it('should support fragments and text node iteration', () => { diff --git a/packages/core-plugin-api/src/routing/SubRouteRef.ts b/packages/core-plugin-api/src/routing/SubRouteRef.ts index 14a614c2ba..b08368d74e 100644 --- a/packages/core-plugin-api/src/routing/SubRouteRef.ts +++ b/packages/core-plugin-api/src/routing/SubRouteRef.ts @@ -51,6 +51,7 @@ export class SubRouteRefImpl<Params extends AnyParams> /** * Used in {@link PathParams} type declaration. * @public + * @deprecated this type is deprecated and will be removed in the future */ export type ParamPart<S extends string> = S extends `:${infer Param}` ? Param @@ -59,6 +60,7 @@ export type ParamPart<S extends string> = S extends `:${infer Param}` /** * Used in {@link PathParams} type declaration. * @public + * @deprecated this type is deprecated and will be removed in the future */ export type ParamNames<S extends string> = S extends `${infer Part}/${infer Rest}` @@ -68,12 +70,14 @@ export type ParamNames<S extends string> = * This utility type helps us infer a Param object type from a string path * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }` * @public + * @deprecated this type is deprecated and will be removed in the future */ export type PathParams<S extends string> = { [name in ParamNames<S>]: string }; /** * Merges a param object type with an optional params type into a params object. * @public + * @deprecated this type is deprecated and will be removed in the future */ export type MergeParams< P1 extends { [param in string]: string }, @@ -85,6 +89,7 @@ export type MergeParams< * The parameters types are merged together while ensuring that there is no overlap between the two. * * @public + * @deprecated this type is deprecated and will be removed in the future */ export type MakeSubRouteRef< Params extends { [param in string]: string }, diff --git a/packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts b/packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts new file mode 100644 index 0000000000..940a4174a9 --- /dev/null +++ b/packages/core-plugin-api/src/routing/convertLegacyRouteRef.ts @@ -0,0 +1,188 @@ +/* + * 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 { routeRefType } from './types'; +import { + RouteRef as LegacyRouteRef, + SubRouteRef as LegacySubRouteRef, + ExternalRouteRef as LegacyExternalRouteRef, + AnyRouteRefParams, +} from '@backstage/core-plugin-api'; + +// Relative imports to avoid dependency, at least for now + +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { + RouteRef, + SubRouteRef, + ExternalRouteRef, + createRouteRef, + createSubRouteRef, + createExternalRouteRef, +} from '../../../frontend-plugin-api/src/routing'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalRouteRef } from '../../../frontend-plugin-api/src/routing/RouteRef'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalSubRouteRef } from '../../../frontend-plugin-api/src/routing/SubRouteRef'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef'; + +// TODO(Rugvip): Once this is moved to a compat package these aliases can be removed and imported from frontend- instead + +/** @ignore */ +type NewRouteRef<TParams extends AnyRouteRefParams = AnyRouteRefParams> = + RouteRef<TParams>; + +/** @ignore */ +type NewSubRouteRef<TParams extends AnyRouteRefParams = AnyRouteRefParams> = + SubRouteRef<TParams>; + +/** @ignore */ +type NewExternalRouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, + TOptional extends boolean = boolean, +> = ExternalRouteRef<TParams, TOptional>; + +/** + * A temporary helper to convert a legacy route ref to the new system. + * + * @public + * @remarks + * + * In the future the legacy createRouteRef will instead create refs compatible with both systems. + */ +export function convertLegacyRouteRef<TParams extends AnyRouteRefParams>( + ref: LegacyRouteRef<TParams>, +): NewRouteRef<TParams>; + +/** + * A temporary helper to convert a legacy sub route ref to the new system. + * + * @public + * @remarks + * + * In the future the legacy createSubRouteRef will instead create refs compatible with both systems. + */ +export function convertLegacyRouteRef<TParams extends AnyRouteRefParams>( + ref: LegacySubRouteRef<TParams>, +): NewSubRouteRef<TParams>; + +/** + * A temporary helper to convert a legacy external route ref to the new system. + * + * @public + * @remarks + * + * In the future the legacy createExternalRouteRef will instead create refs compatible with both systems. + */ +export function convertLegacyRouteRef< + TParams extends AnyRouteRefParams, + TOptional extends boolean, +>( + ref: LegacyExternalRouteRef<TParams, TOptional>, +): NewExternalRouteRef<TParams, TOptional>; + +export function convertLegacyRouteRef( + ref: LegacyRouteRef | LegacySubRouteRef | LegacyExternalRouteRef, +): NewRouteRef | NewSubRouteRef | NewExternalRouteRef { + // Ref has already been converted + if ('$$type' in ref) { + return ref as unknown as NewRouteRef | NewSubRouteRef | NewExternalRouteRef; + } + + const type = (ref as unknown as { [routeRefType]: unknown })[routeRefType]; + + if (type === 'absolute') { + const legacyRef = ref as LegacyRouteRef; + const newRef = toInternalRouteRef( + createRouteRef<{ [key in string]: string }>({ + params: legacyRef.params as string[], + }), + ); + return Object.assign(legacyRef, { + $$type: '@backstage/RouteRef' as const, + version: 'v1', + T: newRef.T, + getParams() { + return newRef.getParams(); + }, + getDescription() { + return newRef.getDescription(); + }, + setId(id: string) { + newRef.setId(id); + }, + toString() { + return newRef.toString(); + }, + }); + } + if (type === 'sub') { + const legacyRef = ref as LegacySubRouteRef; + const newRef = toInternalSubRouteRef( + createSubRouteRef({ + path: legacyRef.path, + parent: convertLegacyRouteRef(legacyRef.parent), + }), + ); + return Object.assign(legacyRef, { + $$type: '@backstage/SubRouteRef' as const, + version: 'v1', + T: newRef.T, + getParams() { + return newRef.getParams(); + }, + getParent() { + return newRef.getParent(); + }, + getDescription() { + return newRef.getDescription(); + }, + toString() { + return newRef.toString(); + }, + }); + } + if (type === 'external') { + const legacyRef = ref as LegacyExternalRouteRef; + const newRef = toInternalExternalRouteRef( + createExternalRouteRef<{ [key in string]: string }>({ + params: legacyRef.params as string[], + optional: legacyRef.optional, + }), + ); + return Object.assign(legacyRef, { + $$type: '@backstage/ExternalRouteRef' as const, + version: 'v1', + T: newRef.T, + optional: newRef.optional, + getParams() { + return newRef.getParams(); + }, + getDescription() { + return newRef.getDescription(); + }, + setId(id: string) { + newRef.setId(id); + }, + toString() { + return newRef.toString(); + }, + }); + } + + throw new Error(`Failed to convert legacy route ref, unknown type '${type}'`); +} diff --git a/packages/core-plugin-api/src/routing/index.ts b/packages/core-plugin-api/src/routing/index.ts index 01d69cd4b0..4f8b12ec73 100644 --- a/packages/core-plugin-api/src/routing/index.ts +++ b/packages/core-plugin-api/src/routing/index.ts @@ -16,6 +16,7 @@ export type { AnyParams, + AnyRouteRefParams, RouteRef, SubRouteRef, ExternalRouteRef, diff --git a/packages/core-plugin-api/src/routing/types.ts b/packages/core-plugin-api/src/routing/types.ts index 80653518bb..32f26f19c1 100644 --- a/packages/core-plugin-api/src/routing/types.ts +++ b/packages/core-plugin-api/src/routing/types.ts @@ -21,12 +21,19 @@ import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; * * @public */ -export type AnyParams = { [param in string]: string } | undefined; +export type AnyRouteRefParams = { [param in string]: string } | undefined; + +/** + * @deprecated use {@link AnyRouteRefParams} instead + * @public + */ +export type AnyParams = AnyRouteRefParams; /** * Type describing the key type of a route parameter mapping. * * @public + * @deprecated this type is deprecated and will be removed in the future */ export type ParamKeys<Params extends AnyParams> = keyof Params extends never ? [] @@ -36,6 +43,7 @@ export type ParamKeys<Params extends AnyParams> = keyof Params extends never * Optional route params. * * @public + * @deprecated this type is deprecated and will be removed in the future */ export type OptionalParams<Params extends { [param in string]: string }> = Params[keyof Params] extends never ? undefined : Params; @@ -81,8 +89,10 @@ export const routeRefType: unique symbol = getOrCreateGlobalSingleton<any>( * @public */ export type RouteRef<Params extends AnyParams = any> = { + /** @deprecated access to this property will be removed in the future */ $$routeRefType: 'absolute'; // See routeRefType above + /** @deprecated access to this property will be removed in the future */ params: ParamKeys<Params>; }; @@ -96,12 +106,15 @@ export type RouteRef<Params extends AnyParams = any> = { * @public */ export type SubRouteRef<Params extends AnyParams = any> = { + /** @deprecated access to this property will be removed in the future */ $$routeRefType: 'sub'; // See routeRefType above + /** @deprecated access to this property will be removed in the future */ parent: RouteRef; path: string; + /** @deprecated access to this property will be removed in the future */ params: ParamKeys<Params>; }; @@ -118,8 +131,10 @@ export type ExternalRouteRef< Params extends AnyParams = any, Optional extends boolean = any, > = { + /** @deprecated access to this property will be removed in the future */ $$routeRefType: 'external'; // See routeRefType above + /** @deprecated access to this property will be removed in the future */ params: ParamKeys<Params>; optional?: Optional; diff --git a/packages/core-plugin-api/src/routing/useRouteRef.test.tsx b/packages/core-plugin-api/src/routing/useRouteRef.test.tsx index 7a03a1cdc4..b302fa6441 100644 --- a/packages/core-plugin-api/src/routing/useRouteRef.test.tsx +++ b/packages/core-plugin-api/src/routing/useRouteRef.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import React from 'react'; import { MemoryRouter, Router } from 'react-router-dom'; import { createVersionedContextForTesting } from '@backstage/version-bridge'; diff --git a/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx b/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx index a8dbdc0402..a7493152de 100644 --- a/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx +++ b/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx @@ -20,7 +20,7 @@ import { TestApiProvider, withLogCollector, } from '@backstage/test-utils'; -import { renderHook } from '@testing-library/react-hooks'; +import { act, renderHook, waitFor } from '@testing-library/react'; import { createTranslationRef, TranslationRef } from './TranslationRef'; import { useTranslationRef } from './useTranslationRef'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports @@ -91,19 +91,15 @@ describe('useTranslationRef', () => { ], }); - const { result, waitForNextUpdate } = renderHook( - () => useTranslationRef(plainRef), - { - wrapper: makeWrapper(translationApi), - }, - ); + const { result } = renderHook(() => useTranslationRef(plainRef), { + wrapper: makeWrapper(translationApi), + }); - await waitForNextUpdate(); - - const { t } = result.current; - - expect(t('key1')).toBe('en1'); - expect(t('key2')).toBe('en2'); + await waitFor(() => { + const { t } = result.current; + expect(t('key1')).toBe('en1'); + expect(t('key2')).toBe('en2'); + }); }); it('should switch between languages', async () => { @@ -123,26 +119,25 @@ describe('useTranslationRef', () => { ], }); - const { result, waitForNextUpdate } = renderHook( - () => useTranslationRef(plainRef), - { - wrapper: makeWrapper(translationApi), - }, - ); + const { result } = renderHook(() => useTranslationRef(plainRef), { + wrapper: makeWrapper(translationApi), + }); - const { t } = result.current; + await waitFor(() => { + const { t } = result.current; - expect(t('key1')).toBe('default1'); - expect(t('key2')).toBe('default2'); + expect(t('key1')).toBe('default1'); + expect(t('key2')).toBe('default2'); + }); languageApi.setLanguage('de'); - await waitForNextUpdate(); + await waitFor(() => { + const { t: t2 } = result.current; - const { t: t2 } = result.current; - - expect(t2('key1')).toBe('de1'); - expect(t2('key2')).toBe('de2'); + expect(t2('key1')).toBe('de1'); + expect(t2('key2')).toBe('de2'); + }); }); it('should load default resource', async () => { @@ -165,19 +160,16 @@ describe('useTranslationRef', () => { languageApi, }); - const { result, waitForNextUpdate } = renderHook( - () => useTranslationRef(resourceRef), - { - wrapper: makeWrapper(translationApi), - }, - ); + const { result } = renderHook(() => useTranslationRef(resourceRef), { + wrapper: makeWrapper(translationApi), + }); - await waitForNextUpdate(); + await waitFor(() => { + const { t } = result.current; - const { t } = result.current; - - expect(t('key1')).toBe('de1'); - expect(t('key2')).toBe('de2'); + expect(t('key1')).toBe('de1'); + expect(t('key2')).toBe('de2'); + }); }); it('should log once and then ignore loading errors', async () => { @@ -212,7 +204,7 @@ describe('useTranslationRef', () => { }); const { error } = await withLogCollector(['error'], async () => { - await rendered2.waitForNextUpdate(); + await act(rendered2.rerender); }); const msg = @@ -303,7 +295,12 @@ describe('useTranslationRef', () => { const translationApi = I18nextTranslationApi.create({ languageApi }); const { result, rerender } = renderHook( - ({ translationRef }) => useTranslationRef(translationRef), + ({ + translationRef, + }: { + translationRef: TranslationRef; + children?: ReactNode; + }) => useTranslationRef(translationRef), { wrapper: ({ children }) => ( <TestApiProvider diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index fed5a6b936..25728675d6 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/create-app +## 0.5.6 + +### Patch Changes + +- ba6a3b59c1: Removed duplicate `apple-touch-icon` link from `packages/app/public/index.html` that linked to nonexistent icon. +- c8ec0dea4a: Create unique temp directory for each `create-app` execution. +- e43d3eb1b7: Bumped create-app version. +- b665f2ce65: Change base node image from node:18-bullseye-slim to node:18-bookworm-slim due to Docker build error on bullseye. + + You can apply these change to your own `Dockerfile` by replacing `node:18-bullseye-slim` with `node:18-bookworm-slim` + +- deed089a3d: Bump `cypress` to fix the end-to-end tests +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- 04a3f65e15: Bump Docker base images to `node:18-bookworm-slim` to fix node compatibility issues raised during image build. + + You can apply these change to your own `Dockerfile` by replacing `node:16-bullseye-slim` with `node:18-bookworm-slim` + +- 9864f263ba: Bump dev dependencies `lerna@7.3.0` on the template +- 5eacd5d213: The E2E test setup based on Cypress has been replaced with one based on [Playwright](https://playwright.dev/). Migrating existing apps is not required as this is a standalone setup, only do so if you also want to switch from Cypress to Playwright. + + The scripts to run the E2E tests have been removed from `packages/app/package.json`, as they are now instead run from the root. Instead, a new script has been added to the root `package.json`, `yarn test:e2e`, which runs the E2E tests in development mode, unless `CI` is set in the environment. + + The Playwright setup uses utilities from the new `@backstage/e2e-test-utils` package to find and include all packages in the monorepo that have an `e2e-tests` folder. + +- 8d2e640af4: Added missing `.eslintignore` file + + To apply this change to an existing app, create a new `.eslintignore` file at the root of your project with the following content: + + ```diff + + playwright.config.ts + ``` + +- Updated dependencies + - @backstage/cli-common@0.1.13 + +## 0.5.6-next.2 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.13-next.0 + ## 0.5.6-next.1 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 6ae88a8e4c..597908c894 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.6-next.1", + "version": "0.5.6", "publishConfig": { "access": "public" }, @@ -42,6 +42,7 @@ "recursive-readdir": "^2.2.2" }, "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", diff --git a/packages/create-app/src/createApp.test.ts b/packages/create-app/src/createApp.test.ts index 7cb9733567..844d2aee1b 100644 --- a/packages/create-app/src/createApp.test.ts +++ b/packages/create-app/src/createApp.test.ts @@ -15,13 +15,13 @@ */ import inquirer from 'inquirer'; -import mockFs from 'mock-fs'; import path from 'path'; import { Command } from 'commander'; import * as tasks from './lib/tasks'; import createApp from './createApp'; import { findPaths } from '@backstage/cli-common'; import { tmpdir } from 'os'; +import { createMockDirectory } from '@backstage/backend-test-utils'; jest.mock('./lib/tasks'); @@ -40,16 +40,7 @@ const moveAppMock = jest.spyOn(tasks, 'moveAppTask'); const buildAppMock = jest.spyOn(tasks, 'buildAppTask'); describe('command entrypoint', () => { - beforeEach(() => { - mockFs({ - [`${__dirname}/package.json`]: '', // required by `findPaths(__dirname)` - 'templates/': mockFs.load(path.resolve(__dirname, '../templates/')), - }); - }); - - afterEach(() => { - mockFs.restore(); - }); + const mockDir = createMockDirectory({ mockOsTmpDir: true }); beforeEach(() => { promptMock.mockResolvedValueOnce({ @@ -62,6 +53,7 @@ describe('command entrypoint', () => { }); afterEach(() => { + mockDir.clear(); jest.resetAllMocks(); }); @@ -75,7 +67,6 @@ describe('command entrypoint', () => { findPaths(__dirname).resolveTarget( 'packages', 'create-app', - 'src', 'templates', 'default-app', ), @@ -97,7 +88,6 @@ describe('command entrypoint', () => { findPaths(__dirname).resolveTarget( 'packages', 'create-app', - 'src', 'templates', 'default-app', ), diff --git a/packages/create-app/src/lib/tasks.test.ts b/packages/create-app/src/lib/tasks.test.ts index 68afdc9222..c436bf5ad2 100644 --- a/packages/create-app/src/lib/tasks.test.ts +++ b/packages/create-app/src/lib/tasks.test.ts @@ -15,9 +15,8 @@ */ import fs from 'fs-extra'; -import mockFs from 'mock-fs'; import child_process from 'child_process'; -import path, { resolve as resolvePath } from 'path'; +import { resolve as resolvePath } from 'path'; import os from 'os'; import { Task, @@ -29,6 +28,7 @@ import { tryInitGitRepository, readGitConfig, } from './tasks'; +import { createMockDirectory } from '@backstage/backend-test-utils'; jest.spyOn(Task, 'log').mockReturnValue(undefined); jest.spyOn(Task, 'error').mockReturnValue(undefined); @@ -101,21 +101,38 @@ describe('tasks', () => { ) => void >; + const mockDir = createMockDirectory(); + + const origCwd = process.cwd(); + const realChdir = process.chdir; + // If anyone calls chdir then make it resolve within the tmpdir + const mockChdir = jest.spyOn(process, 'chdir'); + beforeEach(() => { - mockFs({ - 'projects/my-module.ts': '', - 'projects/dir/my-file.txt': '', - 'tmp/mockApp/.gitignore': '', - 'tmp/mockApp/package.json': '', - 'tmp/mockApp/packages/app/package.json': '', - // load templates into mock filesystem - 'templates/': mockFs.load(path.resolve(__dirname, '../../templates/')), + mockDir.setContent({ + projects: { + 'my-module.ts': '', + 'dir/my-file.txt': '', + }, + 'tmp/mockApp': { + '.gitignore': '', + 'package.json': '', + 'packages/app/package.json': '', + }, }); + realChdir(mockDir.path); + mockChdir.mockImplementation((dir: string) => + realChdir(mockDir.resolve(dir)), + ); }); afterEach(() => { mockExec.mockRestore(); - mockFs.restore(); + mockChdir.mockReset(); + }); + + afterAll(() => { + realChdir(origCwd); }); describe('checkAppExistsTask', () => { @@ -164,8 +181,6 @@ describe('tasks', () => { describe('buildAppTask', () => { it('should change to `appDir` and run `yarn install` and `yarn tsc`', async () => { - const mockChdir = jest.spyOn(process, 'chdir'); - // requires callback implementation to support `promisify` wrapper // https://stackoverflow.com/a/60579617/10044859 mockExec.mockImplementation((_command, callback) => { @@ -199,8 +214,6 @@ describe('tasks', () => { }); it('should error out on incorrect yarn version', async () => { - const mockChdir = jest.spyOn(process, 'chdir'); - // requires callback implementation to support `promisify` wrapper // https://stackoverflow.com/a/60579617/10044859 mockExec.mockImplementation((_command, callback) => { @@ -265,7 +278,7 @@ describe('tasks', () => { describe('templatingTask', () => { it('should generate a project populating context parameters', async () => { - const templateDir = 'templates/default-app'; + const templateDir = resolvePath(__dirname, '../../templates/default-app'); const destinationDir = 'templatedApp'; const context = { name: 'SuperCoolBackstageInstance', diff --git a/packages/create-app/templates/default-app/lerna.json b/packages/create-app/templates/default-app/lerna.json index 322929db1d..529a62fe38 100644 --- a/packages/create-app/templates/default-app/lerna.json +++ b/packages/create-app/templates/default-app/lerna.json @@ -1,6 +1,6 @@ { "packages": ["packages/*", "plugins/*"], "npmClient": "yarn", - "useWorkspaces": true, - "version": "0.1.0" + "version": "0.1.0", + "$schema": "node_modules/lerna/schemas/lerna-schema.json" } diff --git a/packages/create-app/templates/default-app/package.json.hbs b/packages/create-app/templates/default-app/package.json.hbs index 844a7bca9d..b74957dd56 100644 --- a/packages/create-app/templates/default-app/package.json.hbs +++ b/packages/create-app/templates/default-app/package.json.hbs @@ -36,7 +36,7 @@ "@playwright/test": "^1.32.3", "@spotify/prettier-config": "^12.0.0", "concurrently": "^8.0.0", - "lerna": "^4.0.0", + "lerna": "^7.3.0", "node-gyp": "^9.0.0", "prettier": "^2.3.2", "typescript": "~5.2.0" diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 300d3dad2f..3bb6f8e324 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/dev-utils +## 1.0.22 + +### Patch Changes + +- 080d1beb2a: Moving development `dependencies` to `devDependencies` +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 9468a67b92: Added support for React 18. The new `createRoot` API from `react-dom/client` will now be used if present. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/app-defaults@1.4.4 + - @backstage/theme@0.4.3 + +## 1.0.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/app-defaults@1.4.4-next.2 + - @backstage/test-utils@1.4.4-next.2 + ## 1.0.22-next.1 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index dec37f3cea..d860d67070 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.22-next.1", + "version": "1.0.22", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -40,25 +40,25 @@ "@backstage/core-plugin-api": "workspace:^", "@backstage/integration-react": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", - "@backstage/test-utils": "workspace:^", "@backstage/theme": "workspace:^", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/user-event": "^14.0.0", "@types/react": "^16.13.1 || ^17.0.0", - "react-use": "^17.2.4", - "zen-observable": "^0.10.0" + "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { - "@backstage/cli": "workspace:^" + "@backstage/cli": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@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", + "zen-observable": "^0.10.0" }, "files": [ "dist" diff --git a/packages/dev-utils/src/devApp/render.tsx b/packages/dev-utils/src/devApp/render.tsx index 5f2b21b8d2..e45ba649f9 100644 --- a/packages/dev-utils/src/devApp/render.tsx +++ b/packages/dev-utils/src/devApp/render.tsx @@ -45,9 +45,16 @@ import { import { Box } from '@material-ui/core'; import BookmarkIcon from '@material-ui/icons/Bookmark'; import React, { ComponentType, ReactNode, PropsWithChildren } from 'react'; -import ReactDOM from 'react-dom'; import { createRoutesFromChildren, Route } from 'react-router-dom'; import { SidebarThemeSwitcher } from './SidebarThemeSwitcher'; +import 'react-dom'; + +let ReactDOM: typeof import('react-dom') | typeof import('react-dom/client'); +if (process.env.HAS_REACT_DOM_CLIENT) { + ReactDOM = require('react-dom/client'); +} else { + ReactDOM = require('react-dom'); +} export function isReactRouterBeta(): boolean { const [obj] = createRoutesFromChildren(<Route index element={<div />} />); @@ -235,7 +242,11 @@ export class DevAppBuilder { window.location.pathname = this.defaultPage; } - ReactDOM.render(<DevApp />, document.getElementById('root')); + if ('createRoot' in ReactDOM) { + ReactDOM.createRoot(document.getElementById('root')!).render(<DevApp />); + } else { + ReactDOM.render(<DevApp />, document.getElementById('root')); + } } } diff --git a/packages/e2e-test-utils/CHANGELOG.md b/packages/e2e-test-utils/CHANGELOG.md index de15b39751..914644a9f6 100644 --- a/packages/e2e-test-utils/CHANGELOG.md +++ b/packages/e2e-test-utils/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/e2e-test-utils +## 0.1.0 + +### Minor Changes + +- f5b41b27a9: Initial release. + ## 0.1.0-next.0 ### Minor Changes diff --git a/packages/e2e-test-utils/package.json b/packages/e2e-test-utils/package.json index fcbae56796..3448497395 100644 --- a/packages/e2e-test-utils/package.json +++ b/packages/e2e-test-utils/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/e2e-test-utils", "description": "Shared end-to-end test utilities Backstage", - "version": "0.1.0-next.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/packages/e2e-test/CHANGELOG.md b/packages/e2e-test/CHANGELOG.md index 4c47b33e86..37d8b1d24a 100644 --- a/packages/e2e-test/CHANGELOG.md +++ b/packages/e2e-test/CHANGELOG.md @@ -1,5 +1,23 @@ # e2e-test +## 0.2.8 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.6 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.5.6-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/cli-common@0.1.13-next.0 + ## 0.2.8-next.1 ### Patch Changes diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 8b1499446a..f6e90e116e 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.8-next.1", + "version": "0.2.8", "private": true, "backstage": { "role": "cli" diff --git a/packages/errors/CHANGELOG.md b/packages/errors/CHANGELOG.md index 689b3617fc..92655a25d8 100644 --- a/packages/errors/CHANGELOG.md +++ b/packages/errors/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/errors +## 1.2.3 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/types@1.1.1 + +## 1.2.3-next.0 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/types@1.1.1 + ## 1.2.2 ### Patch Changes diff --git a/packages/errors/package.json b/packages/errors/package.json index 8d274be401..7dc17a10a2 100644 --- a/packages/errors/package.json +++ b/packages/errors/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/errors", "description": "Common utilities for error handling within Backstage", - "version": "1.2.2", + "version": "1.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -34,7 +34,6 @@ }, "dependencies": { "@backstage/types": "workspace:^", - "cross-fetch": "^3.1.5", "serialize-error": "^8.0.1" }, "devDependencies": { diff --git a/packages/frontend-app-api/CHANGELOG.md b/packages/frontend-app-api/CHANGELOG.md index 90d7ba70d2..96bf43f73c 100644 --- a/packages/frontend-app-api/CHANGELOG.md +++ b/packages/frontend-app-api/CHANGELOG.md @@ -1,5 +1,61 @@ # @backstage/frontend-app-api +## 0.2.0 + +### Minor Changes + +- 4461d87d5a: Removed support for the new `useRouteRef`. +- 9d03dfe5e3: The `createApp` config option has been replaced by a new `configLoader` option. There is now also a `pluginLoader` option that can be used to dynamically load plugins into the app. +- d7c5d80c57: The hidden `'root'` extension has been removed and has instead been made an input of the `'core'` extension. The checks for rejecting configuration of the `'root'` extension to rejects configuration of the `'core'` extension instead. +- d920b8c343: Added support for installing `ExtensionOverrides` via `createApp` options. As part of this change the `plugins` option has been renamed to `features`, and the `pluginLoader` has been renamed to `featureLoader`. + +### Patch Changes + +- 322bbcae24: Internal update for removal of experimental plugin configuration API. +- f78ac58f88: Filters for discovered packages are now also applied at runtime. This makes it possible to disable packages through the `app.experimental.packages` config at runtime. +- 68ffb9e67d: The app will now reject any extensions that attach to nonexistent inputs. +- 5072824817: Implement `toString()` and `toJSON()` for extension instances. +- 1e60a9c3a5: Fixed an issue preventing the routing system to match subroutes +- 52366db5b3: Make themes configurable through extensions, and switched default themes to use extensions instead. +- 2ecd33618a: Added the `bindRoutes` option to `createApp`. +- e5a2956dd2: Register default api implementations when creating declarative integrated apps. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 06432f900c: Updates for `at` -> `attachTo` refactor. +- 1718ec75b7: Added support for the existing routing system. +- 66d51a4827: Prevents root extension override and duplicated plugin extensions. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/plugin-graphiql@0.2.55 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.2.0-next.2 + +### Minor Changes + +- 4461d87d5a: Removed support for the new `useRouteRef`. + +### Patch Changes + +- 5072824817: Implement `toString()` and `toJSON()` for extension instances. +- 06432f900c: Updates for `at` -> `attachTo` refactor. +- 1718ec75b7: Added support for the existing routing system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/plugin-graphiql@0.2.55-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + ## 0.2.0-next.1 ### Patch Changes diff --git a/packages/frontend-app-api/api-report.md b/packages/frontend-app-api/api-report.md index 2e77ef904b..11c9ac03c5 100644 --- a/packages/frontend-app-api/api-report.md +++ b/packages/frontend-app-api/api-report.md @@ -7,13 +7,33 @@ import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Config } from '@backstage/config'; import { ConfigApi } from '@backstage/core-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; +import { ExtensionOverrides } from '@backstage/frontend-plugin-api'; +import { ExternalRouteRef } from '@backstage/frontend-plugin-api'; import { JSX as JSX_2 } from 'react'; +import { RouteRef } from '@backstage/frontend-plugin-api'; +import { SubRouteRef } from '@backstage/frontend-plugin-api'; + +// @public +export type AppRouteBinder = < + TExternalRoutes extends { + [name: string]: ExternalRouteRef; + }, +>( + externalRoutes: TExternalRoutes, + targetRoutes: PartialKeys< + TargetRouteMap<TExternalRoutes>, + KeysWithType<TExternalRoutes, ExternalRouteRef<any, true>> + >, +) => void; // @public (undocumented) export function createApp(options: { - plugins: BackstagePlugin[]; + features?: (BackstagePlugin | ExtensionOverrides)[]; configLoader?: () => Promise<ConfigApi>; - pluginLoader?: (ctx: { config: ConfigApi }) => Promise<BackstagePlugin[]>; + bindRoutes?(context: { bind: AppRouteBinder }): void; + featureLoader?: (ctx: { + config: ConfigApi; + }) => Promise<(BackstagePlugin | ExtensionOverrides)[]>; }): { createRoot(): JSX_2.Element; }; diff --git a/packages/frontend-app-api/config.d.ts b/packages/frontend-app-api/config.d.ts index 81c24d1185..9ec020fa56 100644 --- a/packages/frontend-app-api/config.d.ts +++ b/packages/frontend-app-api/config.d.ts @@ -16,6 +16,21 @@ export interface Config { app?: { + experimental?: { + /** + * @visibility frontend + * @deepVisibility frontend + */ + packages?: 'all' | { include?: string[]; exclude?: string[] }; + }; + + routes?: { + /** + * @deepVisibility frontend + */ + bindings?: { [externalRouteRefId: string]: string }; + }; + /** * @deepVisibility frontend */ diff --git a/packages/frontend-app-api/package.json b/packages/frontend-app-api/package.json index 477cf8f736..d4a595707a 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.2.0-next.1", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -25,8 +25,8 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3" + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0" }, "configSchema": "config.d.ts", "files": [ @@ -49,7 +49,7 @@ "lodash": "^4.17.21" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" } } diff --git a/packages/frontend-app-api/src/extensions/Core.tsx b/packages/frontend-app-api/src/extensions/Core.tsx index 4cb21a8702..6efe3984dc 100644 --- a/packages/frontend-app-api/src/extensions/Core.tsx +++ b/packages/frontend-app-api/src/extensions/Core.tsx @@ -22,12 +22,27 @@ import { export const Core = createExtension({ id: 'core', - at: 'root', + attachTo: { id: 'root', input: 'default' }, inputs: { apis: createExtensionInput({ api: coreExtensionData.apiFactory, }), + themes: createExtensionInput({ + theme: coreExtensionData.theme, + }), + root: createExtensionInput( + { + element: coreExtensionData.reactElement, + }, + { singleton: true }, + ), + }, + output: { + root: coreExtensionData.reactElement, + }, + factory({ bind, inputs }) { + bind({ + root: inputs.root.element, + }); }, - output: {}, - factory() {}, }); diff --git a/packages/frontend-app-api/src/extensions/CoreLayout.tsx b/packages/frontend-app-api/src/extensions/CoreLayout.tsx index 0c5c0446fc..bf0f382cfc 100644 --- a/packages/frontend-app-api/src/extensions/CoreLayout.tsx +++ b/packages/frontend-app-api/src/extensions/CoreLayout.tsx @@ -24,7 +24,7 @@ import { SidebarPage } from '@backstage/core-components'; export const CoreLayout = createExtension({ id: 'core.layout', - at: 'root', + attachTo: { id: 'core', input: 'root' }, inputs: { nav: createExtensionInput( { diff --git a/packages/frontend-app-api/src/extensions/CoreNav.tsx b/packages/frontend-app-api/src/extensions/CoreNav.tsx index 71ab71a6aa..cd12ca129a 100644 --- a/packages/frontend-app-api/src/extensions/CoreNav.tsx +++ b/packages/frontend-app-api/src/extensions/CoreNav.tsx @@ -19,8 +19,8 @@ import { createExtension, coreExtensionData, createExtensionInput, - useRouteRef, NavTarget, + useRouteRef, } from '@backstage/frontend-plugin-api'; import { makeStyles } from '@material-ui/core'; import { @@ -73,7 +73,7 @@ const SidebarNavItem = (props: NavTarget) => { export const CoreNav = createExtension({ id: 'core.nav', - at: 'core.layout/nav', + attachTo: { id: 'core.layout', input: 'nav' }, inputs: { items: createExtensionInput({ target: coreExtensionData.navTarget, diff --git a/packages/frontend-app-api/src/extensions/CoreRoutes.tsx b/packages/frontend-app-api/src/extensions/CoreRoutes.tsx index 5c79b56f43..8d22b40eec 100644 --- a/packages/frontend-app-api/src/extensions/CoreRoutes.tsx +++ b/packages/frontend-app-api/src/extensions/CoreRoutes.tsx @@ -24,7 +24,7 @@ import { useRoutes } from 'react-router-dom'; export const CoreRoutes = createExtension({ id: 'core.routes', - at: 'core.layout/content', + attachTo: { id: 'core.layout', input: 'content' }, inputs: { routes: createExtensionInput({ path: coreExtensionData.routePath, @@ -39,7 +39,7 @@ export const CoreRoutes = createExtension({ const Routes = () => { const element = useRoutes( inputs.routes.map(route => ({ - path: route.path, + path: `${route.path}/*`, element: route.element, })), ); diff --git a/packages/frontend-app-api/src/index.ts b/packages/frontend-app-api/src/index.ts index f2dfa0f029..ad82b4ceef 100644 --- a/packages/frontend-app-api/src/index.ts +++ b/packages/frontend-app-api/src/index.ts @@ -21,3 +21,4 @@ */ export * from './wiring'; +export * from './routing'; diff --git a/packages/frontend-app-api/src/routing/RouteResolver.test.ts b/packages/frontend-app-api/src/routing/RouteResolver.test.ts new file mode 100644 index 0000000000..e37ee14929 --- /dev/null +++ b/packages/frontend-app-api/src/routing/RouteResolver.test.ts @@ -0,0 +1,365 @@ +/* + * 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 { + createRouteRef, + createSubRouteRef, + createExternalRouteRef, + ExternalRouteRef, + RouteRef, + SubRouteRef, +} from '@backstage/frontend-plugin-api'; +import { BackstagePlugin } from '@backstage/core-plugin-api'; +import { RouteResolver } from './RouteResolver'; +import { MATCH_ALL_ROUTE } from './extractRouteInfoFromInstanceTree'; + +const rest = { + element: null, + caseSensitive: false, + children: [MATCH_ALL_ROUTE], + plugins: new Set<BackstagePlugin>(), +}; + +const ref1 = createRouteRef(); +const ref2 = createRouteRef({ params: ['x'] }); +const ref3 = createRouteRef({ params: ['y'] }); +const subRef1 = createSubRouteRef({ parent: ref1, path: '/foo' }); +const subRef2 = createSubRouteRef({ parent: ref1, path: '/foo/:a' }); +const subRef3 = createSubRouteRef({ parent: ref2, path: '/bar' }); +const subRef4 = createSubRouteRef({ parent: ref2, path: '/bar/:a' }); +const externalRef1 = createExternalRouteRef(); +const externalRef2 = createExternalRouteRef({ optional: true }); +const externalRef3 = createExternalRouteRef({ params: ['x'] }); +const externalRef4 = createExternalRouteRef({ optional: true, params: ['x'] }); + +describe('RouteResolver', () => { + it('should not resolve anything with an empty resolver', () => { + const r = new RouteResolver(new Map(), new Map(), [], new Map(), ''); + + expect(r.resolve(ref1, '/')?.()).toBe(undefined); + expect(r.resolve(ref2, '/')?.({ x: '1x' })).toBe(undefined); + expect(r.resolve(subRef1, '/')?.()).toBe(undefined); + expect(r.resolve(subRef2, '/')?.({ a: '2a' })).toBe(undefined); + expect(r.resolve(subRef3, '/')?.({ x: '3x' })).toBe(undefined); + expect(r.resolve(subRef4, '/')?.({ x: '4x', a: '4a' })).toBe(undefined); + expect(r.resolve(externalRef1, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef2, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef3, '/')?.({ x: '5x' })).toBe(undefined); + expect(r.resolve(externalRef4, '/')?.({ x: '6x' })).toBe(undefined); + }); + + it('should resolve an absolute route', () => { + const r = new RouteResolver( + new Map([[ref1, 'my-route']]), + new Map(), + [{ routeRefs: new Set([ref1]), path: 'my-route', ...rest }], + new Map(), + '', + ); + + expect(r.resolve(ref1, '/')?.()).toBe('/my-route'); + expect(r.resolve(ref2, '/')?.({ x: '1x' })).toBe(undefined); + expect(r.resolve(subRef1, '/')?.()).toBe('/my-route/foo'); + expect(r.resolve(subRef2, '/')?.({ a: '2a' })).toBe('/my-route/foo/2a'); + expect(r.resolve(subRef3, '/')?.({ x: '3x' })).toBe(undefined); + expect(r.resolve(subRef4, '/')?.({ x: '4x', a: '4a' })).toBe(undefined); + expect(r.resolve(externalRef1, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef2, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef3, '/')?.({ x: '5x' })).toBe(undefined); + expect(r.resolve(externalRef4, '/')?.({ x: '6x' })).toBe(undefined); + }); + + it('should resolve an absolute route and sub route with an app base path', () => { + const r = new RouteResolver( + new Map<RouteRef, string>([ + [ref2, 'my-parent/:x'], + [ref1, 'my-route'], + ]), + new Map<RouteRef, RouteRef>([[ref1, ref2]]), + [ + { + routeRefs: new Set([ref2]), + path: 'my-parent/:x', + ...rest, + children: [ + MATCH_ALL_ROUTE, + { routeRefs: new Set([ref1]), path: 'my-route', ...rest }, + ], + }, + ], + new Map(), + '/base', + ); + + expect(r.resolve(ref1, '/my-parent/1x')?.()).toBe( + '/base/my-parent/1x/my-route', + ); + expect(r.resolve(ref1, '/base/my-parent/1x')?.()).toBe( + '/base/my-parent/1x/my-route', + ); + expect(r.resolve(ref2, '/')?.({ x: '1x' })).toBe('/base/my-parent/1x'); + expect(r.resolve(ref2, '/base')?.({ x: '1x' })).toBe('/base/my-parent/1x'); + expect(r.resolve(ref3, '/')?.({ y: '1y' })).toBe(undefined); + expect(r.resolve(subRef1, '/my-parent/2x')?.()).toBe( + '/base/my-parent/2x/my-route/foo', + ); + expect(r.resolve(subRef1, '/base/my-parent/2x')?.()).toBe( + '/base/my-parent/2x/my-route/foo', + ); + expect(r.resolve(subRef2, '/my-parent/3x')?.({ a: '2a' })).toBe( + '/base/my-parent/3x/my-route/foo/2a', + ); + expect(r.resolve(subRef2, '/base/my-parent/3x')?.({ a: '2a' })).toBe( + '/base/my-parent/3x/my-route/foo/2a', + ); + expect(r.resolve(subRef3, '/')?.({ x: '5x' })).toBe( + '/base/my-parent/5x/bar', + ); + expect(r.resolve(subRef4, '/')?.({ x: '6x', a: '4a' })).toBe( + '/base/my-parent/6x/bar/4a', + ); + expect(r.resolve(externalRef1, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef2, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef3, '/')?.({ x: '5x' })).toBe(undefined); + expect(r.resolve(externalRef4, '/')?.({ x: '6x' })).toBe(undefined); + }); + + it('should resolve an absolute route with a param and with a parent', () => { + const r = new RouteResolver( + new Map<RouteRef, string>([ + [ref1, 'my-route'], + [ref2, 'my-parent/:x'], + ]), + new Map([[ref2, ref1]]), + [ + { + routeRefs: new Set([ref2]), + path: 'my-parent/:x', + ...rest, + children: [ + MATCH_ALL_ROUTE, + { routeRefs: new Set([ref1]), path: 'my-route', ...rest }, + ], + }, + ], + new Map<ExternalRouteRef, RouteRef | SubRouteRef>([ + [externalRef1, ref1], + [externalRef3, ref2], + [externalRef4, subRef3], + ]), + '', + ); + + expect(r.resolve(ref1, '/')?.()).toBe('/my-route'); + expect(r.resolve(ref2, '/')?.({ x: '1x' })).toBe('/my-route/my-parent/1x'); + expect(r.resolve(subRef1, '/')?.()).toBe('/my-route/foo'); + expect(r.resolve(subRef2, '/')?.({ a: '2a' })).toBe('/my-route/foo/2a'); + expect(r.resolve(subRef3, '/')?.({ x: '3x' })).toBe( + '/my-route/my-parent/3x/bar', + ); + expect(r.resolve(subRef4, '/')?.({ x: '4x', a: '4a' })).toBe( + '/my-route/my-parent/4x/bar/4a', + ); + expect(r.resolve(externalRef1, '/')?.()).toBe('/my-route'); + expect(r.resolve(externalRef2, '/')?.()).toBe(undefined); + expect(r.resolve(externalRef3, '/')?.({ x: '5x' })).toBe( + '/my-route/my-parent/5x', + ); + expect(r.resolve(externalRef4, '/')?.({ x: '6x' })).toBe( + '/my-route/my-parent/6x/bar', + ); + }); + + it('should resolve the most specific match', () => { + const r = new RouteResolver( + new Map<RouteRef, string>([ + [ref1, 'deep'], + [ref2, 'root/:x'], + [ref3, 'sub/:y'], + ]), + new Map<RouteRef, RouteRef>([ + [ref3, ref2], + [ref1, ref3], + ]), + [ + { + routeRefs: new Set([ref2]), + path: 'root/:x', + ...rest, + children: [ + MATCH_ALL_ROUTE, + { + routeRefs: new Set([ref3]), + path: 'sub/:y', + ...rest, + children: [ + MATCH_ALL_ROUTE, + { + routeRefs: new Set([ref1]), + path: 'deep', + ...rest, + }, + ], + }, + ], + }, + ], + new Map<ExternalRouteRef, RouteRef | SubRouteRef>(), + '', + ); + + expect(r.resolve(ref2, '/')?.({ x: 'x' })).toBe('/root/x'); + expect(r.resolve(ref3, '/root/x')?.({ y: 'y' })).toBe('/root/x/sub/y'); + + expect(() => r.resolve(ref1, '/')?.()).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(() => r.resolve(ref1, '/root/x')?.()).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(r.resolve(ref1, '/root/x/sub/y')?.()).toBe('/root/x/sub/y/deep'); + // Without the MATCH_ALL_ROUTE, we wouldn't properly match the route here + expect(r.resolve(ref1, '/root/x/sub/y/any/nested/path/here')?.()).toBe( + '/root/x/sub/y/deep', + ); + }); + + it('should resolve an absolute route with multiple parents', () => { + const r = new RouteResolver( + new Map<RouteRef, string>([ + [ref1, 'my-route'], + [ref2, 'my-parent/:x'], + [ref3, 'my-grandparent/:y'], + ]), + new Map<RouteRef, RouteRef>([ + [ref1, ref2], + [ref2, ref3], + ]), + [ + { + routeRefs: new Set([ref3]), + path: 'my-grandparent/:y', + ...rest, + children: [ + MATCH_ALL_ROUTE, + { + routeRefs: new Set([ref2]), + path: 'my-parent/:x', + ...rest, + children: [ + MATCH_ALL_ROUTE, + { routeRefs: new Set([ref1]), path: 'my-route', ...rest }, + ], + }, + ], + }, + ], + new Map<ExternalRouteRef, RouteRef | SubRouteRef>([ + [externalRef1, ref1], + [externalRef3, ref2], + [externalRef4, subRef3], + ]), + '', + ); + + const l = '/my-grandparent/my-y/my-parent/my-x'; + expect(r.resolve(ref1, l)?.()).toBe( + '/my-grandparent/my-y/my-parent/my-x/my-route', + ); + expect(() => r.resolve(ref1, '/')?.()).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(r.resolve(ref2, l)?.({ x: '1x' })).toBe( + '/my-grandparent/my-y/my-parent/1x', + ); + expect(r.resolve(ref2, '/my-grandparent/my-y')?.({ x: '1x' })).toBe( + '/my-grandparent/my-y/my-parent/1x', + ); + expect(() => r.resolve(ref2, '/')?.({ x: '1x' })).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(r.resolve(subRef1, l)?.()).toBe( + '/my-grandparent/my-y/my-parent/my-x/my-route/foo', + ); + expect(() => r.resolve(subRef1, '/')?.()).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(r.resolve(subRef2, l)?.({ a: '2a' })).toBe( + '/my-grandparent/my-y/my-parent/my-x/my-route/foo/2a', + ); + expect(() => r.resolve(subRef2, '/')?.({ a: '2a' })).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(r.resolve(subRef3, l)?.({ x: '3x' })).toBe( + '/my-grandparent/my-y/my-parent/3x/bar', + ); + expect(r.resolve(subRef3, '/my-grandparent/my-y')?.({ x: '3x' })).toBe( + '/my-grandparent/my-y/my-parent/3x/bar', + ); + expect(r.resolve(subRef4, l)?.({ x: '4x', a: '4a' })).toBe( + '/my-grandparent/my-y/my-parent/4x/bar/4a', + ); + expect( + r.resolve(subRef4, '/my-grandparent/my-y')?.({ x: '4x', a: '4a' }), + ).toBe('/my-grandparent/my-y/my-parent/4x/bar/4a'); + expect(r.resolve(externalRef1, l)?.()).toBe( + '/my-grandparent/my-y/my-parent/my-x/my-route', + ); + expect(() => r.resolve(externalRef1, '/')?.()).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(r.resolve(externalRef2, l)?.()).toBe(undefined); + expect(r.resolve(externalRef3, l)?.({ x: '5x' })).toBe( + '/my-grandparent/my-y/my-parent/5x', + ); + expect(() => r.resolve(externalRef3, '/')?.({ x: '5x' })).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + expect(r.resolve(externalRef4, l)?.({ x: '6x' })).toBe( + '/my-grandparent/my-y/my-parent/6x/bar', + ); + expect(() => r.resolve(externalRef4, '/')?.({ x: '6x' })).toThrow( + /^Cannot route.*with parent.*as it has parameters$/, + ); + }); + + it('should encode some characters in params', () => { + const r = new RouteResolver( + new Map<RouteRef, string>([ + [ref2, 'my-parent/:x'], + [ref1, 'my-route'], + ]), + new Map<RouteRef, RouteRef>([[ref1, ref2]]), + [ + { + routeRefs: new Set([ref2]), + path: 'my-parent/:x', + ...rest, + children: [ + MATCH_ALL_ROUTE, + { routeRefs: new Set([ref1]), path: 'my-route', ...rest }, + ], + }, + ], + new Map(), + '/base', + ); + + expect(r.resolve(ref2, '/')?.({ x: 'a/#&?b' })).toBe( + '/base/my-parent/a%2F%23%26%3Fb', + ); + }); +}); diff --git a/packages/frontend-app-api/src/routing/RouteResolver.ts b/packages/frontend-app-api/src/routing/RouteResolver.ts new file mode 100644 index 0000000000..77336988e2 --- /dev/null +++ b/packages/frontend-app-api/src/routing/RouteResolver.ts @@ -0,0 +1,268 @@ +/* + * 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 { generatePath, matchRoutes } from 'react-router-dom'; +import { + RouteRef, + ExternalRouteRef, + SubRouteRef, + AnyRouteRefParams, + RouteFunc, +} from '@backstage/frontend-plugin-api'; +import mapValues from 'lodash/mapValues'; +import { AnyRouteRef, BackstageRouteObject } from './types'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { isRouteRef } from '../../../frontend-plugin-api/src/routing/RouteRef'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { + isSubRouteRef, + toInternalSubRouteRef, +} from '../../../frontend-plugin-api/src/routing/SubRouteRef'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { isExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef'; + +// Joins a list of paths together, avoiding trailing and duplicate slashes +export function joinPaths(...paths: string[]): string { + const normalized = paths.join('/').replace(/\/\/+/g, '/'); + if (normalized !== '/' && normalized.endsWith('/')) { + return normalized.slice(0, -1); + } + return normalized; +} + +/** + * Resolves the absolute route ref that our target route ref is pointing pointing to, as well + * as the relative target path. + * + * Returns an undefined target ref if one could not be fully resolved. + */ +function resolveTargetRef( + anyRouteRef: AnyRouteRef, + routePaths: Map<RouteRef, string>, + routeBindings: Map<AnyRouteRef, AnyRouteRef | undefined>, +): readonly [RouteRef | undefined, string] { + // First we figure out which absolute route ref we're dealing with, an if there was an sub route path to append. + // For sub routes it will be the parent path, while for external routes it will be the bound route. + let targetRef: RouteRef; + let subRoutePath = ''; + if (isRouteRef(anyRouteRef)) { + targetRef = anyRouteRef; + } else if (isSubRouteRef(anyRouteRef)) { + const internal = toInternalSubRouteRef(anyRouteRef); + targetRef = internal.getParent(); + subRoutePath = internal.path; + } else if (isExternalRouteRef(anyRouteRef)) { + const resolvedRoute = routeBindings.get(anyRouteRef); + if (!resolvedRoute) { + return [undefined, '']; + } + if (isRouteRef(resolvedRoute)) { + targetRef = resolvedRoute; + } else if (isSubRouteRef(resolvedRoute)) { + const internal = toInternalSubRouteRef(resolvedRoute); + targetRef = internal.getParent(); + subRoutePath = resolvedRoute.path; + } else { + throw new Error( + `ExternalRouteRef was bound to invalid target, ${resolvedRoute}`, + ); + } + } else { + throw new Error(`Unknown object passed to useRouteRef, got ${anyRouteRef}`); + } + + // Bail if no absolute path could be resolved + if (!targetRef) { + return [undefined, '']; + } + + // Find the path that our target route is bound to + const resolvedPath = routePaths.get(targetRef); + if (resolvedPath === undefined) { + return [undefined, '']; + } + + // SubRouteRefs join the path from the parent route with its own path + const targetPath = joinPaths(resolvedPath, subRoutePath); + return [targetRef, targetPath]; +} + +/** + * Resolves the complete base path for navigating to the target RouteRef. + */ +function resolveBasePath( + targetRef: RouteRef, + sourceLocation: Parameters<typeof matchRoutes>[1], + routePaths: Map<RouteRef, string>, + routeParents: Map<RouteRef, RouteRef | undefined>, + routeObjects: BackstageRouteObject[], +) { + // While traversing the app element tree we build up the routeObjects structure + // used here. It is the same kind of structure that react-router creates, with the + // addition that associated route refs are stored throughout the tree. This lets + // us look up all route refs that can be reached from our source location. + // Because of the similar route object structure, we can use `matchRoutes` from + // react-router to do the lookup of our current location. + const match = matchRoutes(routeObjects, sourceLocation) ?? []; + + // While we search for a common routing root between our current location and + // the target route, we build a list of all route refs we find that we need + // to traverse to reach the target. + const refDiffList = Array<RouteRef>(); + + let matchIndex = -1; + for ( + let targetSearchRef: RouteRef | undefined = targetRef; + targetSearchRef; + targetSearchRef = routeParents.get(targetSearchRef) + ) { + // The match contains a list of all ancestral route refs present at our current location + // Starting at the desired target ref and traversing back through its parents, we search + // for a target ref that is present in the match for our current location. When a match + // is found it means we have found a common base to resolve the route from. + matchIndex = match.findIndex(m => + (m.route as BackstageRouteObject).routeRefs.has(targetSearchRef!), + ); + if (matchIndex !== -1) { + break; + } + + // Every time we move a step up in the ancestry of the target ref, we add the current ref + // to the diff list, which ends up being the list of route refs to traverse form the common base + // in order to reach our target. + refDiffList.unshift(targetSearchRef); + } + + // If our target route is present in the initial match we need to construct the final path + // from the parent of the matched route segment. That's to allow the caller of the route + // function to supply their own params. + if (refDiffList.length === 0) { + matchIndex -= 1; + } + + // This is the part of the route tree that the target and source locations have in common. + // We re-use the existing pathname directly along with all params. + const parentPath = matchIndex === -1 ? '' : match[matchIndex].pathname; + + // This constructs the mid section of the path using paths resolved from all route refs + // we need to traverse to reach our target except for the very last one. None of these + // paths are allowed to require any parameters, as the caller would have no way of knowing + // what parameters those are. + const diffPaths = refDiffList.slice(0, -1).map(ref => { + const path = routePaths.get(ref); + if (path === undefined) { + throw new Error(`No path for ${ref}`); + } + if (path.includes(':')) { + throw new Error( + `Cannot route to ${targetRef} with parent ${ref} as it has parameters`, + ); + } + return path; + }); + + return `${joinPaths(parentPath, ...diffPaths)}/`; +} + +export class RouteResolver { + constructor( + private readonly routePaths: Map<RouteRef, string>, + private readonly routeParents: Map<RouteRef, RouteRef | undefined>, + private readonly routeObjects: BackstageRouteObject[], + private readonly routeBindings: Map< + ExternalRouteRef, + RouteRef | SubRouteRef + >, + private readonly appBasePath: string, // base path without a trailing slash + ) {} + + resolve<Params extends AnyRouteRefParams>( + anyRouteRef: + | RouteRef<Params> + | SubRouteRef<Params> + | ExternalRouteRef<Params, any>, + sourceLocation: Parameters<typeof matchRoutes>[1], + ): RouteFunc<Params> | undefined { + // First figure out what our target absolute ref is, as well as our target path. + const [targetRef, targetPath] = resolveTargetRef( + anyRouteRef, + this.routePaths, + this.routeBindings, + ); + if (!targetRef) { + return undefined; + } + + // The location that we get passed in uses the full path, so start by trimming off + // the app base path prefix in case we're running the app on a sub-path. + let relativeSourceLocation: Parameters<typeof matchRoutes>[1]; + if (typeof sourceLocation === 'string') { + relativeSourceLocation = this.trimPath(sourceLocation); + } else if (sourceLocation.pathname) { + relativeSourceLocation = { + ...sourceLocation, + pathname: this.trimPath(sourceLocation.pathname), + }; + } else { + relativeSourceLocation = sourceLocation; + } + + // Next we figure out the base path, which is the combination of the common parent path + // between our current location and our target location, as well as the additional path + // that is the difference between the parent path and the base of our target location. + const basePath = + this.appBasePath + + resolveBasePath( + targetRef, + relativeSourceLocation, + this.routePaths, + this.routeParents, + this.routeObjects, + ); + + const routeFunc: RouteFunc<Params> = (...[params]) => { + // We selectively encode some some known-dangerous characters in the + // params. The reason that we don't perform a blanket `encodeURIComponent` + // here is that this encoding was added defensively long after the initial + // release of this code. There's likely to be many users of this code that + // already encode their parameters knowing that this code didn't do this + // for them in the past. Therefore, we are extra careful NOT to include + // the percent character in this set, even though that might seem like a + // bad idea. + const encodedParams = + params && + mapValues(params, value => { + if (typeof value === 'string') { + return value.replaceAll(/[&?#;\/]/g, c => encodeURIComponent(c)); + } + return value; + }); + return joinPaths(basePath, generatePath(targetPath, encodedParams)); + }; + return routeFunc; + } + + private trimPath(targetPath: string) { + if (!targetPath) { + return targetPath; + } + + if (targetPath.startsWith(this.appBasePath)) { + return targetPath.slice(this.appBasePath.length); + } + return targetPath; + } +} diff --git a/packages/frontend-app-api/src/routing/RoutingContext.tsx b/packages/frontend-app-api/src/routing/RoutingContext.tsx deleted file mode 100644 index 237c8aa5df..0000000000 --- a/packages/frontend-app-api/src/routing/RoutingContext.tsx +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 { RouteRef } from '@backstage/core-plugin-api'; -import React, { createContext, ReactNode } from 'react'; - -export interface RoutingContextType { - resolve( - routeRef: RouteRef, - options: { pathname: string }, - ): (() => string) | undefined; -} - -export const RoutingContext = createContext<RoutingContextType>({ - resolve: () => () => '', -}); - -export class RouteResolver { - constructor(private readonly routePaths: Map<RouteRef, string>) {} - - resolve(anyRouteRef: RouteRef<{}>): (() => string) | undefined { - const basePath = this.routePaths.get(anyRouteRef); - if (!basePath) { - return undefined; - } - return () => basePath; - } -} - -export function RoutingProvider(props: { - routePaths: Map<RouteRef, string>; - children?: ReactNode; -}) { - return ( - <RoutingContext.Provider value={new RouteResolver(props.routePaths)}> - {props.children} - </RoutingContext.Provider> - ); -} diff --git a/packages/frontend-app-api/src/routing/RoutingProvider.tsx b/packages/frontend-app-api/src/routing/RoutingProvider.tsx new file mode 100644 index 0000000000..965faa3655 --- /dev/null +++ b/packages/frontend-app-api/src/routing/RoutingProvider.tsx @@ -0,0 +1,66 @@ +/* + * 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, { ReactNode } from 'react'; +import { + ExternalRouteRef, + RouteRef, + SubRouteRef, +} from '@backstage/frontend-plugin-api'; +import { + createVersionedValueMap, + createVersionedContext, +} from '@backstage/version-bridge'; +import { RouteResolver } from './RouteResolver'; +import { BackstageRouteObject } from './types'; + +const RoutingContext = createVersionedContext<{ 1: RouteResolver }>( + 'routing-context', +); + +type ProviderProps = { + routePaths: Map<RouteRef, string>; + routeParents: Map<RouteRef, RouteRef | undefined>; + routeObjects: BackstageRouteObject[]; + routeBindings: Map<ExternalRouteRef, RouteRef | SubRouteRef>; + basePath?: string; + children: ReactNode; +}; + +// TODO(Rugvip): Migrate to a routing API instead +export const RoutingProvider = ({ + routePaths, + routeParents, + routeObjects, + routeBindings, + basePath = '', + children, +}: ProviderProps) => { + const resolver = new RouteResolver( + routePaths, + routeParents, + routeObjects, + routeBindings, + basePath, + ); + + const versionedValue = createVersionedValueMap({ 1: resolver }); + return ( + <RoutingContext.Provider value={versionedValue}> + {children} + </RoutingContext.Provider> + ); +}; diff --git a/packages/frontend-app-api/src/routing/collectRouteIds.test.ts b/packages/frontend-app-api/src/routing/collectRouteIds.test.ts new file mode 100644 index 0000000000..95a5afd8cd --- /dev/null +++ b/packages/frontend-app-api/src/routing/collectRouteIds.test.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 { + createRouteRef, + createExternalRouteRef, + createPlugin, +} from '@backstage/frontend-plugin-api'; +import { collectRouteIds } from './collectRouteIds'; + +describe('collectRouteIds', () => { + it('should assign IDs to routes', () => { + const ref = createRouteRef(); + const extRef = createExternalRouteRef(); + + expect(String(ref)).toMatch( + /^RouteRef\{created at '.*collectRouteIds\.test\.ts.*'\}$/, + ); + expect(String(extRef)).toMatch( + /^ExternalRouteRef\{created at '.*collectRouteIds\.test\.ts.*'\}$/, + ); + + const collected = collectRouteIds([ + createPlugin({ id: 'test', routes: { ref }, externalRoutes: { extRef } }), + ]); + expect(Object.fromEntries(collected.routes)).toEqual({ + 'plugin.test.routes.ref': ref, + }); + expect(Object.fromEntries(collected.externalRoutes)).toEqual({ + 'plugin.test.externalRoutes.extRef': extRef, + }); + + expect(String(ref)).toBe('RouteRef{plugin.test.routes.ref}'); + expect(String(extRef)).toBe( + 'ExternalRouteRef{plugin.test.externalRoutes.extRef}', + ); + }); +}); diff --git a/packages/frontend-app-api/src/routing/collectRouteIds.ts b/packages/frontend-app-api/src/routing/collectRouteIds.ts new file mode 100644 index 0000000000..7e2a4cad2e --- /dev/null +++ b/packages/frontend-app-api/src/routing/collectRouteIds.ts @@ -0,0 +1,70 @@ +/* + * 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, + ExtensionOverrides, + RouteRef, + SubRouteRef, + ExternalRouteRef, +} from '@backstage/frontend-plugin-api'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalRouteRef } from '../../../frontend-plugin-api/src/routing/RouteRef'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef'; + +/** @internal */ +export interface RouteRefsById { + routes: Map<string, RouteRef | SubRouteRef>; + externalRoutes: Map<string, ExternalRouteRef>; +} + +/** @internal */ +export function collectRouteIds( + features: (BackstagePlugin | ExtensionOverrides)[], +): RouteRefsById { + const routesById = new Map<string, RouteRef | SubRouteRef>(); + const externalRoutesById = new Map<string, ExternalRouteRef>(); + + for (const feature of features) { + if (feature.$$type !== '@backstage/BackstagePlugin') { + continue; + } + + for (const [name, ref] of Object.entries(feature.routes)) { + const refId = `plugin.${feature.id}.routes.${name}`; + if (routesById.has(refId)) { + throw new Error(`Unexpected duplicate route '${refId}'`); + } + + const internalRef = toInternalRouteRef(ref); + internalRef.setId(refId); + routesById.set(refId, ref); + } + for (const [name, ref] of Object.entries(feature.externalRoutes)) { + const refId = `plugin.${feature.id}.externalRoutes.${name}`; + if (externalRoutesById.has(refId)) { + throw new Error(`Unexpected duplicate external route '${refId}'`); + } + + const internalRef = toInternalExternalRouteRef(ref); + internalRef.setId(refId); + externalRoutesById.set(refId, ref); + } + } + + return { routes: routesById, externalRoutes: externalRoutesById }; +} diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts index c64dc7a3b9..0de33b50f2 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.test.ts @@ -15,38 +15,39 @@ */ import React from 'react'; -import { - BackstagePlugin, - RouteRef, - createRouteRef, -} from '@backstage/core-plugin-api'; +import { BackstagePlugin } from '@backstage/core-plugin-api'; import { extractRouteInfoFromInstanceTree } from './extractRouteInfoFromInstanceTree'; import { + AnyRouteRefParams, Extension, + RouteRef, coreExtensionData, createExtension, createExtensionInput, createPlugin, + createRouteRef, } from '@backstage/frontend-plugin-api'; import { createInstances } from '../wiring/createApp'; import { MockConfigApi } from '@backstage/test-utils'; -const ref1 = createRouteRef({ id: 'page1' }); -const ref2 = createRouteRef({ id: 'page2' }); -const ref3 = createRouteRef({ id: 'page3' }); -const ref4 = createRouteRef({ id: 'page4' }); -const ref5 = createRouteRef({ id: 'page5' }); -const refOrder = [ref1, ref2, ref3, ref4, ref5]; +const ref1 = createRouteRef(); +const ref2 = createRouteRef(); +const ref3 = createRouteRef(); +const ref4 = createRouteRef(); +const ref5 = createRouteRef(); +const refOrder: RouteRef<AnyRouteRefParams>[] = [ref1, ref2, ref3, ref4, ref5]; function createTestExtension(options: { id: string; - at?: string; + parent?: string; path?: string; routeRef?: RouteRef; }) { return createExtension({ id: options.id, - at: options.at ?? 'core.routes/children', + attachTo: options.parent + ? { id: options.parent, input: 'children' } + : { id: 'core.routes', input: 'routes' }, output: { element: coreExtensionData.reactElement, path: coreExtensionData.routePath.optional(), @@ -72,12 +73,12 @@ function routeInfoFromExtensions(extensions: Extension<unknown>[]) { id: 'test', extensions, }); - const { rootInstances } = createInstances({ + const { coreInstance } = createInstances({ config: new MockConfigApi({}), - plugins: [plugin], + features: [plugin], }); - return extractRouteInfoFromInstanceTree(rootInstances); + return extractRouteInfoFromInstanceTree(coreInstance); } function sortedEntries<T>(map: Map<RouteRef, T>): [RouteRef, T][] { @@ -126,13 +127,13 @@ describe('discovery', () => { }), createTestExtension({ id: 'page2', - at: 'page1/children', + parent: 'page1', path: 'bar/:id', routeRef: ref2, }), createTestExtension({ id: 'page3', - at: 'page2/children', + parent: 'page2', path: 'baz', routeRef: ref3, }), @@ -143,7 +144,7 @@ describe('discovery', () => { }), createTestExtension({ id: 'page5', - at: 'page1/children', + parent: 'page1', path: 'blop', routeRef: ref5, }), @@ -194,7 +195,7 @@ describe('discovery', () => { }), createTestExtension({ id: 'page2', - at: 'page1/children', + parent: 'page1', path: 'bar/:id', routeRef: ref2, }), @@ -205,13 +206,13 @@ describe('discovery', () => { }), createTestExtension({ id: 'page4', - at: 'page3/children', + parent: 'page3', path: 'divsoup', routeRef: ref4, }), createTestExtension({ id: 'page5', - at: 'page3/children', + parent: 'page3', path: 'blop', routeRef: ref5, }), @@ -242,7 +243,7 @@ describe('discovery', () => { }), createTestExtension({ id: 'page2', - at: 'page1/children', + parent: 'page1', path: '/bar/:id', routeRef: ref2, }), @@ -253,13 +254,13 @@ describe('discovery', () => { }), createTestExtension({ id: 'page4', - at: 'page3/children', + parent: 'page3', path: '/divsoup', routeRef: ref4, }), createTestExtension({ id: 'page5', - at: 'page3/children', + parent: 'page3', path: '/blop', routeRef: ref5, }), @@ -289,20 +290,21 @@ describe('discovery', () => { }), createTestExtension({ id: 'page1', - at: 'foo/children', + parent: 'foo', routeRef: ref1, }), createTestExtension({ id: 'fooChild', - at: 'foo/children', + parent: 'foo', }), createTestExtension({ id: 'page2', - at: 'fooChild/children', + parent: 'fooChild', routeRef: ref2, }), createTestExtension({ id: 'fooEmpty', + parent: 'foo', }), createTestExtension({ id: 'page3', @@ -311,17 +313,17 @@ describe('discovery', () => { }), createTestExtension({ id: 'page3Child', - at: 'page3/children', + parent: 'page3', path: '', }), createTestExtension({ id: 'page4', - at: 'page3Child/children', + parent: 'page3Child', routeRef: ref4, }), createTestExtension({ id: 'page5', - at: 'page4/children', + parent: 'page4', routeRef: ref5, }), ]); @@ -361,29 +363,29 @@ describe('discovery', () => { }), createTestExtension({ id: 'page1Child', - at: 'page1/children', + parent: 'page1', path: 'bar', }), createTestExtension({ id: 'page2', - at: 'page1Child/children', + parent: 'page1Child', routeRef: ref2, }), createTestExtension({ id: 'page3', - at: 'page2/children', + parent: 'page2', path: 'baz', routeRef: ref3, }), createTestExtension({ id: 'page4', - at: 'page3/children', + parent: 'page3', path: '/blop', routeRef: ref4, }), createTestExtension({ id: 'page5', - at: 'page2/children', + parent: 'page2', routeRef: ref5, }), ]); @@ -445,30 +447,30 @@ describe('discovery', () => { }), createTestExtension({ id: 'page1', - at: 'r/children', + parent: 'r', path: 'x', routeRef: ref1, }), createTestExtension({ id: 'y', path: 'y', - at: 'r/children', + parent: 'r', }), createTestExtension({ id: 'page2', - at: 'y/children', + parent: 'y', path: '1', routeRef: ref2, }), createTestExtension({ id: 'page3', - at: 'page2/children', + parent: 'page2', path: 'a', routeRef: ref3, }), createTestExtension({ id: 'page4', - at: 'page2/children', + parent: 'page2', path: 'b', routeRef: ref4, }), diff --git a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts index 30305b0d2c..0bf9c2d1dd 100644 --- a/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts +++ b/packages/frontend-app-api/src/routing/extractRouteInfoFromInstanceTree.ts @@ -14,12 +14,11 @@ * limitations under the License. */ -import { RouteRef } from '@backstage/core-plugin-api'; -import { coreExtensionData } from '@backstage/frontend-plugin-api'; +import { RouteRef, coreExtensionData } from '@backstage/frontend-plugin-api'; import { ExtensionInstance } from '../wiring/createExtensionInstance'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { BackstageRouteObject } from '../../../core-app-api/src/routing/types'; import { toLegacyPlugin } from '../wiring/createApp'; +import { BackstageRouteObject } from './types'; // 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. @@ -42,7 +41,7 @@ export function joinPaths(...paths: string[]): string { return normalized; } -export function extractRouteInfoFromInstanceTree(roots: ExtensionInstance[]): { +export function extractRouteInfoFromInstanceTree(core: ExtensionInstance): { routePaths: Map<RouteRef, string>; routeParents: Map<RouteRef, RouteRef | undefined>; routeObjects: BackstageRouteObject[]; @@ -109,13 +108,6 @@ export function extractRouteInfoFromInstanceTree(roots: ExtensionInstance[]): { // Whenever a route ref is encountered, we need to give it a route path and position in the ref tree. if (routeRef) { - const routeRefId = (routeRef as any).id; // TODO: properly - if (routeRefId !== current.id) { - throw new Error( - `Route ref '${routeRefId}' must have the same ID as extension '${current.id}'`, - ); - } - // The first route ref we find after encountering a route path is selected to be used as the // parent ref further down the tree. We don't start using this candidate ref until we encounter // another route path though, at which point we repeat the process and select another candidate. @@ -151,9 +143,7 @@ export function extractRouteInfoFromInstanceTree(roots: ExtensionInstance[]): { } } - for (const root of roots) { - visit(root); - } + visit(core); return { routePaths, routeParents, routeObjects }; } diff --git a/packages/frontend-app-api/src/routing/index.ts b/packages/frontend-app-api/src/routing/index.ts new file mode 100644 index 0000000000..8c26a732d3 --- /dev/null +++ b/packages/frontend-app-api/src/routing/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 { type AppRouteBinder } from './resolveRouteBindings'; diff --git a/packages/frontend-app-api/src/routing/resolveRouteBindings.test.ts b/packages/frontend-app-api/src/routing/resolveRouteBindings.test.ts new file mode 100644 index 0000000000..d80a02e34d --- /dev/null +++ b/packages/frontend-app-api/src/routing/resolveRouteBindings.test.ts @@ -0,0 +1,120 @@ +/* + * 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 { + createExternalRouteRef, + createRouteRef, +} from '@backstage/frontend-plugin-api'; +import { resolveRouteBindings } from './resolveRouteBindings'; +import { ConfigReader } from '@backstage/config'; + +const emptyIds = { routes: new Map(), externalRoutes: new Map() }; + +describe('resolveRouteBindings', () => { + it('runs happy path', () => { + const external = { myRoute: createExternalRouteRef() }; + const ref = createRouteRef(); + const result = resolveRouteBindings( + ({ bind }) => { + bind(external, { myRoute: ref }); + }, + new ConfigReader({}), + emptyIds, + ); + + expect(result.get(external.myRoute)).toBe(ref); + }); + + it('throws on unknown keys', () => { + const external = { myRoute: createExternalRouteRef() }; + const ref = createRouteRef(); + expect(() => + resolveRouteBindings( + ({ bind }) => { + bind(external, { someOtherRoute: ref } as any); + }, + new ConfigReader({}), + emptyIds, + ), + ).toThrow('Key someOtherRoute is not an existing external route'); + }); + + it('reads bindings from config', () => { + const mySource = createExternalRouteRef(); + const myTarget = createRouteRef(); + const result = resolveRouteBindings( + () => {}, + new ConfigReader({ + app: { routes: { bindings: { mySource: 'myTarget' } } }, + }), + { + routes: new Map([['myTarget', myTarget]]), + externalRoutes: new Map([['mySource', mySource]]), + }, + ); + + expect(result.get(mySource)).toBe(myTarget); + }); + + it('throws on invalid config', () => { + expect(() => + resolveRouteBindings( + () => {}, + new ConfigReader({ app: { routes: { bindings: 'derp' } } }), + emptyIds, + ), + ).toThrow( + "Invalid type in config for key 'app.routes.bindings' in 'mock-config', got string, wanted object", + ); + + expect(() => + resolveRouteBindings( + () => {}, + new ConfigReader({ app: { routes: { bindings: { mySource: true } } } }), + emptyIds, + ), + ).toThrow( + "Invalid config at app.routes.bindings['mySource'], value must be a non-empty string", + ); + + expect(() => + resolveRouteBindings( + () => {}, + new ConfigReader({ + app: { routes: { bindings: { mySource: 'myTarget' } } }, + }), + emptyIds, + ), + ).toThrow( + "Invalid config at app.routes.bindings, 'mySource' is not a valid external route", + ); + + expect(() => + resolveRouteBindings( + () => {}, + new ConfigReader({ + app: { routes: { bindings: { mySource: 'myTarget' } } }, + }), + { + ...emptyIds, + externalRoutes: new Map([['mySource', createExternalRouteRef()]]), + }, + ), + ).toThrow( + "Invalid config at app.routes.bindings['mySource'], 'myTarget' is not a valid route", + ); + }); +}); diff --git a/packages/frontend-app-api/src/routing/resolveRouteBindings.ts b/packages/frontend-app-api/src/routing/resolveRouteBindings.ts new file mode 100644 index 0000000000..f5a2e5bd94 --- /dev/null +++ b/packages/frontend-app-api/src/routing/resolveRouteBindings.ts @@ -0,0 +1,142 @@ +/* + * 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 { + RouteRef, + SubRouteRef, + ExternalRouteRef, +} from '@backstage/frontend-plugin-api'; +import { RouteRefsById } from './collectRouteIds'; +import { Config } from '@backstage/config'; +import { JsonObject } from '@backstage/types'; + +/** + * Extracts a union of the keys in a map whose value extends the given type + * + * @ignore + */ +type KeysWithType<Obj extends { [key in string]: any }, Type> = { + [key in keyof Obj]: Obj[key] extends Type ? key : never; +}[keyof Obj]; + +/** + * Takes a map Map required values and makes all keys matching Keys optional + * + * @ignore + */ +type PartialKeys< + Map extends { [name in string]: any }, + Keys extends keyof Map, +> = Partial<Pick<Map, Keys>> & Required<Omit<Map, Keys>>; + +/** + * Creates a map of target routes with matching parameters based on a map of external routes. + * + * @ignore + */ +type TargetRouteMap< + ExternalRoutes extends { [name: string]: ExternalRouteRef }, +> = { + [name in keyof ExternalRoutes]: ExternalRoutes[name] extends ExternalRouteRef< + infer Params, + any + > + ? RouteRef<Params> | SubRouteRef<Params> + : never; +}; + +/** + * A function that can bind from external routes of a given plugin, to concrete + * routes of other plugins. See {@link createApp}. + * + * @public + */ +export type AppRouteBinder = < + TExternalRoutes extends { [name: string]: ExternalRouteRef }, +>( + externalRoutes: TExternalRoutes, + targetRoutes: PartialKeys< + TargetRouteMap<TExternalRoutes>, + KeysWithType<TExternalRoutes, ExternalRouteRef<any, true>> + >, +) => void; + +/** @internal */ +export function resolveRouteBindings( + bindRoutes: ((context: { bind: AppRouteBinder }) => void) | undefined, + config: Config, + routesById: RouteRefsById, +): Map<ExternalRouteRef, RouteRef | SubRouteRef> { + const result = new Map<ExternalRouteRef, RouteRef | SubRouteRef>(); + + if (bindRoutes) { + const bind: AppRouteBinder = ( + externalRoutes, + targetRoutes: { [name: string]: RouteRef | SubRouteRef }, + ) => { + for (const [key, value] of Object.entries(targetRoutes)) { + const externalRoute = externalRoutes[key]; + if (!externalRoute) { + throw new Error(`Key ${key} is not an existing external route`); + } + if (!value && !externalRoute.optional) { + throw new Error( + `External route ${key} is required but was undefined`, + ); + } + if (value) { + result.set(externalRoute, value); + } + } + }; + bindRoutes({ bind }); + } + + const bindingsConfig = config.getOptionalConfig('app.routes.bindings'); + if (!bindingsConfig) { + return result; + } + + const bindings = bindingsConfig.get<JsonObject>(); + for (const [externalRefId, targetRefId] of Object.entries(bindings)) { + if (typeof targetRefId !== 'string' || targetRefId === '') { + throw new Error( + `Invalid config at app.routes.bindings['${externalRefId}'], value must be a non-empty string`, + ); + } + + const externalRef = routesById.externalRoutes.get(externalRefId); + if (!externalRef) { + throw new Error( + `Invalid config at app.routes.bindings, '${externalRefId}' is not a valid external route`, + ); + } + // Route bindings defined in config have lower priority than those defined in code + if (result.has(externalRef)) { + continue; + } + const targetRef = routesById.routes.get(targetRefId); + if (!targetRef) { + throw new Error( + `Invalid config at app.routes.bindings['${externalRefId}'], '${targetRefId}' is not a valid route`, + ); + } + + result.set(externalRef, targetRef); + } + + return result; +} diff --git a/packages/frontend-app-api/src/routing/types.ts b/packages/frontend-app-api/src/routing/types.ts new file mode 100644 index 0000000000..5f1ed9be84 --- /dev/null +++ b/packages/frontend-app-api/src/routing/types.ts @@ -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 { + ExternalRouteRef, + RouteRef, + SubRouteRef, +} from '@backstage/frontend-plugin-api'; +import { BackstagePlugin as LegacyBackstagePlugin } from '@backstage/core-plugin-api'; + +/** @internal */ +export type AnyRouteRef = RouteRef | SubRouteRef | ExternalRouteRef; + +/** + * A duplicate of the react-router RouteObject, but with routeRef added + * @internal + */ +export interface BackstageRouteObject { + caseSensitive: boolean; + children?: BackstageRouteObject[]; + element: React.ReactNode; + path: string; + routeRefs: Set<RouteRef>; + plugins: Set<LegacyBackstagePlugin>; +} diff --git a/packages/frontend-app-api/src/wiring/createApp.test.tsx b/packages/frontend-app-api/src/wiring/createApp.test.tsx index f6172f5a4b..de574bc6a9 100644 --- a/packages/frontend-app-api/src/wiring/createApp.test.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.test.tsx @@ -16,49 +16,55 @@ import { createExtension, + createExtensionOverrides, createPageExtension, createPlugin, + createRouteRef, createThemeExtension, } from '@backstage/frontend-plugin-api'; import { createApp, createInstances } from './createApp'; -import { screen } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; import { MockConfigApi, renderWithEffects } from '@backstage/test-utils'; import React from 'react'; -import { createRouteRef } from '@backstage/core-plugin-api'; + +const extBaseConfig = { + id: 'test', + attachTo: { id: 'root', input: 'default' }, + output: {}, + factory() {}, +}; describe('createInstances', () => { - it('throws an error when a root extension is parametrized', () => { + it('throws an error when a core extension is parametrized', () => { const config = new MockConfigApi({ app: { extensions: [ { - root: { - at: '', - }, + core: {}, }, ], }, }); - const plugins = [ + const features = [ createPlugin({ id: 'plugin', extensions: [], }), ]; - expect(() => createInstances({ config, plugins })).toThrow( - "A 'root' extension configuration was detected, but the root extension is not configurable", + expect(() => createInstances({ config, features })).toThrow( + "A 'core' extension configuration was detected, but the core extension is not configurable", ); }); - it('throws an error when a root extension is overridden', () => { + it('throws an error when a core extension is overridden', () => { const config = new MockConfigApi({}); - const plugins = [ + const features = [ createPlugin({ id: 'plugin', extensions: [ createExtension({ - id: 'root', - at: 'core.routes/route', + id: 'core', + attachTo: { id: 'core.routes', input: 'route' }, inputs: {}, output: {}, factory() {}, @@ -66,8 +72,8 @@ describe('createInstances', () => { ], }), ]; - expect(() => createInstances({ config, plugins })).toThrow( - "The following plugin(s) are overriding the 'root' extension which is forbidden: plugin", + expect(() => createInstances({ config, features })).toThrow( + "The following plugin(s) are overriding the 'core' extension which is forbidden: plugin", ); }); @@ -77,14 +83,14 @@ describe('createInstances', () => { const ExtensionA = createPageExtension({ id: 'A', defaultPath: '/', - routeRef: createRouteRef({ id: 'A.route' }), + routeRef: createRouteRef(), loader: async () => <div>Extension A</div>, }); const ExtensionB = createPageExtension({ id: 'B', defaultPath: '/', - routeRef: createRouteRef({ id: 'B.route' }), + routeRef: createRouteRef(), loader: async () => <div>Extension B</div>, }); @@ -98,12 +104,32 @@ describe('createInstances', () => { extensions: [ExtensionA, ExtensionB, ExtensionB], }); - const plugins = [PluginA, PluginB]; + const features = [PluginA, PluginB]; - expect(() => createInstances({ config, plugins })).toThrow( + expect(() => createInstances({ config, features })).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('throws an error when duplicated extension overrides are detected', () => { + expect(() => + createInstances({ + config: new MockConfigApi({}), + features: [ + createExtensionOverrides({ + extensions: [ + createExtension({ ...extBaseConfig, id: 'a' }), + createExtension({ ...extBaseConfig, id: 'a' }), + createExtension({ ...extBaseConfig, id: 'b' }), + ], + }), + createExtensionOverrides({ + extensions: [createExtension({ ...extBaseConfig, id: 'b' })], + }), + ], + }), + ).toThrow('The following extensions had duplicate overrides: a, b'); + }); }); describe('createApp', () => { @@ -115,7 +141,7 @@ describe('createApp', () => { extensions: [{ 'themes.light': false }, { 'themes.dark': false }], }, }), - plugins: [ + features: [ createPlugin({ id: 'test', extensions: [ @@ -134,4 +160,126 @@ describe('createApp', () => { await expect(screen.findByText('Derp')).resolves.toBeInTheDocument(); }); + + it('should log an app', () => { + const { coreInstance } = createInstances({ + config: new MockConfigApi({}), + features: [], + }); + + expect(String(coreInstance)).toMatchInlineSnapshot(` + "<core out=[core.reactElement]> + root [ + <core.layout out=[core.reactElement]> + content [ + <core.routes out=[core.reactElement] /> + ] + nav [ + <core.nav out=[core.reactElement] /> + ] + </core.layout> + ] + themes [ + <themes.light out=[core.theme] /> + <themes.dark out=[core.theme] /> + ] + </core>" + `); + }); + + it('should serialize an app as JSON', () => { + const { coreInstance } = createInstances({ + config: new MockConfigApi({}), + features: [], + }); + + expect(JSON.parse(JSON.stringify(coreInstance))).toMatchInlineSnapshot(` + { + "attachments": { + "root": [ + { + "attachments": { + "content": [ + { + "id": "core.routes", + "output": [ + "core.reactElement", + ], + }, + ], + "nav": [ + { + "id": "core.nav", + "output": [ + "core.reactElement", + ], + }, + ], + }, + "id": "core.layout", + "output": [ + "core.reactElement", + ], + }, + ], + "themes": [ + { + "id": "themes.light", + "output": [ + "core.theme", + ], + }, + { + "id": "themes.dark", + "output": [ + "core.theme", + ], + }, + ], + }, + "id": "core", + "output": [ + "core.reactElement", + ], + } + `); + }); + + it('should deduplicate features keeping the last received one', async () => { + const duplicatedFeatureId = 'test'; + const app = createApp({ + configLoader: async () => new MockConfigApi({}), + features: [ + createPlugin({ + id: duplicatedFeatureId, + extensions: [ + createPageExtension({ + id: 'test.page.first', + defaultPath: '/', + loader: async () => <div>First Page</div>, + }), + ], + }), + createPlugin({ + id: duplicatedFeatureId, + extensions: [ + createPageExtension({ + id: 'test.page.last', + defaultPath: '/', + loader: async () => <div>Last Page</div>, + }), + ], + }), + ], + }); + + await renderWithEffects(app.createRoot()); + + await waitFor(() => + expect(screen.queryByText('First Page')).not.toBeInTheDocument(), + ); + await waitFor(() => + expect(screen.getByText('Last Page')).toBeInTheDocument(), + ); + }); }); diff --git a/packages/frontend-app-api/src/wiring/createApp.tsx b/packages/frontend-app-api/src/wiring/createApp.tsx index 540b47849f..e770a6b4c1 100644 --- a/packages/frontend-app-api/src/wiring/createApp.tsx +++ b/packages/frontend-app-api/src/wiring/createApp.tsx @@ -20,6 +20,9 @@ import { BackstagePlugin, coreExtensionData, ExtensionDataRef, + ExtensionOverrides, + RouteRef, + useRouteRef, } from '@backstage/frontend-plugin-api'; import { Core } from '../extensions/Core'; import { CoreRoutes } from '../extensions/CoreRoutes'; @@ -34,7 +37,6 @@ import { mergeExtensionParameters, readAppExtensionParameters, } from './parameters'; -import { RoutingProvider } from '../routing/RoutingContext'; import { AnyApiFactory, ApiHolder, @@ -44,15 +46,13 @@ import { ConfigApi, configApiRef, IconComponent, - RouteRef, BackstagePlugin as LegacyBackstagePlugin, featureFlagsApiRef, attachComponentData, - useRouteRef, identityApiRef, AppTheme, } from '@backstage/core-plugin-api'; -import { getAvailablePlugins } from './discovery'; +import { getAvailableFeatures } from './discovery'; import { ApiFactoryRegistry, ApiProvider, @@ -74,7 +74,9 @@ import { defaultConfigLoaderSync } from '../../../core-app-api/src/app/defaultCo // eslint-disable-next-line @backstage/no-relative-monorepo-imports import { overrideBaseUrlConfigs } from '../../../core-app-api/src/app/overrideBaseUrlConfigs'; // eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { RoutingProvider as LegacyRoutingProvider } from '../../../core-app-api/src/routing/RoutingProvider'; +import { AppLanguageSelector } from '../../../core-app-api/src/apis/implementations/AppLanguageApi/AppLanguageSelector'; +// 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, @@ -86,6 +88,14 @@ import { SidebarItem } from '@backstage/core-components'; import { DarkTheme, LightTheme } from '../extensions/themes'; import { extractRouteInfoFromInstanceTree } from '../routing/extractRouteInfoFromInstanceTree'; import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; +import { + appLanguageApiRef, + translationApiRef, +} from '@backstage/core-plugin-api/alpha'; +import { AppRouteBinder } from '../routing'; +import { RoutingProvider } from '../routing/RoutingProvider'; +import { resolveRouteBindings } from '../routing/resolveRouteBindings'; +import { collectRouteIds } from '../routing/collectRouteIds'; /** @public */ export interface ExtensionTreeNode { @@ -105,9 +115,9 @@ export interface ExtensionTree { export function createExtensionTree(options: { config: Config; }): ExtensionTree { - const plugins = getAvailablePlugins(); + const features = getAvailableFeatures(options.config); const { instances } = createInstances({ - plugins, + features, config: options.config, }); @@ -173,7 +183,7 @@ export function createExtensionTree(options: { * @internal */ export function createInstances(options: { - plugins: BackstagePlugin[]; + features: (BackstagePlugin | ExtensionOverrides)[]; config: Config; }) { const builtinExtensions = [ @@ -188,7 +198,7 @@ export function createInstances(options: { // pull in default extension instance from discovered packages // apply config to adjust default extension instances and add more const extensionParams = mergeExtensionParameters({ - sources: options.plugins, + features: options.features, builtinExtensions, parameters: readAppExtensionParameters(options.config), }); @@ -202,8 +212,8 @@ export function createInstances(options: { Map<string, ExtensionInstanceParameters[]> >(); for (const instanceParams of extensionParams) { - const [extensionId, pointId = 'default'] = instanceParams.at.split('/'); - + const extensionId = instanceParams.attachTo.id; + const pointId = instanceParams.attachTo.input; let pointMap = attachmentMap.get(extensionId); if (!pointMap) { pointMap = new Map(); @@ -250,20 +260,44 @@ export function createInstances(options: { return newInstance; } - const rootConfigs = attachmentMap.get('root')?.get('default') ?? []; - - const rootInstances = rootConfigs.map(instanceParams => - createInstance(instanceParams), + const coreInstance = createInstance( + extensionParams.find(p => p.extension.id === 'core')!, ); - return { instances, rootInstances }; + return { coreInstance, instances }; +} + +function deduplicateFeatures( + allFeatures: (BackstagePlugin | ExtensionOverrides)[], +): (BackstagePlugin | ExtensionOverrides)[] { + // Start by removing duplicates by reference + const features = Array.from(new Set(allFeatures)); + + // Plugins are deduplicated by ID, last one wins + const seenIds = new Set<string>(); + return features + .reverse() + .filter(feature => { + if (feature.$$type !== '@backstage/BackstagePlugin') { + return true; + } + if (seenIds.has(feature.id)) { + return false; + } + seenIds.add(feature.id); + return true; + }) + .reverse(); } /** @public */ export function createApp(options: { - plugins: BackstagePlugin[]; + features?: (BackstagePlugin | ExtensionOverrides)[]; configLoader?: () => Promise<ConfigApi>; - pluginLoader?: (ctx: { config: ConfigApi }) => Promise<BackstagePlugin[]>; + bindRoutes?(context: { bind: AppRouteBinder }): void; + featureLoader?: (ctx: { + config: ConfigApi; + }) => Promise<(BackstagePlugin | ExtensionOverrides)[]>; }): { createRoot(): JSX.Element; } { @@ -274,49 +308,44 @@ export function createApp(options: { overrideBaseUrlConfigs(defaultConfigLoaderSync()), ); - const discoveredPlugins = getAvailablePlugins(); - const loadedPlugins = (await options.pluginLoader?.({ config })) ?? []; - const allPlugins = Array.from( - new Set([...discoveredPlugins, ...options.plugins, ...loadedPlugins]), - ); + const discoveredFeatures = getAvailableFeatures(config); + const loadedFeatures = (await options.featureLoader?.({ config })) ?? []; + const allFeatures = deduplicateFeatures([ + ...discoveredFeatures, + ...loadedFeatures, + ...(options.features ?? []), + ]); - const { rootInstances } = createInstances({ - plugins: allPlugins, + const { coreInstance } = createInstances({ + features: allFeatures, config, }); - const routeInfo = extractRouteInfoFromInstanceTree(rootInstances); + const appContext = createLegacyAppContext( + allFeatures.filter( + (f): f is BackstagePlugin => f.$$type === '@backstage/BackstagePlugin', + ), + ); - const coreInstance = rootInstances.find(({ id }) => id === 'core'); - if (!coreInstance) { - throw Error('Unable to find core extension instance'); - } - - const apiHolder = createApiHolder(coreInstance, config); - - const appContext = createLegacyAppContext(allPlugins); - - const rootElements = rootInstances - .map(e => ( - <React.Fragment key={e.id}> - {e.getData(coreExtensionData.reactElement)} - </React.Fragment> - )) - .filter((x): x is JSX.Element => !!x); + const routeIds = collectRouteIds(allFeatures); const App = () => ( - <ApiProvider apis={apiHolder}> + <ApiProvider apis={createApiHolder(coreInstance, config)}> <AppContextProvider appContext={appContext}> <AppThemeProvider> - <LegacyRoutingProvider - {...routeInfo} - routeBindings={new Map(/* TODO */)} + <RoutingProvider + {...extractRouteInfoFromInstanceTree(coreInstance)} + routeBindings={resolveRouteBindings( + options.bindRoutes, + config, + routeIds, + )} > - <RoutingProvider routePaths={routeInfo.routePaths}> - {/* TODO: set base path using the logic from AppRouter */} - <BrowserRouter>{rootElements}</BrowserRouter> - </RoutingProvider> - </LegacyRoutingProvider> + {/* TODO: set base path using the logic from AppRouter */} + <BrowserRouter> + {coreInstance.getData(coreExtensionData.reactElement)} + </BrowserRouter> + </RoutingProvider> </AppThemeProvider> </AppContextProvider> </ApiProvider> @@ -463,12 +492,42 @@ function createApiHolder( factory: () => AppThemeSelector.createWithStorage(themeExtensions), }); + factoryRegistry.register('static', { + api: appLanguageApiRef, + deps: {}, + factory: () => AppLanguageSelector.createWithStorage(), + }); + + factoryRegistry.register('default', { + api: translationApiRef, + deps: { languageApi: appLanguageApiRef }, + factory: ({ languageApi }) => + I18nextTranslationApi.create({ + languageApi, + }), + }); + factoryRegistry.register('static', { api: configApiRef, deps: {}, factory: () => configApi, }); + factoryRegistry.register('static', { + api: appLanguageApiRef, + deps: {}, + factory: () => AppLanguageSelector.createWithStorage(), + }); + + factoryRegistry.register('default', { + api: translationApiRef, + deps: { languageApi: appLanguageApiRef }, + factory: ({ languageApi }) => + I18nextTranslationApi.create({ + languageApi, + }), + }); + // TODO: ship these as default extensions instead for (const factory of defaultApis as AnyApiFactory[]) { if (!factoryRegistry.register('app', factory)) { diff --git a/packages/frontend-app-api/src/wiring/createExtensionInstance.test.ts b/packages/frontend-app-api/src/wiring/createExtensionInstance.test.ts index 12e109874a..6e69e99cb7 100644 --- a/packages/frontend-app-api/src/wiring/createExtensionInstance.test.ts +++ b/packages/frontend-app-api/src/wiring/createExtensionInstance.test.ts @@ -28,7 +28,7 @@ const inputMirrorDataRef = createExtensionDataRef<unknown>('mirror'); const simpleExtension = createExtension({ id: 'core.test', - at: 'ignored', + attachTo: { id: 'ignored', input: 'ignored' }, output: { test: testDataRef, other: otherDataRef.optional(), @@ -101,7 +101,7 @@ describe('createExtensionInstance', () => { config: undefined, extension: createExtension({ id: 'core.test', - at: 'ignored', + attachTo: { id: 'ignored', input: 'ignored' }, inputs: { optionalSingletonPresent: createExtensionInput( { @@ -166,7 +166,7 @@ describe('createExtensionInstance', () => { config: { other: 'not-a-number' }, extension: createExtension({ id: 'core.test', - at: 'ignored', + attachTo: { id: 'ignored', input: 'ignored' }, output: {}, factory() { const error = new Error('NOPE'); @@ -188,7 +188,7 @@ describe('createExtensionInstance', () => { config: undefined, extension: createExtension({ id: 'core.test', - at: 'ignored', + attachTo: { id: 'ignored', input: 'ignored' }, output: { test1: testDataRef, test2: testDataRef, @@ -211,7 +211,7 @@ describe('createExtensionInstance', () => { config: undefined, extension: createExtension({ id: 'core.test', - at: 'ignored', + attachTo: { id: 'ignored', input: 'ignored' }, output: { test: testDataRef, }, @@ -232,7 +232,7 @@ describe('createExtensionInstance', () => { config: undefined, extension: createExtension({ id: 'core.test', - at: 'ignored', + attachTo: { id: 'ignored', input: 'ignored' }, inputs: { singleton: createExtensionInput( { @@ -250,6 +250,92 @@ describe('createExtensionInstance', () => { ); }); + it('should refuse to create an instance with undeclared inputs', () => { + expect(() => + createExtensionInstance({ + attachments: new Map([ + [ + 'declared', + [ + createExtensionInstance({ + attachments: new Map(), + config: { output: 'many1' }, + extension: simpleExtension, + }), + ], + ], + [ + 'undeclared', + [ + createExtensionInstance({ + attachments: new Map(), + config: { output: 'many1' }, + extension: simpleExtension, + }), + ], + ], + ]), + config: undefined, + extension: createExtension({ + id: 'core.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'", + ); + }); + + it('should refuse to create an instance with multiple undeclared inputs', () => { + expect(() => + createExtensionInstance({ + attachments: new Map([ + [ + 'undeclared1', + [ + createExtensionInstance({ + attachments: new Map(), + config: { output: 'many1' }, + extension: simpleExtension, + }), + ], + ], + [ + 'undeclared2', + [ + createExtensionInstance({ + attachments: new Map(), + config: { output: 'many1' }, + extension: simpleExtension, + }), + createExtensionInstance({ + attachments: new Map(), + config: { output: 'many1' }, + extension: simpleExtension, + }), + ], + ], + ]), + config: undefined, + extension: createExtension({ + id: 'core.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'", + ); + }); + it('should refuse to create an instance with multiple inputs for required singleton', () => { expect(() => createExtensionInstance({ @@ -273,7 +359,7 @@ describe('createExtensionInstance', () => { config: undefined, extension: createExtension({ id: 'core.test', - at: 'ignored', + attachTo: { id: 'ignored', input: 'ignored' }, inputs: { singleton: createExtensionInput( { @@ -314,7 +400,7 @@ describe('createExtensionInstance', () => { config: undefined, extension: createExtension({ id: 'core.test', - at: 'ignored', + attachTo: { id: 'ignored', input: 'ignored' }, inputs: { singleton: createExtensionInput( { @@ -350,7 +436,7 @@ describe('createExtensionInstance', () => { config: undefined, extension: createExtension({ id: 'core.test', - at: 'ignored', + attachTo: { id: 'ignored', input: 'ignored' }, inputs: { singleton: createExtensionInput( { diff --git a/packages/frontend-app-api/src/wiring/createExtensionInstance.ts b/packages/frontend-app-api/src/wiring/createExtensionInstance.ts index 18551eb8da..5a325dc0a0 100644 --- a/packages/frontend-app-api/src/wiring/createExtensionInstance.ts +++ b/packages/frontend-app-api/src/wiring/createExtensionInstance.ts @@ -60,6 +60,24 @@ function resolveInputs( inputMap: AnyExtensionInputMap, attachments: Map<string, ExtensionInstance[]>, ) { + const undeclaredAttachments = Array.from(attachments.entries()).filter( + ([inputName]) => inputMap[inputName] === undefined, + ); + if (undeclaredAttachments.length > 0) { + throw new Error( + `received undeclared input${ + undeclaredAttachments.length > 1 ? 's' : '' + } ${undeclaredAttachments + .map( + ([k, exts]) => + `'${k}' from extension${exts.length > 1 ? 's' : ''} '${exts + .map(e => e.id) + .join("', '")}'`, + ) + .join(' and ')}`, + ); + } + return mapValues(inputMap, (input, inputName) => { const attachedInstances = attachments.get(inputName) ?? []; if (input.config.singleton) { @@ -90,6 +108,68 @@ function resolveInputs( }); } +function indent(str: string) { + return str.replace(/^/gm, ' '); +} + +class ExtensionInstanceImpl implements ExtensionInstance { + readonly $$type = '@backstage/ExtensionInstance'; + + readonly id: string; + readonly #extensionData: Map<string, unknown>; + readonly attachments: Map<string, ExtensionInstance[]>; + readonly source?: BackstagePlugin; + + constructor( + id: string, + extensionData: Map<string, unknown>, + attachments: Map<string, ExtensionInstance[]>, + source: BackstagePlugin | undefined, + ) { + this.id = id; + this.#extensionData = extensionData; + this.attachments = attachments; + this.source = source; + } + + getData<T>(ref: ExtensionDataRef<T>): T | undefined { + return this.#extensionData.get(ref.id) as T | undefined; + } + + toJSON() { + return { + id: this.id, + output: + this.#extensionData.size > 0 + ? [...this.#extensionData.keys()] + : undefined, + attachments: + this.attachments.size > 0 + ? Object.fromEntries(this.attachments) + : undefined, + }; + } + + toString() { + const out = + this.#extensionData.size > 0 + ? ` out=[${[...this.#extensionData.keys()].join(', ')}]` + : ''; + + if (this.attachments.size === 0) { + return `<${this.id}${out} />`; + } + + return [ + `<${this.id}${out}>`, + ...[...this.attachments.entries()].map(([k, v]) => + indent([`${k} [`, ...v.map(e => indent(e.toString())), `]`].join('\n')), + ), + `</${this.id}>`, + ].join('\n'); + } +} + /** @internal */ export function createExtensionInstance(options: { extension: Extension<unknown>; @@ -137,13 +217,10 @@ export function createExtensionInstance(options: { ); } - return { - $$type: '@backstage/ExtensionInstance', - id: options.extension.id, - getData<T>(ref: ExtensionDataRef<T>): T | undefined { - return extensionData.get(ref.id) as T | undefined; - }, - source, + return new ExtensionInstanceImpl( + options.extension.id, + extensionData, attachments, - }; + source, + ); } diff --git a/packages/frontend-app-api/src/wiring/discovery.test.ts b/packages/frontend-app-api/src/wiring/discovery.test.ts index 5f1c4df718..6008ce6746 100644 --- a/packages/frontend-app-api/src/wiring/discovery.test.ts +++ b/packages/frontend-app-api/src/wiring/discovery.test.ts @@ -15,25 +15,30 @@ */ import { createPlugin } from '@backstage/frontend-plugin-api'; -import { getAvailablePlugins } from './discovery'; +import { getAvailableFeatures } from './discovery'; +import { ConfigReader } from '@backstage/config'; const globalSpy = jest.fn(); Object.defineProperty(global, '__@backstage/discovered__', { get: globalSpy, }); -describe('getAvailablePlugins', () => { +const config = new ConfigReader({ + app: { experimental: { packages: 'all' } }, +}); + +describe('getAvailableFeatures', () => { afterEach(jest.resetAllMocks); it('should discover nothing with undefined global', () => { - expect(getAvailablePlugins()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); }); it('should discover nothing with empty global', () => { globalSpy.mockReturnValue({ modules: [], }); - expect(getAvailablePlugins()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); }); it('should discover a plugin', () => { @@ -41,24 +46,24 @@ describe('getAvailablePlugins', () => { globalSpy.mockReturnValue({ modules: [{ default: testPlugin }], }); - expect(getAvailablePlugins()).toEqual([testPlugin]); + expect(getAvailableFeatures(config)).toEqual([testPlugin]); }); it('should ignore garbage', () => { globalSpy.mockReturnValueOnce({ modules: [{ default: null }] }); - expect(getAvailablePlugins()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); globalSpy.mockReturnValueOnce({ modules: [{ default: undefined }] }); - expect(getAvailablePlugins()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); globalSpy.mockReturnValueOnce({ modules: [{ default: Symbol() }] }); - expect(getAvailablePlugins()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); globalSpy.mockReturnValueOnce({ modules: [{ default: () => {} }] }); - expect(getAvailablePlugins()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); globalSpy.mockReturnValueOnce({ modules: [{ default: 0 }] }); - expect(getAvailablePlugins()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); globalSpy.mockReturnValueOnce({ modules: [{ default: false }] }); - expect(getAvailablePlugins()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); globalSpy.mockReturnValueOnce({ modules: [{ default: true }] }); - expect(getAvailablePlugins()).toEqual([]); + expect(getAvailableFeatures(config)).toEqual([]); }); it('should discover multiple plugins', () => { @@ -72,7 +77,7 @@ describe('getAvailablePlugins', () => { { default: test3Plugin }, ], }); - expect(getAvailablePlugins()).toEqual([ + expect(getAvailableFeatures(config)).toEqual([ test1Plugin, test2Plugin, test3Plugin, diff --git a/packages/frontend-app-api/src/wiring/discovery.ts b/packages/frontend-app-api/src/wiring/discovery.ts index 6d0b9282ea..1181992d53 100644 --- a/packages/frontend-app-api/src/wiring/discovery.ts +++ b/packages/frontend-app-api/src/wiring/discovery.ts @@ -14,28 +14,86 @@ * limitations under the License. */ -import { BackstagePlugin } from '@backstage/frontend-plugin-api'; +import { Config, ConfigReader } from '@backstage/config'; +import { + BackstagePlugin, + ExtensionOverrides, +} from '@backstage/frontend-plugin-api'; interface DiscoveryGlobal { - modules: Array<{ name: string; default: unknown }>; + modules: Array<{ name: string; export?: string; default: unknown }>; +} + +function readPackageDetectionConfig(config: Config) { + const packages = config.getOptional('app.experimental.packages'); + if (packages === undefined || packages === null) { + return undefined; + } + + if (typeof packages === 'string') { + if (packages !== 'all') { + throw new Error( + `Invalid app.experimental.packages mode, got '${packages}', expected 'all'`, + ); + } + return {}; + } + + if (typeof packages !== 'object' || Array.isArray(packages)) { + throw new Error( + "Invalid config at 'app.experimental.packages', expected object", + ); + } + const packagesConfig = new ConfigReader( + packages, + 'app.experimental.packages', + ); + + return { + include: packagesConfig.getOptionalStringArray('include'), + exclude: packagesConfig.getOptionalStringArray('exclude'), + }; } /** * @public */ -export function getAvailablePlugins(): BackstagePlugin[] { +export function getAvailableFeatures( + config: Config, +): (BackstagePlugin | ExtensionOverrides)[] { const discovered = ( window as { '__@backstage/discovered__'?: DiscoveryGlobal } )['__@backstage/discovered__']; + const detection = readPackageDetectionConfig(config); + if (!detection) { + return []; + } + return ( - discovered?.modules.map(m => m.default).filter(isBackstagePlugin) ?? [] + discovered?.modules + .filter(({ name }) => { + if (detection.exclude?.includes(name)) { + return false; + } + if (detection.include && !detection.include.includes(name)) { + return false; + } + return true; + }) + .map(m => m.default) + .filter(isBackstageFeature) ?? [] ); } -function isBackstagePlugin(obj: unknown): obj is BackstagePlugin { +function isBackstageFeature( + obj: unknown, +): obj is BackstagePlugin | ExtensionOverrides { if (obj !== null && typeof obj === 'object' && '$$type' in obj) { - return obj.$$type === '@backstage/BackstagePlugin'; + return ( + obj.$$type === '@backstage/BackstagePlugin' || + obj.$$type === '@backstage/ExtensionOverrides' + ); } return false; } diff --git a/packages/frontend-app-api/src/wiring/parameters.test.ts b/packages/frontend-app-api/src/wiring/parameters.test.ts index 10b0e2fc6f..4ee420f667 100644 --- a/packages/frontend-app-api/src/wiring/parameters.test.ts +++ b/packages/frontend-app-api/src/wiring/parameters.test.ts @@ -15,7 +15,11 @@ */ import { ConfigReader } from '@backstage/config'; -import { createPlugin, Extension } from '@backstage/frontend-plugin-api'; +import { + createExtensionOverrides, + createPlugin, + Extension, +} from '@backstage/frontend-plugin-api'; import { JsonValue } from '@backstage/types'; import { expandShorthandExtensionParameters, @@ -23,10 +27,14 @@ import { readAppExtensionParameters, } from './parameters'; -function makeExt(id: string, status: 'disabled' | 'enabled' = 'enabled') { +function makeExt( + id: string, + status: 'disabled' | 'enabled' = 'enabled', + attachId: string = 'root', +) { return { id, - at: 'root', + attachTo: { id: attachId, input: 'default' }, disabled: status === 'disabled', } as Extension<unknown>; } @@ -35,7 +43,7 @@ describe('mergeExtensionParameters', () => { it('should filter out disabled extension instances', () => { expect( mergeExtensionParameters({ - sources: [], + features: [], builtinExtensions: [makeExt('a', 'disabled')], parameters: [], }), @@ -47,13 +55,13 @@ describe('mergeExtensionParameters', () => { const b = makeExt('b'); expect( mergeExtensionParameters({ - sources: [], + features: [], builtinExtensions: [a, b], parameters: [], }), ).toEqual([ - { extension: a, at: 'root' }, - { extension: b, at: 'root' }, + { extension: a, attachTo: { id: 'root', input: 'default' } }, + { extension: b, attachTo: { id: 'root', input: 'default' } }, ]); }); @@ -63,18 +71,22 @@ describe('mergeExtensionParameters', () => { const pluginA = createPlugin({ id: 'test', extensions: [a] }); expect( mergeExtensionParameters({ - sources: [pluginA], + features: [pluginA], builtinExtensions: [b], parameters: [ { id: 'b', - at: 'derp', + attachTo: { id: 'derp', input: 'default' }, }, ], }), ).toEqual([ - { extension: a, at: 'root', source: pluginA }, - { extension: b, at: 'derp' }, + { + extension: a, + attachTo: { id: 'root', input: 'default' }, + source: pluginA, + }, + { extension: b, attachTo: { id: 'derp', input: 'default' } }, ]); }); @@ -84,7 +96,7 @@ describe('mergeExtensionParameters', () => { const plugin = createPlugin({ id: 'test', extensions: [a, b] }); expect( mergeExtensionParameters({ - sources: [plugin], + features: [plugin], builtinExtensions: [], parameters: [ { @@ -102,8 +114,18 @@ describe('mergeExtensionParameters', () => { ], }), ).toEqual([ - { extension: a, at: 'root', source: plugin, config: { foo: { bar: 1 } } }, - { extension: b, at: 'root', source: plugin, config: { foo: { qux: 3 } } }, + { + extension: a, + attachTo: { id: 'root', input: 'default' }, + source: plugin, + config: { foo: { bar: 1 } }, + }, + { + extension: b, + attachTo: { id: 'root', input: 'default' }, + source: plugin, + config: { foo: { qux: 3 } }, + }, ]); }); @@ -112,7 +134,7 @@ describe('mergeExtensionParameters', () => { const b = makeExt('b', 'disabled'); expect( mergeExtensionParameters({ - sources: [createPlugin({ id: 'empty', extensions: [] })], + features: [createPlugin({ id: 'empty', extensions: [] })], builtinExtensions: [a, b], parameters: [ { @@ -126,10 +148,65 @@ describe('mergeExtensionParameters', () => { ], }), ).toEqual([ - { extension: b, at: 'root' }, - { extension: a, at: 'root' }, + { extension: b, attachTo: { id: 'root', input: 'default' } }, + { extension: a, attachTo: { id: 'root', input: 'default' } }, ]); }); + + 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 cOverride = makeExt('c'); + + const result = mergeExtensionParameters({ + features: [ + plugin, + createExtensionOverrides({ + extensions: [aOverride, bOverride, cOverride], + }), + ], + builtinExtensions: [], + parameters: [], + }); + + expect(result.length).toBe(2); + expect(result[0].extension).toBe(aOverride); + expect(result[0].attachTo).toEqual({ id: 'other', input: 'default' }); + expect(result[0].config).toEqual(undefined); + expect(result[0].source).toBe(plugin); + + expect(result[1]).toEqual({ + extension: cOverride, + attachTo: { id: 'root', input: 'default' }, + config: undefined, + source: undefined, + }); + }); + + 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 = mergeExtensionParameters({ + features: [ + createPlugin({ id: 'test', extensions: [a, b, c] }), + createExtensionOverrides({ + extensions: [cOverride, bOverride, aOverride], + }), + ], + builtinExtensions: [], + parameters: ['b', 'c', 'a'].map(id => ({ id, disabled: false })), + }); + + expect(result.map(r => r.extension.id)).toEqual(['b', 'c', 'a']); + }); }); describe('readAppExtensionParameters', () => { @@ -315,14 +392,18 @@ describe('expandShorthandExtensionParameters', () => { expect(() => run({ 'core.router': { id: 'some.id' } }), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router].id, unknown parameter; expected one of 'at', 'disabled', 'config'"`, + `"Invalid extension configuration at app.extensions[1][core.router].id, unknown parameter; expected one of 'attachTo', 'disabled', 'config'"`, ); }); - it('supports object at', () => { - expect(run({ 'core.router': { at: 'other.root/inputs' } })).toEqual({ + it('supports object attachTo', () => { + expect( + run({ + 'core.router': { attachTo: { id: 'other.root', input: 'inputs' } }, + }), + ).toEqual({ id: 'core.router', - at: 'other.root/inputs', + attachTo: { id: 'other.root', input: 'inputs' }, }); expect(() => run({ @@ -331,7 +412,7 @@ describe('expandShorthandExtensionParameters', () => { }, }), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router].id, unknown parameter; expected one of 'at', 'disabled', 'config'"`, + `"Invalid extension configuration at app.extensions[1][core.router].id, unknown parameter; expected one of 'attachTo', 'disabled', 'config'"`, ); }); @@ -369,7 +450,7 @@ describe('expandShorthandExtensionParameters', () => { expect(() => run({ 'core.router': { foo: { settings: true } } }), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid extension configuration at app.extensions[1][core.router].foo, unknown parameter; expected one of 'at', '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/wiring/parameters.ts b/packages/frontend-app-api/src/wiring/parameters.ts index efe0fbf678..911f12f416 100644 --- a/packages/frontend-app-api/src/wiring/parameters.ts +++ b/packages/frontend-app-api/src/wiring/parameters.ts @@ -15,17 +15,23 @@ */ import { Config } from '@backstage/config'; -import { BackstagePlugin, Extension } from '@backstage/frontend-plugin-api'; +import { + BackstagePlugin, + Extension, + ExtensionOverrides, +} from '@backstage/frontend-plugin-api'; +// eslint-disable-next-line @backstage/no-relative-monorepo-imports +import { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides'; import { JsonValue } from '@backstage/types'; export interface ExtensionParameters { id: string; - at?: string; + attachTo?: { id: string; input: string }; disabled?: boolean; config?: unknown; } -const knownExtensionParameters = ['at', 'disabled', 'config']; +const knownExtensionParameters = ['attachTo', 'disabled', 'config']; // Since we'll never merge arrays in config the config reader context // isn't too much of a help. Fall back to manual config reading logic @@ -143,15 +149,33 @@ export function expandShorthandExtensionParameters( throw new Error(errorMsg('value must be a boolean or object', id)); } - const at = value.at; + const attachTo = value.attachTo as { id: string; input: string } | undefined; const disabled = value.disabled; const config = value.config; - if (at !== undefined && typeof at !== 'string') { - throw new Error(errorMsg('must be a string', id, 'at')); - } else if (disabled !== undefined && typeof disabled !== 'boolean') { + if (attachTo !== undefined) { + if ( + attachTo === null || + typeof attachTo !== 'object' || + Array.isArray(attachTo) + ) { + throw new Error(errorMsg('must be an object', id, 'attachTo')); + } + if (typeof attachTo.id !== 'string' || attachTo.id === '') { + throw new Error( + errorMsg('must be a non-empty string', id, 'attachTo.id'), + ); + } + if (typeof attachTo.input !== 'string' || attachTo.input === '') { + throw new Error( + errorMsg('must be a non-empty string', id, 'attachTo.input'), + ); + } + } + if (disabled !== undefined && typeof disabled !== 'boolean') { throw new Error(errorMsg('must be a boolean', id, 'disabled')); - } else if ( + } + if ( config !== undefined && (typeof config !== 'object' || config === null || Array.isArray(config)) ) { @@ -175,7 +199,7 @@ export function expandShorthandExtensionParameters( return { id, - at, + attachTo, disabled, config, }; @@ -184,40 +208,72 @@ export function expandShorthandExtensionParameters( export interface ExtensionInstanceParameters { extension: Extension<unknown>; source?: BackstagePlugin; - at: string; + attachTo: { id: string; input: string }; config?: unknown; } /** @internal */ export function mergeExtensionParameters(options: { - sources: BackstagePlugin[]; + features: (BackstagePlugin | ExtensionOverrides)[]; builtinExtensions: Extension<unknown>[]; parameters: Array<ExtensionParameters>; }): ExtensionInstanceParameters[] { - const { sources, builtinExtensions, parameters } = options; + const { builtinExtensions, parameters } = options; - const pluginExtensions = sources.flatMap(source => { + const plugins = options.features.filter( + (f): f is BackstagePlugin => f.$$type === '@backstage/BackstagePlugin', + ); + const overrides = options.features.filter( + (f): f is ExtensionOverrides => + f.$$type === '@backstage/ExtensionOverrides', + ); + + const pluginExtensions = plugins.flatMap(source => { return source.extensions.map(extension => ({ ...extension, source })); }); + const overrideExtensions = overrides.flatMap( + override => toInternalExtensionOverrides(override).extensions, + ); - // Prevent root override - if (pluginExtensions.some(({ id }) => id === 'root')) { - const rootPluginIds = pluginExtensions - .filter(({ id }) => id === 'root') + // Prevent core override + if (pluginExtensions.some(({ id }) => id === 'core')) { + const pluginIds = pluginExtensions + .filter(({ id }) => id === 'core') .map(({ source }) => source.id); throw new Error( - `The following plugin(s) are overriding the 'root' extension which is forbidden: ${rootPluginIds.join( + `The following plugin(s) are overriding the 'core' extension which is forbidden: ${pluginIds.join( ',', )}`, ); } - const overrides = [ + if (overrideExtensions.some(({ id }) => id === 'root')) { + throw new Error( + `An extension override is overriding the 'root' extension which is forbidden`, + ); + } + const overrideExtensionIds = overrideExtensions.map(({ id }) => id); + if (overrideExtensionIds.length !== new Set(overrideExtensionIds).size) { + const counts = new Map<string, number>(); + for (const id of overrideExtensionIds) { + counts.set(id, (counts.get(id) ?? 0) + 1); + } + const duplicated = Array.from(counts.entries()) + .filter(([, count]) => count > 1) + .map(([id]) => id); + throw new Error( + `The following extensions had duplicate overrides: ${duplicated.join( + ', ', + )}`, + ); + } + + const configuredExtensions = [ ...pluginExtensions.map(({ source, ...extension }) => ({ extension, params: { source, - at: extension.at, + attachTo: extension.attachTo, disabled: extension.disabled, config: undefined as unknown, }, @@ -226,15 +282,40 @@ export function mergeExtensionParameters(options: { extension, params: { source: undefined, - at: extension.at, + attachTo: extension.attachTo, disabled: extension.disabled, config: undefined as unknown, }, })), ]; + // Install all extension overrides + for (const extension of overrideExtensions) { + // Check if our override is overriding an extension that already exists + const index = configuredExtensions.findIndex( + e => e.extension.id === extension.id, + ); + if (index !== -1) { + // Only implementation, attachment point and default disabled status are overridden, the source is kept + configuredExtensions[index].extension = extension; + configuredExtensions[index].params.attachTo = extension.attachTo; + configuredExtensions[index].params.disabled = extension.disabled; + } else { + // Add the extension as a new one when not overriding an existing one + configuredExtensions.push({ + extension, + params: { + source: undefined, + attachTo: extension.attachTo, + disabled: extension.disabled, + config: undefined, + }, + }); + } + } + const duplicatedExtensionIds = new Set<string>(); - const duplicatedExtensionData = overrides.reduce< + const duplicatedExtensionData = configuredExtensions.reduce< Record<string, Record<string, number>> >((data, { extension, params }) => { const extensionId = extension.id; @@ -271,20 +352,20 @@ export function mergeExtensionParameters(options: { for (const overrideParam of parameters) { const extensionId = overrideParam.id; - // Prevent root parametrization - if (extensionId === 'root') { + // Prevent core parametrization + if (extensionId === 'core') { throw new Error( - "A 'root' extension configuration was detected, but the root extension is not configurable", + "A 'core' extension configuration was detected, but the core extension is not configurable", ); } - const existingIndex = overrides.findIndex( + const existingIndex = configuredExtensions.findIndex( e => e.extension.id === extensionId, ); if (existingIndex !== -1) { - const existing = overrides[existingIndex]; - if (overrideParam.at) { - existing.params.at = overrideParam.at; + const existing = configuredExtensions[existingIndex]; + if (overrideParam.attachTo) { + existing.params.attachTo = overrideParam.attachTo; } if (overrideParam.config) { // TODO: merge config? @@ -296,8 +377,8 @@ export function mergeExtensionParameters(options: { existing.params.disabled = Boolean(overrideParam.disabled); if (!existing.params.disabled) { // bump - overrides.splice(existingIndex, 1); - overrides.push(existing); + configuredExtensions.splice(existingIndex, 1); + configuredExtensions.push(existing); } } } else { @@ -305,11 +386,11 @@ export function mergeExtensionParameters(options: { } } - return overrides + return configuredExtensions .filter(override => !override.params.disabled) .map(param => ({ extension: param.extension, - at: param.params.at, + attachTo: param.params.attachTo, source: param.params.source, config: param.params.config, })); diff --git a/packages/frontend-plugin-api/CHANGELOG.md b/packages/frontend-plugin-api/CHANGELOG.md index 2295989418..8fa9a49726 100644 --- a/packages/frontend-plugin-api/CHANGELOG.md +++ b/packages/frontend-plugin-api/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/frontend-plugin-api +## 0.2.0 + +### Minor Changes + +- 06432f900c: Extension attachment point is now configured via `attachTo: { id, input }` instead of `at: 'id/input'`. +- 4461d87d5a: Removed support for the new `useRouteRef`. + +### Patch Changes + +- d3a37f55c0: Add support for `SidebarGroup` on the sidebar item extension. +- 2ecd33618a: Plugins can now be assigned `routes` and `externalRoutes` when created. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- c1e9ca6500: Added `createExtensionOverrides` which can be used to install a collection of extensions in an app that will replace any existing ones. +- 52366db5b3: Added `createThemeExtension` and `coreExtensionData.theme`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/types@1.1.1 + +## 0.2.0-next.2 + +### Minor Changes + +- 06432f900c: Extension attachment point is now configured via `attachTo: { id, input }` instead of `at: 'id/input'`. +- 4461d87d5a: Removed support for the new `useRouteRef`. + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/types@1.1.1 + ## 0.1.1-next.1 ### Patch Changes diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index e28d7d5993..3ed5965c99 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -13,7 +13,6 @@ import { JsonObject } from '@backstage/types'; import { JSX as JSX_2 } from 'react'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; -import { RouteRef } from '@backstage/core-plugin-api'; import { z } from 'zod'; import { ZodSchema } from 'zod'; import { ZodTypeDef } from 'zod'; @@ -40,13 +39,37 @@ export type AnyExtensionInputMap = { }; // @public (undocumented) -export interface BackstagePlugin { +export type AnyExternalRoutes = { + [name in string]: ExternalRouteRef; +}; + +// @public +export type AnyRouteRefParams = + | { + [param in string]: string; + } + | undefined; + +// @public (undocumented) +export type AnyRoutes = { + [name in string]: RouteRef; +}; + +// @public (undocumented) +export interface BackstagePlugin< + Routes extends AnyRoutes = AnyRoutes, + ExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, +> { // (undocumented) $$type: '@backstage/BackstagePlugin'; // (undocumented) extensions: Extension<unknown>[]; // (undocumented) + externalRoutes: ExternalRoutes; + // (undocumented) id: string; + // (undocumented) + routes: Routes; } // @public (undocumented) @@ -70,7 +93,7 @@ export const coreExtensionData: { reactElement: ConfigurableExtensionDataRef<JSX_2.Element, {}>; routePath: ConfigurableExtensionDataRef<string, {}>; apiFactory: ConfigurableExtensionDataRef<AnyApiFactory, {}>; - routeRef: ConfigurableExtensionDataRef<RouteRef, {}>; + routeRef: ConfigurableExtensionDataRef<RouteRef<AnyRouteRefParams>, {}>; navTarget: ConfigurableExtensionDataRef<NavTarget, {}>; theme: ConfigurableExtensionDataRef<AppTheme, {}>; }; @@ -136,7 +159,10 @@ export interface CreateExtensionOptions< TConfig, > { // (undocumented) - at: string; + attachTo: { + id: string; + input: string; + }; // (undocumented) configSchema?: PortableSchema<TConfig>; // (undocumented) @@ -156,10 +182,40 @@ export interface CreateExtensionOptions< output: TOutput; } +// @public (undocumented) +export function createExtensionOverrides( + options: ExtensionOverridesOptions, +): ExtensionOverrides; + +// @public +export function createExternalRouteRef< + TParams extends + | { + [param in TParamKeys]: string; + } + | undefined = undefined, + TOptional extends boolean = false, + TParamKeys extends string = string, +>(options?: { + readonly params?: string extends TParamKeys + ? (keyof TParams)[] + : TParamKeys[]; + optional?: TOptional; +}): ExternalRouteRef< + keyof TParams extends never + ? undefined + : string extends TParamKeys + ? TParams + : { + [param in TParamKeys]: string; + }, + TOptional +>; + // @public export function createNavItemExtension(options: { id: string; - routeRef: RouteRef; + routeRef: RouteRef<undefined>; title: string; icon: IconComponent; }): Extension<{ @@ -182,7 +238,10 @@ export function createPageExtension< } ) & { id: string; - at?: string; + attachTo?: { + id: string; + input: string; + }; disabled?: boolean; inputs?: TInputs; routeRef?: RouteRef; @@ -194,13 +253,47 @@ export function createPageExtension< ): Extension<TConfig>; // @public (undocumented) -export function createPlugin(options: PluginOptions): BackstagePlugin; +export function createPlugin< + Routes extends AnyRoutes = {}, + ExternalRoutes extends AnyExternalRoutes = {}, +>( + options: PluginOptions<Routes, ExternalRoutes>, +): BackstagePlugin<Routes, ExternalRoutes>; + +// @public +export function createRouteRef< + TParams extends + | { + [param in TParamKeys]: string; + } + | undefined = undefined, + TParamKeys extends string = string, +>(config?: { + readonly params: string extends TParamKeys ? (keyof TParams)[] : TParamKeys[]; +}): RouteRef< + keyof TParams extends never + ? undefined + : string extends TParamKeys + ? TParams + : { + [param in TParamKeys]: string; + } +>; // @public (undocumented) export function createSchemaFromZod<TOutput, TInput>( schemaCreator: (zImpl: typeof z) => ZodSchema<TOutput, ZodTypeDef, TInput>, ): PortableSchema<TOutput>; +// @public +export function createSubRouteRef< + Path extends string, + ParentParams extends AnyRouteRefParams = never, +>(config: { + path: Path; + parent: RouteRef<ParentParams>; +}): MakeSubRouteRef<PathParams<Path>, ParentParams>; + // @public (undocumented) export function createThemeExtension(theme: AppTheme): Extension<never>; @@ -209,7 +302,10 @@ export interface Extension<TConfig> { // (undocumented) $$type: '@backstage/Extension'; // (undocumented) - at: string; + attachTo: { + id: string; + input: string; + }; // (undocumented) configSchema?: PortableSchema<TConfig>; // (undocumented) @@ -304,19 +400,51 @@ export type ExtensionInputValues< >; }; +// @public (undocumented) +export interface ExtensionOverrides { + // (undocumented) + $$type: '@backstage/ExtensionOverrides'; +} + +// @public (undocumented) +export interface ExtensionOverridesOptions { + // (undocumented) + extensions: Extension<unknown>[]; +} + +// @public +export interface ExternalRouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, + TOptional extends boolean = boolean, +> { + // (undocumented) + readonly $$type: '@backstage/ExternalRouteRef'; + // (undocumented) + readonly optional: TOptional; + // (undocumented) + readonly T: TParams; +} + // @public (undocumented) export type NavTarget = { title: string; icon: IconComponent; - routeRef: RouteRef<{}>; + routeRef: RouteRef<undefined>; }; // @public (undocumented) -export interface PluginOptions { +export interface PluginOptions< + Routes extends AnyRoutes, + ExternalRoutes extends AnyExternalRoutes, +> { // (undocumented) extensions?: Extension<unknown>[]; // (undocumented) + externalRoutes?: ExternalRoutes; + // (undocumented) id: string; + // (undocumented) + routes?: Routes; } // @public (undocumented) @@ -325,6 +453,50 @@ export type PortableSchema<TOutput> = { schema: JsonObject; }; -// @public (undocumented) -export function useRouteRef(routeRef: RouteRef<any>): () => string; +// @public +export type RouteFunc<TParams extends AnyRouteRefParams> = ( + ...[params]: TParams extends undefined + ? readonly [] + : readonly [params: TParams] +) => string; + +// @public +export interface RouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, +> { + // (undocumented) + readonly $$type: '@backstage/RouteRef'; + // (undocumented) + readonly T: TParams; +} + +// @public +export interface SubRouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, +> { + // (undocumented) + readonly $$type: '@backstage/SubRouteRef'; + // (undocumented) + readonly path: string; + // (undocumented) + readonly T: TParams; +} + +// @public +export function useRouteRef< + TOptional extends boolean, + TParams extends AnyRouteRefParams, +>( + routeRef: ExternalRouteRef<TParams, TOptional>, +): TParams extends true ? RouteFunc<TParams> | undefined : RouteFunc<TParams>; + +// @public +export function useRouteRef<TParams extends AnyRouteRefParams>( + routeRef: RouteRef<TParams> | SubRouteRef<TParams>, +): RouteFunc<TParams>; + +// @public +export function useRouteRefParams<Params extends AnyRouteRefParams>( + _routeRef: RouteRef<Params> | SubRouteRef<Params>, +): Params; ``` diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index 7785b03b7d..baf8cb4575 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.1.1-next.1", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -26,19 +26,21 @@ "@backstage/cli": "workspace:^", "@backstage/frontend-app-api": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3" + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0", + "history": "^5.3.0" }, "files": [ "dist" ], "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "dependencies": { "@backstage/core-plugin-api": "workspace:^", "@backstage/types": "workspace:^", + "@backstage/version-bridge": "workspace:^", "@types/react": "^16.13.1 || ^17.0.0", "lodash": "^4.17.21", "zod": "^3.21.4", diff --git a/packages/frontend-plugin-api/src/extensions/createApiExtension.test.ts b/packages/frontend-plugin-api/src/extensions/createApiExtension.test.ts index 7426edb766..e90c0b6b85 100644 --- a/packages/frontend-plugin-api/src/extensions/createApiExtension.test.ts +++ b/packages/frontend-plugin-api/src/extensions/createApiExtension.test.ts @@ -33,7 +33,7 @@ describe('createApiExtension', () => { expect(extension).toEqual({ $$type: '@backstage/Extension', id: 'apis.test', - at: 'core/apis', + attachTo: { id: 'core', input: 'apis' }, disabled: false, configSchema: undefined, inputs: {}, @@ -67,7 +67,7 @@ describe('createApiExtension', () => { expect(extension).toEqual({ $$type: '@backstage/Extension', id: 'apis.test', - at: 'core/apis', + attachTo: { id: 'core', input: 'apis' }, disabled: false, configSchema: undefined, inputs: {}, diff --git a/packages/frontend-plugin-api/src/extensions/createApiExtension.ts b/packages/frontend-plugin-api/src/extensions/createApiExtension.ts index a142a5af61..f728261072 100644 --- a/packages/frontend-plugin-api/src/extensions/createApiExtension.ts +++ b/packages/frontend-plugin-api/src/extensions/createApiExtension.ts @@ -21,7 +21,8 @@ import { createExtension, coreExtensionData, } from '../wiring'; -import { AnyExtensionInputMap, Expand } from '../wiring/createExtension'; +import { AnyExtensionInputMap } from '../wiring/createExtension'; +import { Expand } from '../types'; /** @public */ export function createApiExtension< @@ -51,7 +52,7 @@ export function createApiExtension< return createExtension({ id: `apis.${apiRef.id}`, - at: 'core/apis', + attachTo: { id: 'core', input: 'apis' }, inputs: extensionInputs, configSchema, output: { diff --git a/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx b/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx index 8c55531866..ee38dda016 100644 --- a/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx +++ b/packages/frontend-plugin-api/src/extensions/createNavItemExtension.tsx @@ -14,9 +14,10 @@ * limitations under the License. */ -import { IconComponent, RouteRef } from '@backstage/core-plugin-api'; +import { IconComponent } from '@backstage/core-plugin-api'; import { createSchemaFromZod } from '../schema/createSchemaFromZod'; import { coreExtensionData, createExtension } from '../wiring'; +import { RouteRef } from '../routing'; /** * Helper for creating extensions for a nav item. @@ -24,14 +25,14 @@ import { coreExtensionData, createExtension } from '../wiring'; */ export function createNavItemExtension(options: { id: string; - routeRef: RouteRef; + routeRef: RouteRef<undefined>; title: string; icon: IconComponent; }) { const { id, routeRef, title, icon } = options; return createExtension({ id, - at: 'core.nav/items', + 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/createPageExtension.test.tsx b/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx index 7de6ee3253..125bf3495d 100644 --- a/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx +++ b/packages/frontend-plugin-api/src/extensions/createPageExtension.test.tsx @@ -35,7 +35,7 @@ describe('createPageExtension', () => { ).toEqual({ $$type: '@backstage/Extension', id: 'test', - at: 'core.routes/routes', + attachTo: { id: 'core.routes', input: 'routes' }, configSchema: expect.anything(), disabled: false, inputs: {}, @@ -50,7 +50,7 @@ describe('createPageExtension', () => { expect( createPageExtension({ id: 'test', - at: 'other/place', + attachTo: { id: 'other', input: 'place' }, disabled: true, configSchema, inputs: { @@ -63,7 +63,7 @@ describe('createPageExtension', () => { ).toEqual({ $$type: '@backstage/Extension', id: 'test', - at: 'other/place', + attachTo: { id: 'other', input: 'place' }, configSchema: expect.anything(), disabled: true, inputs: { @@ -88,7 +88,7 @@ describe('createPageExtension', () => { ).toEqual({ $$type: '@backstage/Extension', id: 'test', - at: 'core.routes/routes', + attachTo: { id: 'core.routes', input: 'routes' }, configSchema: expect.anything(), disabled: false, inputs: {}, diff --git a/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx b/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx index 5460fb518d..217fb33ce5 100644 --- a/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx +++ b/packages/frontend-plugin-api/src/extensions/createPageExtension.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ -import { RouteRef } from '@backstage/core-plugin-api'; import React from 'react'; import { ExtensionBoundary } from '../components'; import { createSchemaFromZod, PortableSchema } from '../schema'; @@ -24,7 +23,9 @@ import { Extension, ExtensionInputValues, } from '../wiring'; -import { AnyExtensionInputMap, Expand } from '../wiring/createExtension'; +import { AnyExtensionInputMap } from '../wiring/createExtension'; +import { Expand } from '../types'; +import { RouteRef } from '../routing'; /** * Helper for creating extensions for a routable React page component. @@ -44,7 +45,7 @@ export function createPageExtension< } ) & { id: string; - at?: string; + attachTo?: { id: string; input: string }; disabled?: boolean; inputs?: TInputs; routeRef?: RouteRef; @@ -63,7 +64,7 @@ export function createPageExtension< return createExtension({ id: options.id, - at: options.at ?? 'core.routes/routes', + attachTo: options.attachTo ?? { id: 'core.routes', input: 'routes' }, disabled: options.disabled, output: { element: coreExtensionData.reactElement, diff --git a/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts b/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts index 5c13dd199e..38763688a4 100644 --- a/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts +++ b/packages/frontend-plugin-api/src/extensions/createThemeExtension.ts @@ -21,7 +21,7 @@ import { AppTheme } from '@backstage/core-plugin-api'; export function createThemeExtension(theme: AppTheme) { return createExtension({ id: `themes.${theme.id}`, - at: 'core/themes', + attachTo: { id: 'core', input: 'themes' }, output: { theme: coreExtensionData.theme, }, diff --git a/packages/frontend-plugin-api/src/index.ts b/packages/frontend-plugin-api/src/index.ts index 4e1a383899..73abf28ce4 100644 --- a/packages/frontend-plugin-api/src/index.ts +++ b/packages/frontend-plugin-api/src/index.ts @@ -22,6 +22,6 @@ export * from './components'; export * from './extensions'; +export * from './routing'; export * from './schema'; export * from './wiring'; -export * from './routing'; diff --git a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts new file mode 100644 index 0000000000..727dc1f53e --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.test.ts @@ -0,0 +1,114 @@ +/* + * 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 { + ExternalRouteRef, + createExternalRouteRef, + toInternalExternalRouteRef, +} from './ExternalRouteRef'; +import { AnyRouteRefParams } from './types'; + +describe('ExternalRouteRef', () => { + it('should be created', () => { + const routeRef: ExternalRouteRef<undefined> = createExternalRouteRef(); + const internal = toInternalExternalRouteRef(routeRef); + expect(internal.getParams()).toEqual([]); + expect(internal.optional).toBe(false); + + expect(String(internal)).toMatch( + /^ExternalRouteRef\{created at '.*ExternalRouteRef\.test\.ts.*'\}$/, + ); + internal.setId('some-id'); + expect(String(internal)).toBe('ExternalRouteRef{some-id}'); + }); + + it('should be created as optional', () => { + const routeRef: ExternalRouteRef<undefined, true> = createExternalRouteRef({ + params: [], + optional: true, + }); + const internal = toInternalExternalRouteRef(routeRef); + expect(internal.getParams()).toEqual([]); + expect(internal.optional).toEqual(true); + }); + + it('should be created with params', () => { + const routeRef: ExternalRouteRef<{ + x: string; + y: string; + }> = createExternalRouteRef({ params: ['x', 'y'] }); + const internal = toInternalExternalRouteRef(routeRef); + expect(internal.getParams()).toEqual(['x', 'y']); + expect(internal.optional).toEqual(false); + }); + + it('should be created as optional with params', () => { + const routeRef: ExternalRouteRef<{ + x: string; + y: string; + }> = createExternalRouteRef({ params: ['x', 'y'], optional: true }); + const internal = toInternalExternalRouteRef(routeRef); + expect(internal.getParams()).toEqual(['x', 'y']); + expect(internal.optional).toEqual(true); + }); + + it('should properly infer and validate parameter types and assignments', () => { + function checkRouteRef< + T extends AnyRouteRefParams, + TOptional extends boolean, + TCheck extends TOptional, + >( + _ref: ExternalRouteRef<T, TOptional>, + _params: T extends undefined ? undefined : T, + _optional: TCheck, + ) {} + + const _1 = createExternalRouteRef({ params: ['notX'] }); + checkRouteRef(_1, { notX: '' }, false); + // @ts-expect-error + checkRouteRef(_1, { x: '' }, false); + + const _2 = createExternalRouteRef({ params: ['x'], optional: true }); + checkRouteRef(_2, { x: '' }, true); + // @ts-expect-error + checkRouteRef(_2, undefined, false); + + const _3 = createExternalRouteRef({ params: ['x', 'y'] }); + checkRouteRef(_3, { x: '', y: '' }, false); + // @ts-expect-error + checkRouteRef(_3, { x: '' }, false); + // @ts-expect-error + checkRouteRef(_3, { x: '', y: '', z: '' }, false); + + const _4 = createExternalRouteRef({ params: [] }); + checkRouteRef(_4, undefined, false); + // @ts-expect-error + checkRouteRef<any>(_4, { x: '' }); + + const _5 = createExternalRouteRef(); + checkRouteRef(_5, undefined, false); + // @ts-expect-error + checkRouteRef<any>(_5, { x: '' }); + + const _6 = createExternalRouteRef({ optional: true }); + checkRouteRef(_6, undefined, true); + // @ts-expect-error + checkRouteRef(_6, undefined, false); + + // To avoid complains about missing expectations and unused vars + expect([_1, _2, _3, _4, _5, _6].join('')).toEqual(expect.any(String)); + }); +}); diff --git a/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts new file mode 100644 index 0000000000..c9aabdef27 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/ExternalRouteRef.ts @@ -0,0 +1,131 @@ +/* + * 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 { RouteRefImpl } from './RouteRef'; +import { describeParentCallSite } from './describeParentCallSite'; +import { AnyRouteRefParams } from './types'; + +/** + * Route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system}. + * + * @public + */ +export interface ExternalRouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, + TOptional extends boolean = boolean, +> { + readonly $$type: '@backstage/ExternalRouteRef'; + readonly T: TParams; + readonly optional: TOptional; +} + +/** @internal */ +export interface InternalExternalRouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, + TOptional extends boolean = boolean, +> extends ExternalRouteRef<TParams, TOptional> { + readonly version: 'v1'; + getParams(): string[]; + getDescription(): string; + + setId(id: string): void; +} + +/** @internal */ +export function toInternalExternalRouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, + TOptional extends boolean = boolean, +>( + resource: ExternalRouteRef<TParams, TOptional>, +): InternalExternalRouteRef<TParams, TOptional> { + const r = resource as InternalExternalRouteRef<TParams, TOptional>; + if (r.$$type !== '@backstage/ExternalRouteRef') { + throw new Error(`Invalid ExternalRouteRef, bad type '${r.$$type}'`); + } + + return r; +} + +/** @internal */ +export function isExternalRouteRef(opaque: { + $$type: string; +}): opaque is ExternalRouteRef { + return opaque.$$type === '@backstage/ExternalRouteRef'; +} + +/** @internal */ +class ExternalRouteRefImpl + extends RouteRefImpl + implements InternalExternalRouteRef +{ + readonly $$type = '@backstage/ExternalRouteRef' as any; + + constructor( + readonly optional: boolean, + readonly params: string[] = [], + creationSite: string, + ) { + super(params, creationSite); + } +} + +/** + * Creates a route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system}. + * + * @param options - Description of the route reference to be created. + * @public + */ +export function createExternalRouteRef< + TParams extends { [param in TParamKeys]: string } | undefined = undefined, + TOptional extends boolean = false, + TParamKeys extends string = string, +>(options?: { + /** + * The parameters that will be provided to the external route reference. + */ + readonly params?: string extends TParamKeys + ? (keyof TParams)[] + : TParamKeys[]; + + /** + * Whether or not this route is optional, defaults to false. + * + * Optional external routes are not required to be bound in the app, and + * if they aren't, `useExternalRouteRef` will return `undefined`. + */ + optional?: TOptional; +}): ExternalRouteRef< + keyof TParams extends never + ? undefined + : string extends TParamKeys + ? TParams + : { [param in TParamKeys]: string }, + TOptional +> { + return new ExternalRouteRefImpl( + Boolean(options?.optional), + options?.params as string[] | undefined, + describeParentCallSite(), + ) as ExternalRouteRef<any, any>; +} diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.test.ts b/packages/frontend-plugin-api/src/routing/RouteRef.test.ts new file mode 100644 index 0000000000..de7a3de887 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/RouteRef.test.ts @@ -0,0 +1,93 @@ +/* + * 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 { AnyRouteRefParams } from './types'; +import { RouteRef, createRouteRef, toInternalRouteRef } from './RouteRef'; + +describe('RouteRef', () => { + it('should be created and have a mutable ID', () => { + const routeRef: RouteRef<undefined> = createRouteRef(); + const internal = toInternalRouteRef(routeRef); + expect(internal.T).toBe(undefined); + expect(internal.getParams()).toEqual([]); + expect(internal.getDescription()).toMatch(/RouteRef\.test\.ts/); + + expect(String(internal)).toMatch( + /^RouteRef\{created at .*RouteRef\.test\.ts.*\}$/, + ); + + expect(() => internal.setId('')).toThrow( + 'RouteRef id must be a non-empty string', + ); + + internal.setId('some-id'); + expect(String(internal)).toBe('RouteRef{some-id}'); + + expect(() => internal.setId('some-other-id')).toThrow( + "RouteRef was referenced twice as both 'some-id' and 'some-other-id'", + ); + }); + + it('should be created with params', () => { + const routeRef: RouteRef<{ + x: string; + y: string; + }> = createRouteRef({ + params: ['x', 'y'], + }); + const internal = toInternalRouteRef(routeRef); + expect(internal.getParams()).toEqual(['x', 'y']); + expect(internal.getDescription()).toMatch(/RouteRef\.test\.ts/); + }); + + it('should properly infer and validate parameter types and assignments', () => { + function checkRouteRef<T extends AnyRouteRefParams>( + _ref: RouteRef<T>, + _params: T extends undefined ? undefined : T, + ) {} + + const _1 = createRouteRef({ params: ['x'] }); + checkRouteRef(_1, { x: '' }); + // @ts-expect-error + checkRouteRef(_1, { y: '' }); + // @ts-expect-error + checkRouteRef(_1, undefined); + + const _2 = createRouteRef({ params: ['x', 'y'] }); + checkRouteRef(_2, { x: '', y: '' }); + // @ts-expect-error + checkRouteRef(_2, { x: '' }); + // @ts-expect-error + checkRouteRef(_2, undefined); + // @ts-expect-error + checkRouteRef(_2, { x: '', z: '' }); + // @ts-expect-error + checkRouteRef(_2, { x: '', y: '', z: '' }); + + const _3 = createRouteRef({ params: [] }); + checkRouteRef(_3, undefined); + // @ts-expect-error + checkRouteRef(_3, { x: '' }); + + const _4 = createRouteRef(); + checkRouteRef(_4, undefined); + // @ts-expect-error + checkRouteRef(_4, { x: '' }); + + // To avoid complains about missing expectations and unused vars + expect([_1, _2, _3, _4].join('')).toEqual(expect.any(String)); + }); +}); diff --git a/packages/frontend-plugin-api/src/routing/RouteRef.ts b/packages/frontend-plugin-api/src/routing/RouteRef.ts new file mode 100644 index 0000000000..da562e5273 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/RouteRef.ts @@ -0,0 +1,136 @@ +/* + * 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 { describeParentCallSite } from './describeParentCallSite'; +import { AnyRouteRefParams } from './types'; + +/** + * Absolute route reference. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system}. + * + * @public + */ +export interface RouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, +> { + readonly $$type: '@backstage/RouteRef'; + readonly T: TParams; +} + +/** @internal */ +export interface InternalRouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, +> extends RouteRef<TParams> { + readonly version: 'v1'; + getParams(): string[]; + getDescription(): string; + + setId(id: string): void; +} + +/** @internal */ +export function toInternalRouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, +>(resource: RouteRef<TParams>): InternalRouteRef<TParams> { + const r = resource as InternalRouteRef<TParams>; + if (r.$$type !== '@backstage/RouteRef') { + throw new Error(`Invalid RouteRef, bad type '${r.$$type}'`); + } + + return r; +} + +/** @internal */ +export function isRouteRef(opaque: { $$type: string }): opaque is RouteRef { + return opaque.$$type === '@backstage/RouteRef'; +} + +/** @internal */ +export class RouteRefImpl implements InternalRouteRef { + readonly $$type = '@backstage/RouteRef'; + readonly version = 'v1'; + declare readonly T: never; + + #id?: string; + #params: string[]; + #creationSite: string; + + constructor(readonly params: string[] = [], creationSite: string) { + this.#params = params; + this.#creationSite = creationSite; + } + + getParams(): string[] { + return this.#params; + } + + getDescription(): string { + if (this.#id) { + return this.#id; + } + return `created at '${this.#creationSite}'`; + } + + get #name() { + return this.$$type.slice('@backstage/'.length); + } + + setId(id: string): void { + if (!id) { + throw new Error(`${this.#name} id must be a non-empty string`); + } + if (this.#id) { + throw new Error( + `${this.#name} was referenced twice as both '${this.#id}' and '${id}'`, + ); + } + this.#id = id; + } + + toString(): string { + return `${this.#name}{${this.getDescription()}}`; + } +} + +/** + * Create a {@link RouteRef} from a route descriptor. + * + * @param config - Description of the route reference to be created. + * @public + */ +export function createRouteRef< + // Params is the type that we care about and the one to be embedded in the route ref. + // For example, given the params ['name', 'kind'], Params will be {name: string, kind: string} + TParams extends { [param in TParamKeys]: string } | undefined = undefined, + TParamKeys extends string = string, +>(config?: { + /** A list of parameter names that the path that this route ref is bound to must contain */ + readonly params: string extends TParamKeys ? (keyof TParams)[] : TParamKeys[]; +}): RouteRef< + keyof TParams extends never + ? undefined + : string extends TParamKeys + ? TParams + : { [param in TParamKeys]: string } +> { + return new RouteRefImpl( + config?.params as string[] | undefined, + describeParentCallSite(), + ) as RouteRef<any>; +} diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts new file mode 100644 index 0000000000..b04728c49b --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.test.ts @@ -0,0 +1,139 @@ +/* + * 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 { AnyRouteRefParams } from './types'; +import { + SubRouteRef, + createSubRouteRef, + toInternalSubRouteRef, +} from './SubRouteRef'; +import { createRouteRef, toInternalRouteRef } from './RouteRef'; + +const parent = createRouteRef(); +const parentX = createRouteRef({ params: ['x'] }); + +describe('SubRouteRef', () => { + it('should be created', () => { + const internalParent = toInternalRouteRef(createRouteRef()); + const routeRef: SubRouteRef = createSubRouteRef({ + parent: internalParent, + path: '/foo', + }); + const internal = toInternalSubRouteRef(routeRef); + expect(internal.path).toBe('/foo'); + expect(internal.T).toBe(undefined); + expect(internal.getParent()).toBe(internalParent); + expect(internal.getParams()).toEqual([]); + expect(String(internal)).toMatch( + /SubRouteRef\{at \/foo with parent created at '.*SubRouteRef\.test\.ts.*'\}/, + ); + internalParent.setId('some-id'); + expect(String(internal)).toBe('SubRouteRef{at /foo with parent some-id}'); + }); + + it('should be created with params', () => { + const routeRef: SubRouteRef<{ bar: string }> = createSubRouteRef({ + parent, + path: '/foo/:bar', + }); + const internal = toInternalSubRouteRef(routeRef); + expect(internal.path).toBe('/foo/:bar'); + expect(internal.getParent()).toBe(parent); + expect(internal.getParams()).toEqual(['bar']); + }); + + it('should be created with merged params', () => { + const routeRef: SubRouteRef<{ + x: string; + y: string; + z: string; + }> = createSubRouteRef({ + parent: parentX, + path: '/foo/:y/:z', + }); + const internal = toInternalSubRouteRef(routeRef); + expect(internal.path).toBe('/foo/:y/:z'); + expect(internal.getParent()).toBe(parentX); + expect(internal.getParams()).toEqual(['x', 'y', 'z']); + }); + + it('should be created with params from parent', () => { + const routeRef: SubRouteRef<{ x: string }> = createSubRouteRef({ + parent: parentX, + path: '/foo/bar', + }); + const internal = toInternalSubRouteRef(routeRef); + expect(internal.path).toBe('/foo/bar'); + expect(internal.getParent()).toBe(parentX); + expect(internal.getParams()).toEqual(['x']); + }); + + it.each([ + ['foo', "SubRouteRef path must start with '/', got 'foo'"], + [':foo', "SubRouteRef path must start with '/', got ':foo'"], + ['', "SubRouteRef path must start with '/', got ''"], + ['/', "SubRouteRef path must not end with '/', got '/'"], + ['/foo/', "SubRouteRef path must not end with '/', got '/foo/'"], + ['/foo/:x', 'SubRouteRef may not have params that overlap with its parent'], + ['/:/foo', "SubRouteRef path has invalid param, got ''"], + ['/:inva:lid/foo', "SubRouteRef path has invalid param, got 'inva:lid'"], + ['/:inva=lid/foo', "SubRouteRef path has invalid param, got 'inva=lid'"], + ])('should throw if path is invalid, %s', (path, message) => { + expect(() => createSubRouteRef({ path, parent: parentX })).toThrow(message); + }); + + it('should properly infer and parse path parameters', () => { + function checkSubRouteRef<T extends AnyRouteRefParams>( + _ref: SubRouteRef<T>, + _params: T extends undefined ? undefined : T, + ) {} + + const _1 = createSubRouteRef({ parent, path: '/foo/bar' }); + // @ts-expect-error + checkSubRouteRef(_1, { x: '' }); + checkSubRouteRef(_1, undefined); + + const _2 = createSubRouteRef({ parent, path: '/foo/:x/:y' }); + // @ts-expect-error + checkSubRouteRef(_2, undefined); + // @ts-expect-error + checkSubRouteRef(_2, { x: '', z: '' }); + // @ts-expect-error + checkSubRouteRef(_2, { y: '' }); + // @ts-expect-error + checkSubRouteRef(_2, { x: '', y: '', z: '' }); + checkSubRouteRef(_2, { x: '', y: '' }); + + const _3 = createSubRouteRef({ parent: parentX, path: '/foo' }); + // @ts-expect-error + checkSubRouteRef(_3, undefined); + // @ts-expect-error + checkSubRouteRef(_3, { y: '' }); + checkSubRouteRef(_3, { x: '' }); + + const _4 = createSubRouteRef({ parent: parentX, path: '/foo/:y' }); + // @ts-expect-error + checkSubRouteRef(_4, undefined); + // @ts-expect-error + checkSubRouteRef(_4, { x: '', z: '' }); + // @ts-expect-error + checkSubRouteRef(_4, { y: '' }); + checkSubRouteRef(_4, { x: '', y: '' }); + + // To avoid complains about missing expectations and unused vars + expect([_1, _2, _3, _4].join('')).toEqual(expect.any(String)); + }); +}); diff --git a/packages/frontend-plugin-api/src/routing/SubRouteRef.ts b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts new file mode 100644 index 0000000000..74996ab4e7 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/SubRouteRef.ts @@ -0,0 +1,208 @@ +/* + * 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 { RouteRef, toInternalRouteRef } from './RouteRef'; +import { AnyRouteRefParams } from './types'; + +// Should match the pattern in react-router +const PARAM_PATTERN = /^\w+$/; + +/** + * Descriptor of a route relative to an absolute {@link RouteRef}. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system}. + * + * @public + */ +export interface SubRouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, +> { + readonly $$type: '@backstage/SubRouteRef'; + + readonly T: TParams; + + readonly path: string; +} + +/** @internal */ +export interface InternalSubRouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, +> extends SubRouteRef<TParams> { + readonly version: 'v1'; + + getParams(): string[]; + getParent(): RouteRef; + getDescription(): string; +} + +/** @internal */ +export function toInternalSubRouteRef< + TParams extends AnyRouteRefParams = AnyRouteRefParams, +>(resource: SubRouteRef<TParams>): InternalSubRouteRef<TParams> { + const r = resource as InternalSubRouteRef<TParams>; + if (r.$$type !== '@backstage/SubRouteRef') { + throw new Error(`Invalid SubRouteRef, bad type '${r.$$type}'`); + } + + return r; +} + +/** @internal */ +export function isSubRouteRef(opaque: { + $$type: string; +}): opaque is SubRouteRef { + return opaque.$$type === '@backstage/SubRouteRef'; +} + +/** @internal */ +export class SubRouteRefImpl<TParams extends AnyRouteRefParams> + implements SubRouteRef<TParams> +{ + readonly $$type = '@backstage/SubRouteRef'; + readonly version = 'v1'; + declare readonly T: never; + + #params: string[]; + #parent: RouteRef; + + constructor(readonly path: string, params: string[], parent: RouteRef) { + this.#params = params; + this.#parent = parent; + } + + getParams(): string[] { + return this.#params; + } + + getParent(): RouteRef { + return this.#parent; + } + + getDescription(): string { + const parent = toInternalRouteRef(this.#parent); + return `at ${this.path} with parent ${parent.getDescription()}`; + } + + toString(): string { + return `SubRouteRef{${this.getDescription()}}`; + } +} + +/** + * Used in {@link PathParams} type declaration. + * @ignore + */ +type ParamPart<S extends string> = S extends `:${infer Param}` ? Param : never; + +/** + * Used in {@link PathParams} type declaration. + * @ignore + */ +type ParamNames<S extends string> = S extends `${infer Part}/${infer Rest}` + ? ParamPart<Part> | ParamNames<Rest> + : ParamPart<S>; +/** + * This utility type helps us infer a Param object type from a string path + * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }` + * @ignore + */ +type PathParams<S extends string> = { [name in ParamNames<S>]: string }; + +/** + * Merges a param object type with an optional params type into a params object. + * @ignore + */ +type MergeParams< + P1 extends { [param in string]: string }, + P2 extends AnyRouteRefParams, +> = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2); + +/** + * Convert empty params to undefined. + * @ignore + */ +type TrimEmptyParams<Params extends { [param in string]: string }> = + keyof Params extends never ? undefined : Params; + +/** + * Creates a SubRouteRef type given the desired parameters and parent route parameters. + * The parameters types are merged together while ensuring that there is no overlap between the two. + * + * @ignore + */ +type MakeSubRouteRef< + Params extends { [param in string]: string }, + ParentParams extends AnyRouteRefParams, +> = keyof Params & keyof ParentParams extends never + ? SubRouteRef<TrimEmptyParams<MergeParams<Params, ParentParams>>> + : never; + +/** + * Create a {@link SubRouteRef} from a route descriptor. + * + * @param config - Description of the route reference to be created. + * @public + */ +export function createSubRouteRef< + Path extends string, + ParentParams extends AnyRouteRefParams = never, +>(config: { + path: Path; + parent: RouteRef<ParentParams>; +}): MakeSubRouteRef<PathParams<Path>, ParentParams> { + const { path, parent } = config; + type Params = PathParams<Path>; + + const internalParent = toInternalRouteRef(parent); + const parentParams = internalParent.getParams(); + + // Collect runtime parameters from the path, e.g. ['bar', 'baz'] from '/foo/:bar/:baz' + const pathParams = path + .split('/') + .filter(p => p.startsWith(':')) + .map(p => p.substring(1)); + const params = [...parentParams, ...pathParams]; + + if (parentParams.some(p => pathParams.includes(p as string))) { + throw new Error( + 'SubRouteRef may not have params that overlap with its parent', + ); + } + if (!path.startsWith('/')) { + throw new Error(`SubRouteRef path must start with '/', got '${path}'`); + } + if (path.endsWith('/')) { + throw new Error(`SubRouteRef path must not end with '/', got '${path}'`); + } + for (const param of pathParams) { + if (!PARAM_PATTERN.test(param)) { + throw new Error(`SubRouteRef path has invalid param, got '${param}'`); + } + } + + // We ensure that the type of the return type is sane here + const subRouteRef = new SubRouteRefImpl( + path, + params as string[], + parent, + ) as SubRouteRef<TrimEmptyParams<MergeParams<Params, ParentParams>>>; + + // But skip type checking of the return value itself, because the conditional + // type checking of the parent parameter overlap is tricky to express. + return subRouteRef as any; +} diff --git a/packages/frontend-plugin-api/src/routing/describeParentCallSite.test.ts b/packages/frontend-plugin-api/src/routing/describeParentCallSite.test.ts new file mode 100644 index 0000000000..03a94dcb45 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/describeParentCallSite.test.ts @@ -0,0 +1,84 @@ +/* + * 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 { describeParentCallSite } from './describeParentCallSite'; + +class ChromeError { + name = 'Error'; + message = 'eHgtF5hmbrXyiEvo'; + get stack() { + return `Error: eHgtF5hmbrXyiEvo + at describeParentCallSite (describeParentCallSite.js:1:11) + at parent (parent.js:2:22) + at caller (parent-caller.js:3:33) + at other.js:3:33`; + } +} + +class SafariError { + name = 'Error'; + message = 'eHgtF5hmbrXyiEvo'; + get stack() { + return `describeParentCallSite@describeParentCallSite.js:1:11 +parent@parent.js:2:22 +caller@parent-caller.js:3:33 +code@other.js:3:33`; + } +} + +class FirefoxError { + name = 'Error'; + message = 'eHgtF5hmbrXyiEvo'; + get stack() { + return `describeParentCallSite@describeParentCallSite.js:1:11 +parent@parent.js:2:22 +caller@parent-caller.js:3:33 +@other.js:3:33 +`; + } +} + +describe('describeParentCallSite', () => { + it('should work in Chrome', () => { + function myFactory() { + return describeParentCallSite(ChromeError); + } + function myCaller() { + return myFactory(); + } + expect(myCaller()).toBe('parent-caller.js:3:33'); + }); + + it('should work in Safari', () => { + function myFactory() { + return describeParentCallSite(SafariError); + } + function myCaller() { + return myFactory(); + } + expect(myCaller()).toBe('parent-caller.js:3:33'); + }); + + it('should work in Firefox', () => { + function myFactory() { + return describeParentCallSite(FirefoxError); + } + function myCaller() { + return myFactory(); + } + expect(myCaller()).toBe('parent-caller.js:3:33'); + }); +}); diff --git a/packages/frontend-plugin-api/src/routing/describeParentCallSite.ts b/packages/frontend-plugin-api/src/routing/describeParentCallSite.ts new file mode 100644 index 0000000000..72997e07db --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/describeParentCallSite.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. + */ + +const MESSAGE_MARKER = 'eHgtF5hmbrXyiEvo'; + +/** + * Internal helper that describes the location of the parent caller. + * @internal + */ +export function describeParentCallSite( + ErrorConstructor: { new (message: string): Error } = Error, +): string { + const { stack } = new ErrorConstructor(MESSAGE_MARKER); + if (!stack) { + return '<unknown>'; + } + + // Safari and Firefox don't include the error itself in the stack + const startIndex = stack.includes(MESSAGE_MARKER) + ? stack.indexOf('\n') + 1 + : 0; + const secondEntryStart = + stack.indexOf('\n', stack.indexOf('\n', startIndex) + 1) + 1; + const secondEntryEnd = stack.indexOf('\n', secondEntryStart); + + const line = stack.substring(secondEntryStart, secondEntryEnd).trim(); + if (!line) { + return 'unknown'; + } + + // Below we try to extract the location for different browsers. + // Since RouteRefs are declared at the top-level of modules the caller name isn't interesting. + + // Chrome + if (line.includes('(')) { + return line.substring(line.indexOf('(') + 1, line.indexOf(')')); + } + + // Safari & Firefox + if (line.includes('@')) { + return line.substring(line.indexOf('@') + 1); + } + + // Give up + return line; +} diff --git a/packages/frontend-plugin-api/src/routing/index.ts b/packages/frontend-plugin-api/src/routing/index.ts index 4506538fa0..6c25f725b5 100644 --- a/packages/frontend-plugin-api/src/routing/index.ts +++ b/packages/frontend-plugin-api/src/routing/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Backstage Authors + * 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. @@ -14,4 +14,12 @@ * limitations under the License. */ -export { useRouteRef } from './useRouteRef'; +export type { AnyRouteRefParams } from './types'; +export { createRouteRef, type RouteRef } from './RouteRef'; +export { createSubRouteRef, type SubRouteRef } from './SubRouteRef'; +export { + createExternalRouteRef, + type ExternalRouteRef, +} from './ExternalRouteRef'; +export { useRouteRef, type RouteFunc } from './useRouteRef'; +export { useRouteRefParams } from './useRouteRefParams'; diff --git a/packages/frontend-plugin-api/src/routing/types.ts b/packages/frontend-plugin-api/src/routing/types.ts new file mode 100644 index 0000000000..3bf1323210 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/types.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +/** + * Catch-all type for route params. + * + * @public + */ +export type AnyRouteRefParams = { [param in string]: string } | undefined; diff --git a/packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx b/packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx new file mode 100644 index 0000000000..dcd56f81a6 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/useRouteRef.test.tsx @@ -0,0 +1,157 @@ +/* + * 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 { renderHook } from '@testing-library/react'; +import React from 'react'; +import { MemoryRouter, Router } from 'react-router-dom'; +import { createVersionedContextForTesting } from '@backstage/version-bridge'; +import { useRouteRef } from './useRouteRef'; +import { createRouteRef } from './RouteRef'; +import { createBrowserHistory } from 'history'; + +describe('v1 consumer', () => { + const context = createVersionedContextForTesting('routing-context'); + + afterEach(() => { + context.reset(); + }); + + it('should resolve routes', () => { + const resolve = jest.fn(() => () => '/hello'); + context.set({ 1: { resolve } }); + + const routeRef = createRouteRef(); + + const renderedHook = renderHook(() => useRouteRef(routeRef), { + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + <MemoryRouter initialEntries={['/my-page']} children={children} /> + ), + }); + + const routeFunc = renderedHook.result.current; + expect(routeFunc()).toBe('/hello'); + expect(resolve).toHaveBeenCalledWith( + routeRef, + expect.objectContaining({ + pathname: '/my-page', + }), + ); + }); + + it('re-resolves the routeFunc when the search parameters change', () => { + const resolve = jest.fn(() => () => '/hello'); + context.set({ 1: { resolve } }); + + const routeRef = createRouteRef(); + const history = createBrowserHistory(); + history.push('/my-page'); + + const { rerender } = renderHook(() => useRouteRef(routeRef), { + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + <Router + location={history.location} + navigator={history} + children={children} + /> + ), + }); + + expect(resolve).toHaveBeenCalledTimes(1); + + history.push('/my-new-page'); + rerender(); + + expect(resolve).toHaveBeenCalledTimes(2); + }); + + it('does not re-resolve the routeFunc the location pathname does not change', () => { + const resolve = jest.fn(() => () => '/hello'); + context.set({ 1: { resolve } }); + + const routeRef = createRouteRef(); + const history = createBrowserHistory(); + history.push('/my-page'); + + const { rerender } = renderHook(() => useRouteRef(routeRef), { + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + <Router + location={history.location} + navigator={history} + children={children} + /> + ), + }); + + expect(resolve).toHaveBeenCalledTimes(1); + + history.push('/my-page'); + rerender(); + + expect(resolve).toHaveBeenCalledTimes(1); + }); + + it('does not re-resolve the routeFunc when the search parameter changes', () => { + const resolve = jest.fn(() => () => '/hello'); + context.set({ 1: { resolve } }); + + const routeRef = createRouteRef(); + const history = createBrowserHistory(); + history.push('/my-page'); + + const { rerender } = renderHook(() => useRouteRef(routeRef), { + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + <Router + location={history.location} + navigator={history} + children={children} + /> + ), + }); + + expect(resolve).toHaveBeenCalledTimes(1); + + history.push('/my-page?foo=bar'); + rerender(); + + expect(resolve).toHaveBeenCalledTimes(1); + }); + + it('does not re-resolve the routeFunc when the hash parameter changes', () => { + const resolve = jest.fn(() => () => '/hello'); + context.set({ 1: { resolve } }); + + const routeRef = createRouteRef(); + const history = createBrowserHistory(); + history.push('/my-page'); + + const { rerender } = renderHook(() => useRouteRef(routeRef), { + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + <Router + location={history.location} + navigator={history} + children={children} + /> + ), + }); + + expect(resolve).toHaveBeenCalledTimes(1); + + history.push('/my-page#foo'); + rerender(); + + expect(resolve).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/frontend-plugin-api/src/routing/useRouteRef.ts b/packages/frontend-plugin-api/src/routing/useRouteRef.ts deleted file mode 100644 index ad1c16ea8e..0000000000 --- a/packages/frontend-plugin-api/src/routing/useRouteRef.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 { RouteRef } from '@backstage/core-plugin-api'; -// eslint-disable-next-line @backstage/no-forbidden-package-imports -import { RoutingContext } from '@backstage/frontend-app-api/src/routing/RoutingContext'; -import { useContext, useMemo } from 'react'; -import { useLocation } from 'react-router-dom'; - -/** @public */ -export function useRouteRef(routeRef: RouteRef<any>): () => string { - const { pathname } = useLocation(); - const resolver = useContext(RoutingContext); - - const routeFunc = useMemo( - () => resolver && resolver.resolve(routeRef, { pathname }), - [resolver, routeRef, pathname], - ); - - if (!routeFunc) { - throw new Error(`Failed to resolve routeRef ${routeRef}`); - } - - return routeFunc; -} diff --git a/packages/frontend-plugin-api/src/routing/useRouteRef.tsx b/packages/frontend-plugin-api/src/routing/useRouteRef.tsx new file mode 100644 index 0000000000..dfcb110930 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/useRouteRef.tsx @@ -0,0 +1,134 @@ +/* + * 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 { useMemo } from 'react'; +import { matchRoutes, useLocation } from 'react-router-dom'; +import { useVersionedContext } from '@backstage/version-bridge'; +import { AnyRouteRefParams } from './types'; +import { RouteRef } from './RouteRef'; +import { SubRouteRef } from './SubRouteRef'; +import { ExternalRouteRef } from './ExternalRouteRef'; + +/** + * TS magic for handling route parameters. + * + * @remarks + * + * The extra TS magic here is to require a single params argument if the RouteRef + * had at least one param defined, but require 0 arguments if there are no params defined. + * Without this we'd have to pass in empty object to all parameter-less RouteRefs + * just to make TypeScript happy, or we would have to make the argument optional in + * which case you might forget to pass it in when it is actually required. + * + * @public + */ +export type RouteFunc<TParams extends AnyRouteRefParams> = ( + ...[params]: TParams extends undefined + ? readonly [] + : readonly [params: TParams] +) => string; + +/** + * @internal + */ +export interface RouteResolver { + resolve<TParams extends AnyRouteRefParams>( + anyRouteRef: + | RouteRef<TParams> + | SubRouteRef<TParams> + | ExternalRouteRef<TParams, any>, + sourceLocation: Parameters<typeof matchRoutes>[1], + ): RouteFunc<TParams> | undefined; +} + +/** + * React hook for constructing URLs to routes. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system} + * + * @param routeRef - The ref to route that should be converted to URL. + * @returns A function that will in turn return the concrete URL of the `routeRef`. + * @public + */ +export function useRouteRef< + TOptional extends boolean, + TParams extends AnyRouteRefParams, +>( + routeRef: ExternalRouteRef<TParams, TOptional>, +): TParams extends true ? RouteFunc<TParams> | undefined : RouteFunc<TParams>; + +/** + * React hook for constructing URLs to routes. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system} + * + * @param routeRef - The ref to route that should be converted to URL. + * @returns A function that will in turn return the concrete URL of the `routeRef`. + * @public + */ +export function useRouteRef<TParams extends AnyRouteRefParams>( + routeRef: RouteRef<TParams> | SubRouteRef<TParams>, +): RouteFunc<TParams>; + +/** + * React hook for constructing URLs to routes. + * + * @remarks + * + * See {@link https://backstage.io/docs/plugins/composability#routing-system} + * + * @param routeRef - The ref to route that should be converted to URL. + * @returns A function that will in turn return the concrete URL of the `routeRef`. + * @public + */ +export function useRouteRef<TParams extends AnyRouteRefParams>( + routeRef: + | RouteRef<TParams> + | SubRouteRef<TParams> + | ExternalRouteRef<TParams, any>, +): RouteFunc<TParams> | undefined { + const { pathname } = useLocation(); + const versionedContext = useVersionedContext<{ 1: RouteResolver }>( + 'routing-context', + ); + if (!versionedContext) { + throw new Error('Routing context is not available'); + } + + const resolver = versionedContext.atVersion(1); + const routeFunc = useMemo( + () => resolver && resolver.resolve(routeRef, { pathname }), + [resolver, routeRef, pathname], + ); + + if (!versionedContext) { + throw new Error('useRouteRef used outside of routing context'); + } + if (!resolver) { + throw new Error('RoutingContext v1 not available'); + } + + const isOptional = 'optional' in routeRef && routeRef.optional; + if (!routeFunc && !isOptional) { + throw new Error(`No path for ${routeRef}`); + } + + return routeFunc; +} diff --git a/packages/frontend-plugin-api/src/routing/useRouteRefParams.test.tsx b/packages/frontend-plugin-api/src/routing/useRouteRefParams.test.tsx new file mode 100644 index 0000000000..37432b294e --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/useRouteRefParams.test.tsx @@ -0,0 +1,51 @@ +/* + * 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 { render } from '@testing-library/react'; +import React from 'react'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { useRouteRefParams } from './useRouteRefParams'; +import { createRouteRef } from './RouteRef'; + +describe('useRouteRefParams', () => { + it('should provide types params', () => { + const routeRef = createRouteRef({ + params: ['a', 'b'], + }); + + const Page = () => { + const params: { a: string; b: string } = useRouteRefParams(routeRef); + + return ( + <div> + <span>{params.a}</span> + <span>{params.b}</span> + </div> + ); + }; + + const { getByText } = render( + <MemoryRouter initialEntries={['/foo/bar']}> + <Routes> + <Route path="/:a/:b" element={<Page />} /> + </Routes> + </MemoryRouter>, + ); + + expect(getByText('foo')).toBeInTheDocument(); + expect(getByText('bar')).toBeInTheDocument(); + }); +}); diff --git a/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts b/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts new file mode 100644 index 0000000000..1bbd8ec6b8 --- /dev/null +++ b/packages/frontend-plugin-api/src/routing/useRouteRefParams.ts @@ -0,0 +1,31 @@ +/* + * 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 { useParams } from 'react-router-dom'; +import { AnyRouteRefParams } from './types'; +import { RouteRef } from './RouteRef'; +import { SubRouteRef } from './SubRouteRef'; + +/** + * React hook for retrieving dynamic params from the current URL. + * @param _routeRef - Ref of the current route. + * @public + */ +export function useRouteRefParams<Params extends AnyRouteRefParams>( + _routeRef: RouteRef<Params> | SubRouteRef<Params>, +): Params { + return useParams() as Params; +} diff --git a/packages/frontend-plugin-api/src/types.ts b/packages/frontend-plugin-api/src/types.ts new file mode 100644 index 0000000000..8b6f02a942 --- /dev/null +++ b/packages/frontend-plugin-api/src/types.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. + */ + +// 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> = T extends infer O ? { [K in keyof O]: O[K] } : never; diff --git a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts index 6913501907..023eab57e1 100644 --- a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts +++ b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts @@ -19,15 +19,15 @@ import { AnyApiFactory, AppTheme, IconComponent, - RouteRef, } from '@backstage/core-plugin-api'; import { createExtensionDataRef } from './createExtensionDataRef'; +import { RouteRef } from '../routing'; /** @public */ export type NavTarget = { title: string; icon: IconComponent; - routeRef: RouteRef<{}>; + routeRef: RouteRef<undefined>; }; /** @public */ diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.test.ts b/packages/frontend-plugin-api/src/wiring/createExtension.test.ts index 6f4a21399d..757bcd7e3d 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.test.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.test.ts @@ -26,7 +26,7 @@ describe('createExtension', () => { it('should create an extension with a simple output', () => { const extension = createExtension({ id: 'test', - at: 'root', + attachTo: { id: 'root', input: 'default' }, output: { foo: stringData, }, @@ -56,7 +56,7 @@ describe('createExtension', () => { it('should create an extension with a some optional output', () => { const extension = createExtension({ id: 'test', - at: 'root', + attachTo: { id: 'root', input: 'default' }, output: { foo: stringData, bar: stringData.optional(), @@ -94,7 +94,7 @@ describe('createExtension', () => { it('should create an extension with input', () => { const extension = createExtension({ id: 'test', - at: 'root', + attachTo: { id: 'root', input: 'default' }, inputs: { mixed: createExtensionInput({ required: stringData, diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.ts b/packages/frontend-plugin-api/src/wiring/createExtension.ts index dd365a87d8..fa24a24797 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.ts @@ -15,6 +15,7 @@ */ import { PortableSchema } from '../schema'; +import { Expand } from '../types'; import { ExtensionDataRef } from './createExtensionDataRef'; import { ExtensionInput } from './createExtensionInput'; import { BackstagePlugin } from './createPlugin'; @@ -32,13 +33,6 @@ export type AnyExtensionInputMap = { >; }; -// 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> = T extends infer O ? { [K in keyof O]: O[K] } : never; - /** * Converts an extension data map into the matching concrete data values type. * @public @@ -80,7 +74,7 @@ export interface CreateExtensionOptions< TConfig, > { id: string; - at: string; + attachTo: { id: string; input: string }; disabled?: boolean; inputs?: TInputs; output: TOutput; @@ -97,7 +91,7 @@ export interface CreateExtensionOptions< export interface Extension<TConfig> { $$type: '@backstage/Extension'; id: string; - at: string; + attachTo: { id: string; input: string }; disabled: boolean; inputs: AnyExtensionInputMap; output: AnyExtensionDataMap; diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.test.ts b/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.test.ts new file mode 100644 index 0000000000..fa430a7834 --- /dev/null +++ b/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.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 { createExtension } from './createExtension'; +import { + createExtensionOverrides, + toInternalExtensionOverrides, +} from './createExtensionOverrides'; + +describe('createExtensionOverrides', () => { + it('should create overrides without extensions', () => { + expect(createExtensionOverrides({ extensions: [] })).toMatchInlineSnapshot(` + { + "$$type": "@backstage/ExtensionOverrides", + "extensions": [], + "version": "v1", + } + `); + }); + + it('should create overrides with extensions', () => { + expect( + createExtensionOverrides({ + extensions: [ + createExtension({ + id: 'a', + attachTo: { id: 'core', input: 'apis' }, + output: {}, + factory() {}, + }), + ], + }), + ).toMatchInlineSnapshot(` + { + "$$type": "@backstage/ExtensionOverrides", + "extensions": [ + { + "$$type": "@backstage/Extension", + "attachTo": { + "id": "core", + "input": "apis", + }, + "disabled": false, + "factory": [Function], + "id": "a", + "inputs": {}, + "output": {}, + }, + ], + "version": "v1", + } + `); + }); + + it('should convert to internal overrides', () => { + const overrides = createExtensionOverrides({ + extensions: [ + createExtension({ + id: 'a', + attachTo: { id: 'core', input: 'apis' }, + output: {}, + factory() {}, + }), + ], + }); + const internal = toInternalExtensionOverrides(overrides); + expect(internal).toBe(overrides); + }); +}); diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts b/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts new file mode 100644 index 0000000000..2c64229eb9 --- /dev/null +++ b/packages/frontend-plugin-api/src/wiring/createExtensionOverrides.ts @@ -0,0 +1,62 @@ +/* + * 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 } from './createExtension'; + +/** @public */ +export interface ExtensionOverridesOptions { + extensions: Extension<unknown>[]; +} + +/** @public */ +export interface ExtensionOverrides { + $$type: '@backstage/ExtensionOverrides'; +} + +/** @internal */ +export interface InternalExtensionOverrides extends ExtensionOverrides { + version: string; + extensions: Extension<unknown>[]; +} + +/** @public */ +export function createExtensionOverrides( + options: ExtensionOverridesOptions, +): ExtensionOverrides { + return { + $$type: '@backstage/ExtensionOverrides', + version: 'v1', + extensions: options.extensions, + } as InternalExtensionOverrides; +} + +/** @internal */ +export function toInternalExtensionOverrides( + overrides: ExtensionOverrides, +): InternalExtensionOverrides { + const internal = overrides as InternalExtensionOverrides; + if (internal.$$type !== '@backstage/ExtensionOverrides') { + throw new Error( + `Invalid translation resource, bad type '${internal.$$type}'`, + ); + } + if (internal.version !== 'v1') { + throw new Error( + `Invalid translation resource, 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 b14838c17a..7f73c45544 100644 --- a/packages/frontend-plugin-api/src/wiring/createPlugin.test.ts +++ b/packages/frontend-plugin-api/src/wiring/createPlugin.test.ts @@ -30,7 +30,7 @@ const nameExtensionDataRef = createExtensionDataRef<string>('name'); const TechRadarPage = createExtension({ id: 'plugin.techradar.page', - at: 'test.output/names', + attachTo: { id: 'test.output', input: 'names' }, output: { name: nameExtensionDataRef, }, @@ -41,7 +41,7 @@ const TechRadarPage = createExtension({ const CatalogPage = createExtension({ id: 'plugin.catalog.page', - at: 'test.output/names', + attachTo: { id: 'test.output', input: 'names' }, output: { name: nameExtensionDataRef, }, @@ -55,7 +55,7 @@ const CatalogPage = createExtension({ const TechDocsAddon = createExtension({ id: 'plugin.techdocs.addon.example', - at: 'plugin.techdocs.page/addons', + attachTo: { id: 'plugin.techdocs.page', input: 'addons' }, output: { name: nameExtensionDataRef, }, @@ -69,7 +69,7 @@ const TechDocsAddon = createExtension({ const TechDocsPage = createExtension({ id: 'plugin.techdocs.page', - at: 'test.output/names', + attachTo: { id: 'test.output', input: 'names' }, inputs: { addons: createExtensionInput({ name: nameExtensionDataRef, @@ -85,7 +85,7 @@ const TechDocsPage = createExtension({ const outputExtension = createExtension({ id: 'test.output', - at: 'root', + attachTo: { id: 'core', input: 'root' }, inputs: { names: createExtensionInput({ name: nameExtensionDataRef, @@ -104,14 +104,14 @@ const outputExtension = createExtension({ }); function createTestAppRoot({ - plugins, + features, config = {}, }: { - plugins: BackstagePlugin[]; + features: BackstagePlugin[]; config: JsonObject; }) { return createApp({ - plugins: plugins, + features, configLoader: async () => new MockConfigApi(config), }).createRoot(); } @@ -132,7 +132,7 @@ describe('createPlugin', () => { await renderWithEffects( createTestAppRoot({ - plugins: [plugin], + features: [plugin], config: { app: { extensions: [{ 'core.layout': false }] } }, }), ); @@ -157,7 +157,7 @@ describe('createPlugin', () => { await renderWithEffects( createTestAppRoot({ - plugins: [plugin], + features: [plugin], config: { app: { extensions: [ diff --git a/packages/frontend-plugin-api/src/wiring/createPlugin.ts b/packages/frontend-plugin-api/src/wiring/createPlugin.ts index bd8e9954ef..84edd954ef 100644 --- a/packages/frontend-plugin-api/src/wiring/createPlugin.ts +++ b/packages/frontend-plugin-api/src/wiring/createPlugin.ts @@ -15,25 +15,49 @@ */ import { Extension } from './createExtension'; +import { ExternalRouteRef, RouteRef } from '../routing'; /** @public */ -export interface PluginOptions { +export type AnyRoutes = { [name in string]: RouteRef }; + +/** @public */ +export type AnyExternalRoutes = { [name in string]: ExternalRouteRef }; + +/** @public */ +export interface PluginOptions< + Routes extends AnyRoutes, + ExternalRoutes extends AnyExternalRoutes, +> { id: string; + routes?: Routes; + externalRoutes?: ExternalRoutes; extensions?: Extension<unknown>[]; } /** @public */ -export interface BackstagePlugin { +export interface BackstagePlugin< + Routes extends AnyRoutes = AnyRoutes, + ExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes, +> { $$type: '@backstage/BackstagePlugin'; id: string; extensions: Extension<unknown>[]; + routes: Routes; + externalRoutes: ExternalRoutes; } /** @public */ -export function createPlugin(options: PluginOptions): BackstagePlugin { +export function createPlugin< + Routes extends AnyRoutes = {}, + ExternalRoutes extends AnyExternalRoutes = {}, +>( + options: PluginOptions<Routes, ExternalRoutes>, +): BackstagePlugin<Routes, ExternalRoutes> { return { ...options, - $$type: '@backstage/BackstagePlugin', + routes: options.routes ?? ({} as Routes), + externalRoutes: options.externalRoutes ?? ({} as ExternalRoutes), extensions: options.extensions ?? [], + $$type: '@backstage/BackstagePlugin', }; } diff --git a/packages/frontend-plugin-api/src/wiring/index.ts b/packages/frontend-plugin-api/src/wiring/index.ts index b7f0acefd9..ec685d6c81 100644 --- a/packages/frontend-plugin-api/src/wiring/index.ts +++ b/packages/frontend-plugin-api/src/wiring/index.ts @@ -37,4 +37,11 @@ export { createPlugin, type BackstagePlugin, type PluginOptions, + type AnyRoutes, + type AnyExternalRoutes, } from './createPlugin'; +export { + createExtensionOverrides, + type ExtensionOverrides, + type ExtensionOverridesOptions, +} from './createExtensionOverrides'; diff --git a/packages/integration-aws-node/CHANGELOG.md b/packages/integration-aws-node/CHANGELOG.md index e62b3ff7fe..87156a5623 100644 --- a/packages/integration-aws-node/CHANGELOG.md +++ b/packages/integration-aws-node/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/integration-aws-node +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + +## 0.1.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + - @backstage/config@1.1.1-next.0 + ## 0.1.6 ### Patch Changes diff --git a/packages/integration-aws-node/package.json b/packages/integration-aws-node/package.json index cfe691b85c..714ccf4767 100644 --- a/packages/integration-aws-node/package.json +++ b/packages/integration-aws-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/integration-aws-node", "description": "Helpers for fetching AWS account credentials", - "version": "0.1.6", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/packages/integration-react/CHANGELOG.md b/packages/integration-react/CHANGELOG.md index 8ef2df3709..f26a0e631b 100644 --- a/packages/integration-react/CHANGELOG.md +++ b/packages/integration-react/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/integration-react +## 1.1.20 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/config@1.1.1 + +## 1.1.20-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/integration@1.7.1-next.1 + - @backstage/config@1.1.1-next.0 + ## 1.1.20-next.1 ### Patch Changes diff --git a/packages/integration-react/package.json b/packages/integration-react/package.json index 55e15f9b22..f5f77aa775 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.20-next.1", + "version": "1.1.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,29 +31,24 @@ }, "dependencies": { "@backstage/config": "workspace:^", - "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/integration": "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", - "react-use": "^17.2.4" + "@types/react": "^16.13.1 || ^17.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", + "@backstage/core-components": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/user-event": "^14.0.0", + "@testing-library/dom": "^9.0.0", + "@testing-library/jest-dom": "^6.0.0", "msw": "^1.0.0" }, "files": [ diff --git a/packages/integration/CHANGELOG.md b/packages/integration/CHANGELOG.md index 961e6eb869..552e225e3b 100644 --- a/packages/integration/CHANGELOG.md +++ b/packages/integration/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/integration +## 1.7.1 + +### Patch Changes + +- 3963d0b885: Ensure that all relevant config fields are properly marked as secret +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/config@1.1.1 + +## 1.7.1-next.1 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/config@1.1.1-next.0 + ## 1.7.1-next.0 ### Patch Changes diff --git a/packages/integration/package.json b/packages/integration/package.json index ab78c07edf..42a6ba4bf3 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.1-next.0", + "version": "1.7.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -35,7 +35,6 @@ "dependencies": { "@azure/identity": "^3.2.1", "@backstage/config": "workspace:^", - "@backstage/errors": "workspace:^", "@octokit/auth-app": "^4.0.0", "@octokit/rest": "^19.0.3", "cross-fetch": "^3.1.5", diff --git a/packages/repo-tools/CHANGELOG.md b/packages/repo-tools/CHANGELOG.md index 0864fd7347..75ee910172 100644 --- a/packages/repo-tools/CHANGELOG.md +++ b/packages/repo-tools/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/repo-tools +## 0.3.5 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/cli-node@0.1.5 + +## 0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/cli-node@0.1.5-next.1 + ## 0.3.5-next.0 ### Patch Changes diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index 8fc04fce71..fa398e598e 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.3.5-next.0", + "version": "0.3.5", "publishConfig": { "access": "public" }, diff --git a/packages/techdocs-cli-embedded-app/CHANGELOG.md b/packages/techdocs-cli-embedded-app/CHANGELOG.md index 45494ccba1..7a935bc85c 100644 --- a/packages/techdocs-cli-embedded-app/CHANGELOG.md +++ b/packages/techdocs-cli-embedded-app/CHANGELOG.md @@ -1,5 +1,43 @@ # techdocs-cli-embedded-app +## 0.2.87 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/test-utils@1.4.4 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/app-defaults@1.4.4 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## 0.2.87-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.23.0-next.2 + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/plugin-techdocs@1.7.1-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog@1.14.0-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/app-defaults@1.4.4-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/test-utils@1.4.4-next.2 + - @backstage/plugin-techdocs-react@1.1.12-next.2 + ## 0.2.87-next.1 ### Patch Changes diff --git a/packages/techdocs-cli-embedded-app/package.json b/packages/techdocs-cli-embedded-app/package.json index 21eee41e19..8cd74ea71a 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.87-next.1", + "version": "0.2.87", "private": true, "backstage": { "role": "frontend" @@ -29,16 +29,16 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "history": "^5.0.0", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.0.2", + "react-dom": "^18.0.2", "react-router-dom": "^6.3.0", "react-use": "^17.2.4" }, "devDependencies": { "@backstage/cli": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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": "*", "@types/react-dom": "*", diff --git a/packages/techdocs-cli-embedded-app/src/index.tsx b/packages/techdocs-cli-embedded-app/src/index.tsx index b15bc4c102..e5ca03fe64 100644 --- a/packages/techdocs-cli-embedded-app/src/index.tsx +++ b/packages/techdocs-cli-embedded-app/src/index.tsx @@ -16,7 +16,7 @@ import '@backstage/cli/asset-types'; import React from 'react'; -import ReactDOM from 'react-dom'; +import ReactDOM from 'react-dom/client'; import App from './App'; -ReactDOM.render(<App />, document.getElementById('root')); +ReactDOM.createRoot(document.getElementById('root')!).render(<App />); diff --git a/packages/techdocs-cli/CHANGELOG.md b/packages/techdocs-cli/CHANGELOG.md index abafa808fc..1ab192f698 100644 --- a/packages/techdocs-cli/CHANGELOG.md +++ b/packages/techdocs-cli/CHANGELOG.md @@ -1,5 +1,37 @@ # @techdocs/cli +## 1.6.0 + +### Minor Changes + +- d06b30b050: Add possibility to use a mkdocs config file with a different name than `mkdocs.<yaml|yml> with the serve command using the `--mkdocs-config-file-name` argument + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- 2b6e572051: Restructured tests. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-techdocs-node@1.9.0 + - @backstage/catalog-model@1.4.3 + - @backstage/cli-common@0.1.13 + - @backstage/config@1.1.1 + +## 1.6.0-next.2 + +### Minor Changes + +- d06b30b050: Add possibility to use a mkdocs config file with a different name than `mkdocs.<yaml|yml> with the serve command using the `--mkdocs-config-file-name` argument + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-techdocs-node@1.9.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/config@1.1.1-next.0 + ## 1.5.2-next.1 ### Patch Changes diff --git a/packages/techdocs-cli/cli-report.md b/packages/techdocs-cli/cli-report.md index 5f148daf24..890718b0d2 100644 --- a/packages/techdocs-cli/cli-report.md +++ b/packages/techdocs-cli/cli-report.md @@ -106,6 +106,7 @@ Options: -v --verbose --preview-app-bundle-path <PATH_TO_BUNDLE> --preview-app-port <PORT> + -c, --mkdocs-config-file-name <FILENAME> -h, --help ``` diff --git a/packages/techdocs-cli/package.json b/packages/techdocs-cli/package.json index 14120ab801..7b97f13e3f 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.5.2-next.1", + "version": "1.6.0", "publishConfig": { "access": "public" }, diff --git a/packages/techdocs-cli/src/commands/index.ts b/packages/techdocs-cli/src/commands/index.ts index 3321bb7f43..10a00da513 100644 --- a/packages/techdocs-cli/src/commands/index.ts +++ b/packages/techdocs-cli/src/commands/index.ts @@ -285,6 +285,10 @@ export function registerCommands(program: Command) { 'Port for the preview app to be served on', defaultPreviewAppPort, ) + .option( + '-c, --mkdocs-config-file-name <FILENAME>', + 'Mkdocs config file name', + ) .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 9e2e521546..5fcf1787d3 100644 --- a/packages/techdocs-cli/src/commands/serve/serve.ts +++ b/packages/techdocs-cli/src/commands/serve/serve.ts @@ -65,11 +65,13 @@ export default async function serve(opts: OptionValues) { const mkdocsExpectedDevAddr = opts.docker ? mkdocsDockerAddr : mkdocsLocalAddr; + const mkdocsConfigFileName = opts.mkdocsConfigFileName; + const siteName = opts.siteName; - const { path: mkdocsYmlPath, configIsTemporary } = await getMkdocsYml( - './', - opts.siteName, - ); + const { path: mkdocsYmlPath, configIsTemporary } = await getMkdocsYml('./', { + name: siteName, + mkdocsConfigFileName, + }); let mkdocsServerHasStarted = false; const mkdocsLogFunc: LogFunc = data => { @@ -104,6 +106,7 @@ export default async function serve(opts: OptionValues) { useDocker: opts.docker, stdoutLogFunc: mkdocsLogFunc, stderrLogFunc: mkdocsLogFunc, + mkdocsConfigFileName: mkdocsYmlPath, }); // Wait until mkdocs server has started so that Backstage starts with docs loaded diff --git a/packages/techdocs-cli/src/lib/mkdocsServer.ts b/packages/techdocs-cli/src/lib/mkdocsServer.ts index 5ca7e47573..42409acb46 100644 --- a/packages/techdocs-cli/src/lib/mkdocsServer.ts +++ b/packages/techdocs-cli/src/lib/mkdocsServer.ts @@ -25,6 +25,7 @@ export const runMkdocsServer = async (options: { dockerOptions?: string[]; stdoutLogFunc?: LogFunc; stderrLogFunc?: LogFunc; + mkdocsConfigFileName?: string; }): Promise<ChildProcess> => { const port = options.port ?? '8000'; const useDocker = options.useDocker ?? true; @@ -51,6 +52,9 @@ export const runMkdocsServer = async (options: { 'serve', '--dev-addr', `0.0.0.0:${port}`, + ...(options.mkdocsConfigFileName + ? ['--config-file', options.mkdocsConfigFileName] + : []), ], { stdoutLogFunc: options.stdoutLogFunc, @@ -59,8 +63,19 @@ export const runMkdocsServer = async (options: { ); } - return await run('mkdocs', ['serve', '--dev-addr', `127.0.0.1:${port}`], { - stdoutLogFunc: options.stdoutLogFunc, - stderrLogFunc: options.stderrLogFunc, - }); + return await run( + 'mkdocs', + [ + 'serve', + '--dev-addr', + `127.0.0.1:${port}`, + ...(options.mkdocsConfigFileName + ? ['--config-file', options.mkdocsConfigFileName] + : []), + ], + { + stdoutLogFunc: options.stdoutLogFunc, + stderrLogFunc: options.stderrLogFunc, + }, + ); }; diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index 4cab843d01..213877cfb0 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/test-utils +## 1.4.4 + +### Patch Changes + +- 322bbcae24: Removed the alpha `MockPluginProvider` export since the plugin configuration API has been removed. +- 1a0616fa10: Add missing resource and template app icons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## 1.4.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-permission-react@0.4.16-next.1 + ## 1.4.4-next.1 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index b972a6a824..28aa1715e6 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.4-next.1", + "version": "1.4.4", "publishConfig": { "access": "public" }, @@ -68,7 +68,7 @@ }, "devDependencies": { "@backstage/cli": "workspace:^", - "@testing-library/jest-dom": "^5.10.1", + "@testing-library/jest-dom": "^6.0.0", "msw": "^1.0.0" }, "files": [ diff --git a/packages/test-utils/src/testUtils/appWrappers.test.tsx b/packages/test-utils/src/testUtils/appWrappers.test.tsx index 19bdc15a48..79327afc0b 100644 --- a/packages/test-utils/src/testUtils/appWrappers.test.tsx +++ b/packages/test-utils/src/testUtils/appWrappers.test.tsx @@ -92,6 +92,11 @@ describe('wrapInTestApp', () => { }); expect(error).toEqual([ + expect.objectContaining({ + detail: new Error( + 'MockErrorApi received unexpected error, Error: NOPE', + ), + }), expect.objectContaining({ detail: new Error( 'MockErrorApi received unexpected error, Error: NOPE', diff --git a/packages/theme/CHANGELOG.md b/packages/theme/CHANGELOG.md index 445bc6055a..69c88c79ab 100644 --- a/packages/theme/CHANGELOG.md +++ b/packages/theme/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/theme +## 0.4.3 + +### Patch Changes + +- 5ad5344756: Added support for string `fontSize` values (e.g. `"2.5rem"`) in themes in addition to numbers. Also added an optional `fontFamily` prop for header typography variants to allow further customization. + +## 0.4.3-next.0 + +### Patch Changes + +- 5ad5344756: Added support for string `fontSize` values (e.g. `"2.5rem"`) in themes in addition to numbers. Also added an optional `fontFamily` prop for header typography variants to allow further customization. + ## 0.4.2 ### Patch Changes diff --git a/packages/theme/package.json b/packages/theme/package.json index 98be3baddd..77109aef87 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.2", + "version": "0.4.3", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -40,8 +40,8 @@ "peerDependencies": { "@material-ui/core": "^4.12.2", "@types/react": "^16.13.1 || ^17.0.0", - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/packages/version-bridge/CHANGELOG.md b/packages/version-bridge/CHANGELOG.md index bd7136e3ed..bffaff7177 100644 --- a/packages/version-bridge/CHANGELOG.md +++ b/packages/version-bridge/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/version-bridge +## 1.0.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. + ## 1.0.5 ### Patch Changes diff --git a/packages/version-bridge/package.json b/packages/version-bridge/package.json index f14b263747..caf196f497 100644 --- a/packages/version-bridge/package.json +++ b/packages/version-bridge/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/version-bridge", "description": "Utilities used by @backstage packages to support multiple concurrent versions", - "version": "1.0.5", + "version": "1.0.6", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -36,15 +36,14 @@ "@types/react": "^16.13.1 || ^17.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.0.0" + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0" }, "files": [ "dist" diff --git a/packages/version-bridge/src/lib/VersionedContext.test.tsx b/packages/version-bridge/src/lib/VersionedContext.test.tsx index 275e491324..4ffe3f45ca 100644 --- a/packages/version-bridge/src/lib/VersionedContext.test.tsx +++ b/packages/version-bridge/src/lib/VersionedContext.test.tsx @@ -15,7 +15,7 @@ */ import React, { useContext } from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { createVersionedContext, createVersionedContextForTesting, diff --git a/plugins/adr-backend/CHANGELOG.md b/plugins/adr-backend/CHANGELOG.md index e2acb92554..16446bee2a 100644 --- a/plugins/adr-backend/CHANGELOG.md +++ b/plugins/adr-backend/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-adr-backend +## 0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-adr-common@0.2.16 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## 0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-adr-common@0.2.16-next.1 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 0.4.2-next.1 ### Patch Changes diff --git a/plugins/adr-backend/package.json b/plugins/adr-backend/package.json index 580e3064af..ffc5740aaf 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.2-next.1", + "version": "0.4.3", "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 961562e016..849b00fdac 100644 --- a/plugins/adr-common/CHANGELOG.md +++ b/plugins/adr-common/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-adr-common +## 0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-search-common@1.2.7 + +## 0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 0.2.16-next.0 ### Patch Changes diff --git a/plugins/adr-common/package.json b/plugins/adr-common/package.json index 5e8e236b42..f3021eb4b1 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.16-next.0", + "version": "0.2.16", "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 950e2c7ca3..ea9f9519b0 100644 --- a/plugins/adr/CHANGELOG.md +++ b/plugins/adr/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-adr +## 0.6.8 + +### Patch Changes + +- 499e34656e: Fix icon alignment in `AdrSearchResultListItem` +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 1204e7628e: Create an experimental `AdrSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/theme@0.4.3 + - @backstage/plugin-adr-common@0.2.16 + - @backstage/plugin-search-common@1.2.7 + +## 0.6.8-next.2 + +### Patch Changes + +- 499e34656e: Fix icon alignment in `AdrSearchResultListItem` +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-adr-common@0.2.16-next.1 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 0.6.8-next.1 ### Patch Changes diff --git a/plugins/adr/alpha-api-report.md b/plugins/adr/alpha-api-report.md index 9d0bd071b1..5740556904 100644 --- a/plugins/adr/alpha-api-report.md +++ b/plugins/adr/alpha-api-report.md @@ -24,7 +24,7 @@ export const adrTranslationRef: TranslationRef< >; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin<{}, {}>; export default _default; // (No @packageDocumentation comment for this package) diff --git a/plugins/adr/package.json b/plugins/adr/package.json index 94d8250993..86e07013bf 100644 --- a/plugins/adr/package.json +++ b/plugins/adr/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-adr", - "version": "0.6.8-next.1", + "version": "0.6.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -62,8 +62,8 @@ "remark-gfm": "^3.0.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -71,9 +71,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/git-url-parse": "^9.0.0", "cross-fetch": "^3.1.5", diff --git a/plugins/airbrake-backend/CHANGELOG.md b/plugins/airbrake-backend/CHANGELOG.md index ba6e94f7eb..d10077998b 100644 --- a/plugins/airbrake-backend/CHANGELOG.md +++ b/plugins/airbrake-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-airbrake-backend +## 0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## 0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.3.2-next.1 ### Patch Changes diff --git a/plugins/airbrake-backend/package.json b/plugins/airbrake-backend/package.json index e7bbcc9310..dda7f4e28d 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.2-next.1", + "version": "0.3.3", "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 712f785b2e..725d9f883a 100644 --- a/plugins/airbrake/CHANGELOG.md +++ b/plugins/airbrake/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-airbrake +## 0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/test-utils@1.4.4 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/dev-utils@1.0.22 + - @backstage/theme@0.4.3 + +## 0.3.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/dev-utils@1.0.22-next.2 + - @backstage/test-utils@1.4.4-next.2 + ## 0.3.25-next.1 ### Patch Changes diff --git a/plugins/airbrake/package.json b/plugins/airbrake/package.json index 003da7d232..4e6476ecea 100644 --- a/plugins/airbrake/package.json +++ b/plugins/airbrake/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-airbrake", - "version": "0.3.25-next.1", + "version": "0.3.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -52,9 +52,9 @@ "@backstage/cli": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/allure/CHANGELOG.md b/plugins/allure/CHANGELOG.md index 956f4d79fa..7117a5e22a 100644 --- a/plugins/allure/CHANGELOG.md +++ b/plugins/allure/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-allure +## 0.1.41 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 0.1.41-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + ## 0.1.41-next.1 ### Patch Changes diff --git a/plugins/allure/package.json b/plugins/allure/package.json index fde188d1c8..628eea6651 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.41-next.1", + "version": "0.1.41", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -42,8 +42,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -51,9 +51,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/analytics-module-ga/CHANGELOG.md b/plugins/analytics-module-ga/CHANGELOG.md index 251990d5c3..72c42c20fb 100644 --- a/plugins/analytics-module-ga/CHANGELOG.md +++ b/plugins/analytics-module-ga/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-analytics-module-ga +## 0.1.34 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## 0.1.34-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + ## 0.1.34-next.1 ### Patch Changes diff --git a/plugins/analytics-module-ga/package.json b/plugins/analytics-module-ga/package.json index 86f0a4204e..44d922ed7a 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.34-next.1", + "version": "0.1.34", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -36,13 +36,12 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", - "prop-types": "^15.7.2", "react-ga": "^3.3.0", "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -50,9 +49,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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" diff --git a/plugins/analytics-module-ga4/CHANGELOG.md b/plugins/analytics-module-ga4/CHANGELOG.md index d79ec11dea..366fc6e16f 100644 --- a/plugins/analytics-module-ga4/CHANGELOG.md +++ b/plugins/analytics-module-ga4/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-analytics-module-ga4 +## 0.1.5 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## 0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + ## 0.1.5-next.1 ### Patch Changes diff --git a/plugins/analytics-module-ga4/package.json b/plugins/analytics-module-ga4/package.json index ab9611f5e8..705a430424 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.5-next.1", + "version": "0.1.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -37,8 +37,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -46,9 +46,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/jest": "^28.1.3", "@types/react": "^16.13.1 || ^17.0.0", diff --git a/plugins/analytics-module-newrelic-browser/CHANGELOG.md b/plugins/analytics-module-newrelic-browser/CHANGELOG.md index 7bfaf1c262..2d7e7ea467 100644 --- a/plugins/analytics-module-newrelic-browser/CHANGELOG.md +++ b/plugins/analytics-module-newrelic-browser/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-analytics-module-newrelic-browser +## 0.0.3 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/config@1.1.1 + +## 0.0.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/config@1.1.1-next.0 + ## 0.0.3-next.1 ### Patch Changes diff --git a/plugins/analytics-module-newrelic-browser/package.json b/plugins/analytics-module-newrelic-browser/package.json index c27be5f94e..06b3cf5e02 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.3-next.1", + "version": "0.0.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,15 +30,15 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0" + "react": "^16.13.1 || ^17.0.0 || ^18.0.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/apache-airflow/CHANGELOG.md b/plugins/apache-airflow/CHANGELOG.md index 4c0f6a418d..d245b155f6 100644 --- a/plugins/apache-airflow/CHANGELOG.md +++ b/plugins/apache-airflow/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-apache-airflow +## 0.2.16 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + +## 0.2.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + ## 0.2.16-next.1 ### Patch Changes diff --git a/plugins/apache-airflow/package.json b/plugins/apache-airflow/package.json index 28f8f81ab0..e87179784f 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.16-next.1", + "version": "0.2.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -40,8 +40,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -49,9 +49,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/api-docs-module-protoc-gen-doc/CHANGELOG.md b/plugins/api-docs-module-protoc-gen-doc/CHANGELOG.md index 3786ca011a..883ed270fa 100644 --- a/plugins/api-docs-module-protoc-gen-doc/CHANGELOG.md +++ b/plugins/api-docs-module-protoc-gen-doc/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-api-docs-module-protoc-gen-doc +## 0.1.4 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. + ## 0.1.3 ### Patch Changes diff --git a/plugins/api-docs-module-protoc-gen-doc/package.json b/plugins/api-docs-module-protoc-gen-doc/package.json index e0ad10f4f0..80fe6645d7 100644 --- a/plugins/api-docs-module-protoc-gen-doc/package.json +++ b/plugins/api-docs-module-protoc-gen-doc/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-api-docs-module-protoc-gen-doc", "description": "Additional functionalities for the api-docs plugin that renders the output of the protoc-gen-doc", - "version": "0.1.3", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -36,13 +36,13 @@ "grpc-docs": "^1.1.2" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", - "@testing-library/jest-dom": "^5.16.4" + "@testing-library/jest-dom": "^6.0.0" }, "files": [ "dist" diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index 021c55b807..5cefe7b94b 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-api-docs +## 0.9.12 + +### Patch Changes + +- 0117a6b47e: Adding `requestInterceptor` option to `api-docs` and pass it to SwaggerUI. This will enable to configure a proxy or headers to be sent to all the request made through the `Try it out` button on SwaggerUI. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 18f1756908: added aria-label on api definition button for better a11y. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 0.9.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/plugin-catalog@1.14.0-next.2 + - @backstage/theme@0.4.3-next.0 + ## 0.9.12-next.1 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index f257d85d82..53832682af 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.9.12-next.1", + "version": "0.9.12", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -52,8 +52,8 @@ "swagger-ui-react": "^5.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -61,9 +61,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/swagger-ui-react": "^4.18.0", "cross-fetch": "^3.1.5", diff --git a/plugins/api-docs/src/setupTests.ts b/plugins/api-docs/src/setupTests.ts index a41fe2eeb4..9bcfe5e887 100644 --- a/plugins/api-docs/src/setupTests.ts +++ b/plugins/api-docs/src/setupTests.ts @@ -16,6 +16,10 @@ import '@testing-library/jest-dom'; +Object.defineProperty(global, 'TextEncoder', { + value: require('util').TextEncoder, +}); + Object.defineProperty(global, 'TextDecoder', { value: require('util').TextDecoder, }); diff --git a/plugins/apollo-explorer/CHANGELOG.md b/plugins/apollo-explorer/CHANGELOG.md index 869e487cff..a502d30e7d 100644 --- a/plugins/apollo-explorer/CHANGELOG.md +++ b/plugins/apollo-explorer/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-apollo-explorer +## 0.1.16 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## 0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + ## 0.1.16-next.1 ### Patch Changes diff --git a/plugins/apollo-explorer/package.json b/plugins/apollo-explorer/package.json index 6c7eb11c50..6af85a2784 100644 --- a/plugins/apollo-explorer/package.json +++ b/plugins/apollo-explorer/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-apollo-explorer", - "version": "0.1.16-next.1", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -40,8 +40,8 @@ "use-deep-compare-effect": "^1.8.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -49,9 +49,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index d54709fbc2..991c1defc5 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-app-backend +## 0.3.54 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config-loader@1.5.1 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-app-node@0.1.6 + +## 0.3.54-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/config-loader@1.5.1-next.1 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-app-node@0.1.6-next.2 + ## 0.3.53-next.1 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index 0874b66a27..cda5301de8 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.53-next.1", + "version": "0.3.54", "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 d1d2284dce..30bfaecc96 100644 --- a/plugins/app-node/CHANGELOG.md +++ b/plugins/app-node/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-app-node +## 0.1.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + +## 0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6-next.2 + ## 0.1.5-next.1 ### Patch Changes diff --git a/plugins/app-node/package.json b/plugins/app-node/package.json index 5e21650501..915c5a0881 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.5-next.1", + "version": "0.1.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md b/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md index 8c14e20d07..9cf2657b6b 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-gcp-iap-provider/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-auth-backend-module-gcp-iap-provider +## 0.2.0 + +### Minor Changes + +- 6f142d5356: **BREAKING** `gcpIapAuthenticator.initialize()` is no longer `async` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/types@1.1.1 + +## 0.2.0-next.2 + +### Minor Changes + +- 6f142d5356: **BREAKING** `gcpIapAuthenticator.initialize()` is no longer `async` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/types@1.1.1 + ## 0.1.2-next.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 7e9cd78fa4..85ddf5aaba 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.1.2-next.1", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-gcp-iap-provider/src/authenticator.test.ts b/plugins/auth-backend-module-gcp-iap-provider/src/authenticator.test.ts index 51efbe1a04..5f90d3a379 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/src/authenticator.test.ts +++ b/plugins/auth-backend-module-gcp-iap-provider/src/authenticator.test.ts @@ -29,7 +29,7 @@ jest.mock('./helpers', () => ({ describe('GcpIapProvider', () => { it('should find default JWT header', async () => { - const ctx = await gcpIapAuthenticator.initialize({ + const ctx = gcpIapAuthenticator.initialize({ config: mockServices.rootConfig({ data: { audience: 'my-audience' } }), }); await expect( @@ -50,7 +50,7 @@ describe('GcpIapProvider', () => { it('should find custom JWT header', async () => { const jwtHeader = 'x-custom-header'; - const ctx = await gcpIapAuthenticator.initialize({ + const ctx = gcpIapAuthenticator.initialize({ config: mockServices.rootConfig({ data: { audience: 'my-audience', jwtHeader }, }), @@ -70,7 +70,7 @@ describe('GcpIapProvider', () => { }); it('should throw if header is missing', async () => { - const ctx = await gcpIapAuthenticator.initialize({ + const ctx = gcpIapAuthenticator.initialize({ config: mockServices.rootConfig({ data: { audience: 'my-audience' }, }), diff --git a/plugins/auth-backend-module-gcp-iap-provider/src/authenticator.ts b/plugins/auth-backend-module-gcp-iap-provider/src/authenticator.ts index ca104ded86..9bb68fcbb3 100644 --- a/plugins/auth-backend-module-gcp-iap-provider/src/authenticator.ts +++ b/plugins/auth-backend-module-gcp-iap-provider/src/authenticator.ts @@ -29,7 +29,7 @@ export const gcpIapAuthenticator = createProxyAuthenticator({ defaultProfileTransform: async (result: GcpIapResult) => { return { profile: { email: result.iapToken.email } }; }, - async initialize({ config }) { + initialize({ config }) { const audience = config.getString('audience'); const jwtHeader = config.getOptionalString('jwtHeader') ?? DEFAULT_IAP_JWT_HEADER; diff --git a/plugins/auth-backend-module-github-provider/CHANGELOG.md b/plugins/auth-backend-module-github-provider/CHANGELOG.md index d98d330281..80f47d6c2b 100644 --- a/plugins/auth-backend-module-github-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-github-provider/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-auth-backend-module-github-provider +## 0.1.3 + +### Patch Changes + +- 5d32a58b5a: Fixed a bug where the GitHub authenticator did not properly persist granted OAuth scopes. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## 0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + ## 0.1.2-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-github-provider/package.json b/plugins/auth-backend-module-github-provider/package.json index 25563c32c5..85b6927ba5 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.2-next.1", + "version": "0.1.3", "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 cafc7ec1a4..aad16984c2 100644 --- a/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-gitlab-provider/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-auth-backend-module-gitlab-provider +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## 0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + ## 0.1.2-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-gitlab-provider/package.json b/plugins/auth-backend-module-gitlab-provider/package.json index e039faf1a2..85fb4b77df 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.2-next.1", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-google-provider/CHANGELOG.md b/plugins/auth-backend-module-google-provider/CHANGELOG.md index 974a3c1dfe..4b78ea58fa 100644 --- a/plugins/auth-backend-module-google-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-google-provider/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-auth-backend-module-google-provider +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## 0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + ## 0.1.2-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-google-provider/package.json b/plugins/auth-backend-module-google-provider/package.json index 46adb1148e..7332f0c5e9 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.2-next.1", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-microsoft-provider/.eslintrc.js b/plugins/auth-backend-module-microsoft-provider/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/auth-backend-module-microsoft-provider/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md b/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md new file mode 100644 index 0000000000..4d982911e7 --- /dev/null +++ b/plugins/auth-backend-module-microsoft-provider/CHANGELOG.md @@ -0,0 +1,27 @@ +# @backstage/plugin-auth-backend-module-microsoft-provider + +## 0.1.0 + +### Minor Changes + +- 2d8f7e82c1: Migrated the Microsoft auth provider to new `@backstage/plugin-auth-backend-module-microsoft-provider` module package. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## 0.1.0-next.0 + +### Minor Changes + +- 2d8f7e82c1: Migrated the Microsoft auth provider to new `@backstage/plugin-auth-backend-module-microsoft-provider` module package. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 diff --git a/plugins/auth-backend-module-microsoft-provider/README.md b/plugins/auth-backend-module-microsoft-provider/README.md new file mode 100644 index 0000000000..5154f1644b --- /dev/null +++ b/plugins/auth-backend-module-microsoft-provider/README.md @@ -0,0 +1,8 @@ +# Auth Module: Microsoft Provider + +This module provides an Microsoft auth provider implementation for `@backstage/plugin-auth-backend`. + +## Links + +- [Repository](https://gitlab.com/backstage/backstage/tree/master/plugins/auth-backend-module-microsoft-provider) +- [Backstage Project Homepage](https://backstage.io) diff --git a/plugins/auth-backend-module-microsoft-provider/api-report.md b/plugins/auth-backend-module-microsoft-provider/api-report.md new file mode 100644 index 0000000000..60192c5cbc --- /dev/null +++ b/plugins/auth-backend-module-microsoft-provider/api-report.md @@ -0,0 +1,29 @@ +## API Report File for "@backstage/plugin-auth-backend-module-microsoft-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 authModuleMicrosoftProvider: () => BackendFeature; + +// @public (undocumented) +export const microsoftAuthenticator: OAuthAuthenticator< + PassportOAuthAuthenticatorHelper, + PassportProfile +>; + +// @public +export namespace microsoftSignInResolvers { + const emailMatchingUserEntityAnnotation: SignInResolverFactory< + OAuthAuthenticatorResult<PassportProfile>, + unknown + >; +} +``` diff --git a/plugins/auth-backend-module-microsoft-provider/catalog-info.yaml b/plugins/auth-backend-module-microsoft-provider/catalog-info.yaml new file mode 100644 index 0000000000..1742fc9ed6 --- /dev/null +++ b/plugins/auth-backend-module-microsoft-provider/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-auth-backend-module-microsoft-provider + title: '@backstage/plugin-auth-backend-module-microsoft-provider' + description: The microsoft-provider backend module for the auth plugin. +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: maintainers diff --git a/plugins/auth-backend-module-microsoft-provider/config.d.ts b/plugins/auth-backend-module-microsoft-provider/config.d.ts new file mode 100644 index 0000000000..5f1fa958e5 --- /dev/null +++ b/plugins/auth-backend-module-microsoft-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 */ + microsoft?: { + [authEnv: string]: { + clientId: string; + /** + * @visibility secret + */ + tenantId: string; + clientSecret: string; + callbackUrl?: string; + }; + }; + }; + }; +} diff --git a/plugins/auth-backend-module-microsoft-provider/dev/index.ts b/plugins/auth-backend-module-microsoft-provider/dev/index.ts new file mode 100644 index 0000000000..e701470af8 --- /dev/null +++ b/plugins/auth-backend-module-microsoft-provider/dev/index.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 { createBackend } from '@backstage/backend-defaults'; +import authPlugin from '@backstage/plugin-auth-backend'; +import { authModuleMicrosoftProvider } from '../src'; + +const backend = createBackend(); + +backend.add(authPlugin); +backend.add(authModuleMicrosoftProvider); + +backend.start(); diff --git a/plugins/auth-backend-module-microsoft-provider/package.json b/plugins/auth-backend-module-microsoft-provider/package.json new file mode 100644 index 0000000000..16c10667fe --- /dev/null +++ b/plugins/auth-backend-module-microsoft-provider/package.json @@ -0,0 +1,45 @@ +{ + "name": "@backstage/plugin-auth-backend-module-microsoft-provider", + "description": "The microsoft-provider backend module for the auth plugin.", + "version": "0.1.0", + "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.6.0", + "passport-microsoft": "^1.0.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-microsoft-provider/src/authenticator.ts b/plugins/auth-backend-module-microsoft-provider/src/authenticator.ts new file mode 100644 index 0000000000..ba1d75adf8 --- /dev/null +++ b/plugins/auth-backend-module-microsoft-provider/src/authenticator.ts @@ -0,0 +1,73 @@ +/* + * 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 MicrosoftStrategy } from 'passport-microsoft'; +import { + createOAuthAuthenticator, + PassportOAuthAuthenticatorHelper, + PassportOAuthDoneCallback, + PassportProfile, +} from '@backstage/plugin-auth-node'; + +/** @public */ +export const microsoftAuthenticator = createOAuthAuthenticator({ + defaultProfileTransform: + PassportOAuthAuthenticatorHelper.defaultProfileTransform, + initialize({ callbackUrl, config }) { + const clientId = config.getString('clientId'); + const clientSecret = config.getString('clientSecret'); + const tenantId = config.getString('tenantId'); + + return PassportOAuthAuthenticatorHelper.from( + new MicrosoftStrategy( + { + clientID: clientId, + clientSecret: clientSecret, + callbackURL: callbackUrl, + tenant: tenantId, + scope: ['user.read'], + }, + ( + 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', + }); + }, + + async authenticate(input, helper) { + return helper.authenticate(input); + }, + + async refresh(input, helper) { + return helper.refresh(input); + }, +}); diff --git a/plugins/auth-backend-module-microsoft-provider/src/index.ts b/plugins/auth-backend-module-microsoft-provider/src/index.ts new file mode 100644 index 0000000000..ae4fbf5926 --- /dev/null +++ b/plugins/auth-backend-module-microsoft-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 gitlab-provider backend module for the auth plugin. + * + * @packageDocumentation + */ + +export { microsoftAuthenticator } from './authenticator'; +export { authModuleMicrosoftProvider } from './module'; +export { microsoftSignInResolvers } from './resolvers'; diff --git a/plugins/auth-backend-module-microsoft-provider/src/module.test.ts b/plugins/auth-backend-module-microsoft-provider/src/module.test.ts new file mode 100644 index 0000000000..2cfedc5d5e --- /dev/null +++ b/plugins/auth-backend-module-microsoft-provider/src/module.test.ts @@ -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 { mockServices, startTestBackend } from '@backstage/backend-test-utils'; +import authPlugin from '@backstage/plugin-auth-backend'; +import { decodeOAuthState } from '@backstage/plugin-auth-node'; +import request from 'supertest'; +import { authModuleMicrosoftProvider } from './module'; + +describe('authModuleMicrosoftProvider', () => { + it('should start', async () => { + const { server } = await startTestBackend({ + features: [ + authPlugin, + authModuleMicrosoftProvider, + mockServices.rootConfig.factory({ + data: { + app: { + baseUrl: 'http://localhost:3000', + }, + auth: { + providers: { + microsoft: { + development: { + clientId: 'my-client-id', + clientSecret: 'my-client-secret', + tenantId: 'my-tenant-id', + }, + }, + }, + }, + }, + }), + ], + }); + + const agent = request.agent(server); + + const res = await agent.get('/api/auth/microsoft/start?env=development'); + + expect(res.status).toEqual(302); + + const nonceCookie = agent.jar.getCookie('microsoft-nonce', { + domain: 'localhost', + path: '/api/auth/microsoft/handler', + script: false, + secure: false, + }); + expect(nonceCookie).toBeDefined(); + + const startUrl = new URL(res.get('location')); + expect(startUrl.origin).toBe('https://login.microsoftonline.com'); + expect(startUrl.pathname).toBe('/my-tenant-id/oauth2/v2.0/authorize'); + expect(Object.fromEntries(startUrl.searchParams)).toEqual({ + response_type: 'code', + scope: 'user.read', + client_id: 'my-client-id', + redirect_uri: `http://localhost:${server.port()}/api/auth/microsoft/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-microsoft-provider/src/module.ts b/plugins/auth-backend-module-microsoft-provider/src/module.ts new file mode 100644 index 0000000000..4d5c5968a2 --- /dev/null +++ b/plugins/auth-backend-module-microsoft-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 { microsoftAuthenticator } from './authenticator'; +import { microsoftSignInResolvers } from './resolvers'; + +/** @public */ +export const authModuleMicrosoftProvider = createBackendModule({ + pluginId: 'auth', + moduleId: 'microsoft-provider', + register(reg) { + reg.registerInit({ + deps: { + providers: authProvidersExtensionPoint, + }, + async init({ providers }) { + providers.registerProvider({ + providerId: 'microsoft', + factory: createOAuthProviderFactory({ + authenticator: microsoftAuthenticator, + signInResolverFactories: { + ...microsoftSignInResolvers, + ...commonSignInResolvers, + }, + }), + }); + }, + }); + }, +}); diff --git a/plugins/auth-backend-module-microsoft-provider/src/resolvers.ts b/plugins/auth-backend-module-microsoft-provider/src/resolvers.ts new file mode 100644 index 0000000000..7ef4a57175 --- /dev/null +++ b/plugins/auth-backend-module-microsoft-provider/src/resolvers.ts @@ -0,0 +1,53 @@ +/* + * 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 { + OAuthAuthenticatorResult, + createSignInResolverFactory, + PassportProfile, + SignInInfo, +} from '@backstage/plugin-auth-node'; + +/** + * Available sign-in resolvers for the Microsoft auth provider. + * + * @public + */ +export namespace microsoftSignInResolvers { + /** + * Looks up the user by matching their Microsoft username to the entity name. + */ + export const emailMatchingUserEntityAnnotation = createSignInResolverFactory({ + create() { + return async ( + info: SignInInfo<OAuthAuthenticatorResult<PassportProfile>>, + ctx, + ) => { + const { profile } = info; + + if (!profile.email) { + throw new Error('Microsoft profile contained no email'); + } + + return ctx.signInWithCatalogUser({ + annotations: { + 'microsoft.com/email': profile.email, + }, + }); + }; + }, + }); +} diff --git a/packages/backend/src/plugins/graphql.ts b/plugins/auth-backend-module-microsoft-provider/src/types.d.ts similarity index 65% rename from packages/backend/src/plugins/graphql.ts rename to plugins/auth-backend-module-microsoft-provider/src/types.d.ts index c9aafa70ff..ca6ae9ac40 100644 --- a/packages/backend/src/plugins/graphql.ts +++ b/plugins/auth-backend-module-microsoft-provider/src/types.d.ts @@ -14,15 +14,12 @@ * limitations under the License. */ -import { createRouter } from '@backstage/plugin-graphql-backend'; -import { Router } from 'express'; -import { PluginEnvironment } from '../types'; +declare module 'passport-microsoft' { + import { Request } from 'express'; + import { StrategyCreated } from 'passport'; -export default async function createPlugin( - env: PluginEnvironment, -): Promise<Router> { - return await createRouter({ - logger: env.logger, - config: env.config, - }); + export class Strategy { + constructor(options: any, verify: any); + authenticate(this: StrategyCreated<this>, req: Request, options?: any): any; + } } diff --git a/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md b/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md index f2437a2e73..3920726928 100644 --- a/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md +++ b/plugins/auth-backend-module-oauth2-provider/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-auth-backend-module-oauth2-provider +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + +## 0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + ## 0.1.2-next.1 ### Patch Changes diff --git a/plugins/auth-backend-module-oauth2-provider/package.json b/plugins/auth-backend-module-oauth2-provider/package.json index 3e53ba5954..dda9aca87a 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.2-next.1", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-backend-module-pinniped-provider/.eslintrc.js b/plugins/auth-backend-module-pinniped-provider/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/auth-backend-module-pinniped-provider/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md b/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md new file mode 100644 index 0000000000..3d24e48a89 --- /dev/null +++ b/plugins/auth-backend-module-pinniped-provider/CHANGELOG.md @@ -0,0 +1,14 @@ +# @backstage/plugin-auth-backend-module-pinniped-provider + +## 0.1.0 + +### Minor Changes + +- ae34255836: Add new Pinniped auth module and authenticator to be used alongside the new Pinniped auth provider. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 diff --git a/plugins/auth-backend-module-pinniped-provider/README.md b/plugins/auth-backend-module-pinniped-provider/README.md new file mode 100644 index 0000000000..bdb340d426 --- /dev/null +++ b/plugins/auth-backend-module-pinniped-provider/README.md @@ -0,0 +1,7 @@ +# Auth Module: Pinniped Provider + +This module provides an Pinniped auth provider implementation for `@backstage/plugin-auth-backend`. + +## Links + +- [Backstage](https://backstage.io) diff --git a/plugins/auth-backend-module-pinniped-provider/api-report.md b/plugins/auth-backend-module-pinniped-provider/api-report.md new file mode 100644 index 0000000000..b9b993bd1e --- /dev/null +++ b/plugins/auth-backend-module-pinniped-provider/api-report.md @@ -0,0 +1,28 @@ +## API Report File for "@backstage/plugin-auth-backend-module-pinniped-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 { BaseClient } from 'openid-client'; +import { OAuthAuthenticator } from '@backstage/plugin-auth-node'; +import { Strategy } from 'openid-client'; +import { TokenSet } from 'openid-client'; + +// @public (undocumented) +export const authModulePinnipedProvider: () => BackendFeature; + +// @public (undocumented) +export const pinnipedAuthenticator: OAuthAuthenticator< + Promise<{ + providerStrategy: Strategy< + { + tokenset: TokenSet; + }, + BaseClient + >; + client: BaseClient; + }>, + unknown +>; +``` diff --git a/plugins/auth-backend-module-pinniped-provider/catalog-info.yaml b/plugins/auth-backend-module-pinniped-provider/catalog-info.yaml new file mode 100644 index 0000000000..9d1ef1c299 --- /dev/null +++ b/plugins/auth-backend-module-pinniped-provider/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-auth-backend-module-pinniped-provider + title: '@backstage/plugin-auth-backend-module-pinniped-provider' + description: The pinniped-provider backend module for the auth plugin. +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: maintainers diff --git a/plugins/auth-backend-module-pinniped-provider/dev/index.ts b/plugins/auth-backend-module-pinniped-provider/dev/index.ts new file mode 100644 index 0000000000..bd09f77a1f --- /dev/null +++ b/plugins/auth-backend-module-pinniped-provider/dev/index.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 { createBackend } from '@backstage/backend-defaults'; +import authPlugin from '@backstage/plugin-auth-backend'; +import { authModulePinnipedProvider } from '../src'; + +const backend = createBackend(); + +backend.add(authPlugin); +backend.add(authModulePinnipedProvider); + +backend.start(); diff --git a/plugins/auth-backend-module-pinniped-provider/package.json b/plugins/auth-backend-module-pinniped-provider/package.json new file mode 100644 index 0000000000..013fd6c49f --- /dev/null +++ b/plugins/auth-backend-module-pinniped-provider/package.json @@ -0,0 +1,49 @@ +{ + "name": "@backstage/plugin-auth-backend-module-pinniped-provider", + "description": "The pinniped-provider backend module for the auth plugin.", + "version": "0.1.0", + "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:^", + "openid-client": "^5.4.3" + }, + "devDependencies": { + "@backstage/backend-defaults": "workspace:^", + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/plugin-auth-backend": "workspace:^", + "cookie-parser": "^1.4.6", + "express": "^4.18.2", + "express-promise-router": "^4.1.1", + "express-session": "^1.17.3", + "jose": "^4.14.6", + "msw": "^1.3.0", + "passport": "^0.6.0", + "supertest": "^6.3.3" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/auth-backend-module-pinniped-provider/src/authenticator.test.ts b/plugins/auth-backend-module-pinniped-provider/src/authenticator.test.ts new file mode 100644 index 0000000000..f908c1ea13 --- /dev/null +++ b/plugins/auth-backend-module-pinniped-provider/src/authenticator.test.ts @@ -0,0 +1,503 @@ +/* + * 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 { + OAuthAuthenticatorAuthenticateInput, + OAuthAuthenticatorRefreshInput, + OAuthAuthenticatorStartInput, + OAuthState, + decodeOAuthState, + encodeOAuthState, +} from '@backstage/plugin-auth-node'; +import { pinnipedAuthenticator } from './authenticator'; +import { setupServer } from 'msw/node'; +import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; +import { ConfigReader } from '@backstage/config'; +import { JWK, SignJWT, exportJWK, generateKeyPair } from 'jose'; +import { rest } from 'msw'; +import express from 'express'; + +describe('pinnipedAuthenticator', () => { + let implementation: any; + let oauthState: OAuthState; + let idToken: string; + let publicKey: JWK; + + const mswServer = setupServer(); + setupRequestMockHandlers(mswServer); + + const issuerMetadata = { + issuer: 'https://pinniped.test', + authorization_endpoint: 'https://pinniped.test/oauth2/authorize', + token_endpoint: 'https://pinniped.test/oauth2/token', + revocation_endpoint: 'https://pinniped.test/oauth2/revoke_token', + userinfo_endpoint: 'https://pinniped.test/idp/userinfo.openid', + introspection_endpoint: 'https://pinniped.test/introspect.oauth2', + jwks_uri: 'https://pinniped.test/jwks.json', + scopes_supported: [ + 'openid', + 'offline_access', + 'pinniped:request-audience', + 'username', + 'groups', + ], + claims_supported: ['email', 'username', 'groups', 'additionalClaims'], + response_types_supported: ['code'], + id_token_signing_alg_values_supported: ['RS256', 'RS512', 'HS256'], + token_endpoint_auth_signing_alg_values_supported: [ + 'RS256', + 'RS512', + 'HS256', + ], + request_object_signing_alg_values_supported: ['RS256', 'RS512', 'HS256'], + }; + + const clusterScopedIdToken = 'dummy-token'; + + beforeAll(async () => { + const keyPair = await generateKeyPair('ES256'); + const privateKey = await exportJWK(keyPair.privateKey); + publicKey = await exportJWK(keyPair.publicKey); + publicKey.alg = privateKey.alg = 'ES256'; + + idToken = await new SignJWT({ + sub: 'test', + iss: 'https://pinniped.test', + iat: Date.now(), + aud: 'clientId', + exp: Date.now() + 10000, + }) + .setProtectedHeader({ alg: privateKey.alg, kid: privateKey.kid }) + .sign(keyPair.privateKey); + }); + + beforeEach(() => { + jest.clearAllMocks(); + + mswServer.use( + rest.get( + 'https://federationDomain.test/.well-known/openid-configuration', + (_req, res, ctx) => + res( + ctx.status(200), + ctx.set('Content-Type', 'application/json'), + ctx.json(issuerMetadata), + ), + ), + rest.get('https://pinniped.test/jwks.json', async (_req, res, ctx) => + res(ctx.status(200), ctx.json({ keys: [{ ...publicKey }] })), + ), + rest.post('https://pinniped.test/oauth2/token', async (req, res, ctx) => { + const formBody = new URLSearchParams(await req.text()); + const isGrantTypeTokenExchange = + formBody.get('grant_type') === + 'urn:ietf:params:oauth:grant-type:token-exchange'; + const hasValidTokenExchangeParams = + formBody.get('subject_token') === 'accessToken' && + formBody.get('audience') === 'test_cluster' && + formBody.get('subject_token_type') === + 'urn:ietf:params:oauth:token-type:access_token' && + formBody.get('requested_token_type') === + 'urn:ietf:params:oauth:token-type:jwt'; + + return res( + req.headers.get('Authorization') && + (!isGrantTypeTokenExchange || hasValidTokenExchangeParams) + ? ctx.json({ + access_token: isGrantTypeTokenExchange + ? clusterScopedIdToken + : 'accessToken', + refresh_token: 'refreshToken', + ...(!isGrantTypeTokenExchange && { id_token: idToken }), + scope: 'testScope', + }) + : ctx.status(401), + ); + }), + ); + + implementation = pinnipedAuthenticator.initialize({ + callbackUrl: 'https://backstage.test/callback', + config: new ConfigReader({ + federationDomain: 'https://federationDomain.test', + clientId: 'clientId', + clientSecret: 'clientSecret', + }), + }); + + oauthState = { + nonce: 'nonce', + env: 'env', + }; + }); + + describe('#start', () => { + let fakeSession: Record<string, any>; + let startRequest: OAuthAuthenticatorStartInput; + + beforeEach(() => { + fakeSession = {}; + startRequest = { + state: encodeOAuthState(oauthState), + req: { + method: 'GET', + url: 'test', + session: fakeSession, + }, + } as unknown as OAuthAuthenticatorStartInput; + }); + + it('redirects to authorization endpoint returned from OIDC metadata endpoint', async () => { + const startResponse = await pinnipedAuthenticator.start( + startRequest, + implementation, + ); + const url = new URL(startResponse.url); + + expect(url.protocol).toBe('https:'); + expect(url.hostname).toBe('pinniped.test'); + expect(url.pathname).toBe('/oauth2/authorize'); + }); + + it('initiates authorization code grant', async () => { + const startResponse = await pinnipedAuthenticator.start( + startRequest, + implementation, + ); + const { searchParams } = new URL(startResponse.url); + + expect(searchParams.get('response_type')).toBe('code'); + }); + + it('persists audience parameter in oauth state', async () => { + startRequest.req.query = { audience: 'test-cluster' }; + const startResponse = await pinnipedAuthenticator.start( + startRequest, + implementation, + ); + const { searchParams } = new URL(startResponse.url); + const stateParam = searchParams.get('state'); + const decodedState = decodeOAuthState(stateParam!); + + expect(decodedState).toMatchObject({ + nonce: 'nonce', + env: 'env', + audience: 'test-cluster', + }); + }); + + it('passes client ID from config', async () => { + const startResponse = await pinnipedAuthenticator.start( + startRequest, + implementation, + ); + const { searchParams } = new URL(startResponse.url); + + expect(searchParams.get('client_id')).toBe('clientId'); + }); + + it('passes callback URL from config', async () => { + const startResponse = await pinnipedAuthenticator.start( + startRequest, + implementation, + ); + const { searchParams } = new URL(startResponse.url); + + expect(searchParams.get('redirect_uri')).toBe( + 'https://backstage.test/callback', + ); + }); + + it('generates PKCE challenge', async () => { + const startResponse = await pinnipedAuthenticator.start( + startRequest, + implementation, + ); + 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 pinnipedAuthenticator.start(startRequest, implementation); + expect(fakeSession['oidc:pinniped.test'].code_verifier).toBeDefined(); + }); + + it('requests sufficient scopes for token exchange by default', async () => { + const startResponse = await pinnipedAuthenticator.start( + startRequest, + implementation, + ); + const { searchParams } = new URL(startResponse.url); + const scopes = searchParams.get('scope')?.split(' ') ?? []; + + expect(scopes).toEqual( + expect.arrayContaining([ + 'openid', + 'pinniped:request-audience', + 'username', + 'offline_access', + ]), + ); + }); + + it('encodes OAuth state in query param', async () => { + const startResponse = await pinnipedAuthenticator.start( + startRequest, + implementation, + ); + const { searchParams } = new URL(startResponse.url); + const stateParam = searchParams.get('state'); + const decodedState = decodeOAuthState(stateParam!); + + expect(decodedState).toMatchObject(oauthState); + }); + + it('fails when request has no session', async () => { + return expect( + pinnipedAuthenticator.start( + { + state: encodeOAuthState(oauthState), + req: { + method: 'GET', + url: 'test', + }, + } as unknown as OAuthAuthenticatorStartInput, + implementation, + ), + ).rejects.toThrow('authentication requires session support'); + }); + }); + + describe('#authenticate', () => { + let handlerRequest: OAuthAuthenticatorAuthenticateInput; + + beforeEach(() => { + handlerRequest = { + req: { + method: 'GET', + url: `https://test?code=authorization_code&state=${encodeOAuthState( + oauthState, + )}`, + session: { + 'oidc:pinniped.test': { + state: encodeOAuthState(oauthState), + }, + }, + } as unknown as express.Request, + }; + }); + + it('exchanges authorization code for access token', async () => { + const handlerResponse = await pinnipedAuthenticator.authenticate( + handlerRequest, + implementation, + ); + const accessToken = handlerResponse.session.accessToken; + + expect(accessToken).toEqual('accessToken'); + }); + + it('exchanges authorization code for refresh token', async () => { + const handlerResponse = await pinnipedAuthenticator.authenticate( + handlerRequest, + implementation, + ); + const refreshToken = handlerResponse.session.refreshToken; + + expect(refreshToken).toEqual('refreshToken'); + }); + + it('returns granted scope', async () => { + const handlerResponse = await pinnipedAuthenticator.authenticate( + handlerRequest, + implementation, + ); + const responseScope = handlerResponse.session.scope; + + expect(responseScope).toEqual('testScope'); + }); + + it('returns cluster-scoped ID token when audience is specified', async () => { + oauthState.audience = 'test_cluster'; + handlerRequest = { + req: { + method: 'GET', + url: `https://test?code=authorization_code&state=${encodeOAuthState( + oauthState, + )}`, + session: { + 'oidc:pinniped.test': { + state: encodeOAuthState(oauthState), + }, + }, + } as unknown as express.Request, + }; + + const handlerResponse = await pinnipedAuthenticator.authenticate( + handlerRequest, + implementation, + ); + + expect(handlerResponse.session.idToken).toEqual(clusterScopedIdToken); + }); + + it('fails on network error during token exchange', async () => { + mswServer.use( + rest.post( + 'https://pinniped.test/oauth2/token', + async (req, res, ctx) => { + const formBody = new URLSearchParams(await req.text()); + const isGrantTypeTokenExchange = + formBody.get('grant_type') === + 'urn:ietf:params:oauth:grant-type:token-exchange'; + const hasValidTokenExchangeParams = + formBody.get('subject_token') === 'accessToken' && + formBody.get('audience') === 'test_cluster' && + formBody.get('subject_token_type') === + 'urn:ietf:params:oauth:token-type:access_token' && + formBody.get('requested_token_type') === + 'urn:ietf:params:oauth:token-type:jwt'; + + mswServer.use( + rest.post( + 'https://pinniped.test/oauth2/token', + async (_req, response, _ctx) => + response.networkError('Connection timed out'), + ), + ); + + return res( + req.headers.get('Authorization') && + (!isGrantTypeTokenExchange || hasValidTokenExchangeParams) + ? ctx.json({ + access_token: isGrantTypeTokenExchange + ? clusterScopedIdToken + : 'accessToken', + refresh_token: 'refreshToken', + ...(!isGrantTypeTokenExchange && { id_token: idToken }), + scope: 'testScope', + }) + : ctx.status(401), + ); + }, + ), + ); + + oauthState.audience = 'test_cluster'; + handlerRequest = { + req: { + method: 'GET', + url: `https://test?code=authorization_code&state=${encodeOAuthState( + oauthState, + )}`, + session: { + 'oidc:pinniped.test': { + state: encodeOAuthState(oauthState), + }, + }, + } as unknown as express.Request, + }; + + await expect( + pinnipedAuthenticator.authenticate(handlerRequest, implementation), + ).rejects.toThrow( + `Failed to get cluster specific ID token for "test_cluster": Error: RFC8693 token exchange failed with error: NetworkError: Connection timed out`, + ); + }); + + it('fails without authorization code', async () => { + handlerRequest.req.url = 'https://test.com'; + return expect( + pinnipedAuthenticator.authenticate(handlerRequest, implementation), + ).rejects.toThrow('Unexpected redirect'); + }); + + it('fails without oauth state', async () => { + return expect( + pinnipedAuthenticator.authenticate( + { + req: { + method: 'GET', + url: `https://test?code=authorization_code}`, + session: { + ['oidc:pinniped.test']: { + state: { handle: 'sessionid', code_verifier: 'foo' }, + }, + }, + } as unknown as express.Request, + }, + implementation, + ), + ).rejects.toThrow( + 'Authentication rejected, state missing from the response', + ); + }); + + it('fails when request has no session', async () => { + return expect( + pinnipedAuthenticator.authenticate( + { + req: { + method: 'GET', + url: 'https://test.com', + } as unknown as express.Request, + }, + implementation, + ), + ).rejects.toThrow('authentication requires session support'); + }); + }); + + describe('#refresh', () => { + let refreshRequest: OAuthAuthenticatorRefreshInput; + + beforeEach(() => { + refreshRequest = { + scope: '', + refreshToken: 'otherRefreshToken', + req: {} as express.Request, + }; + }); + + it('gets new refresh token', async () => { + const refreshResponse = await pinnipedAuthenticator.refresh( + refreshRequest, + implementation, + ); + + expect(refreshResponse.session.refreshToken).toBe('refreshToken'); + }); + + it('gets access token', async () => { + const refreshResponse = await pinnipedAuthenticator.refresh( + refreshRequest, + implementation, + ); + + expect(refreshResponse.session.accessToken).toBe('accessToken'); + }); + + it('gets id token', async () => { + const refreshResponse = await pinnipedAuthenticator.refresh( + refreshRequest, + implementation, + ); + + expect(refreshResponse.session.idToken).toBe(idToken); + }); + }); +}); diff --git a/plugins/auth-backend-module-pinniped-provider/src/authenticator.ts b/plugins/auth-backend-module-pinniped-provider/src/authenticator.ts new file mode 100644 index 0000000000..83c4204ad0 --- /dev/null +++ b/plugins/auth-backend-module-pinniped-provider/src/authenticator.ts @@ -0,0 +1,195 @@ +/* + * 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 { PassportDoneCallback } from '@backstage/plugin-auth-node'; +import { + createOAuthAuthenticator, + decodeOAuthState, + encodeOAuthState, +} from '@backstage/plugin-auth-node'; +import { + Client, + Issuer, + TokenSet, + Strategy as OidcStrategy, +} from 'openid-client'; + +const rfc8693TokenExchange = async ({ + subject_token, + target_audience, + ctx, +}: { + subject_token: string; + target_audience: string; + ctx: Promise<{ + providerStrategy: OidcStrategy<{}>; + client: Client; + }>; +}): Promise<string | undefined> => { + const { client } = await ctx; + return client + .grant({ + grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange', + subject_token, + audience: target_audience, + subject_token_type: 'urn:ietf:params:oauth:token-type:access_token', + requested_token_type: 'urn:ietf:params:oauth:token-type:jwt', + }) + .then(tokenset => tokenset.access_token) + .catch(err => { + throw new Error(`RFC8693 token exchange failed with error: ${err}`); + }); +}; + +/** @public */ +export const pinnipedAuthenticator = createOAuthAuthenticator({ + defaultProfileTransform: async (_r, _c) => ({ profile: {} }), + async initialize({ callbackUrl, config }) { + const issuer = await Issuer.discover( + `${config.getString( + 'federationDomain', + )}/.well-known/openid-configuration`, + ); + const client = new issuer.Client({ + access_type: 'offline', // this option must be passed to provider to receive a refresh token + client_id: config.getString('clientId'), + client_secret: config.getString('clientSecret'), + redirect_uris: [callbackUrl], + response_types: ['code'], + scope: config.getOptionalString('scope') || '', + id_token_signed_response_alg: 'ES256', + }); + const providerStrategy = new OidcStrategy( + { + client, + passReqToCallback: false, + }, + ( + tokenset: TokenSet, + done: PassportDoneCallback< + { tokenset: TokenSet }, + { + refreshToken?: string; + } + >, + ) => { + done(undefined, { tokenset }, {}); + }, + ); + + return { providerStrategy, client }; + }, + + async start(input, ctx) { + const { providerStrategy } = await ctx; + const stringifiedAudience = input.req.query?.audience as string; + const decodedState = decodeOAuthState(input.state); + const state = { ...decodedState, audience: stringifiedAudience }; + const options: Record<string, string> = { + scope: + input.scope || + 'openid pinniped:request-audience username offline_access', + state: encodeOAuthState(state), + }; + + return new Promise((resolve, reject) => { + const strategy = Object.create(providerStrategy); + strategy.redirect = (url: string) => { + resolve({ url }); + }; + strategy.error = (error: Error) => { + reject(error); + }; + strategy.authenticate(input.req, { ...options }); + }); + }, + + async authenticate(input, ctx) { + const { providerStrategy } = await ctx; + const { req } = input; + const { searchParams } = new URL(req.url, 'https://pinniped.com'); + const stateParam = searchParams.get('state'); + const audience = stateParam + ? decodeOAuthState(stateParam).audience + : undefined; + + return new Promise((resolve, reject) => { + const strategy = Object.create(providerStrategy); + strategy.success = (user: any) => { + (audience + ? rfc8693TokenExchange({ + subject_token: user.tokenset.access_token, + target_audience: audience, + ctx, + }).catch(err => + reject( + new Error( + `Failed to get cluster specific ID token for "${audience}": ${err}`, + ), + ), + ) + : Promise.resolve(user.tokenset.id_token) + ).then(idToken => { + resolve({ + fullProfile: { provider: '', id: '', displayName: '' }, + session: { + accessToken: user.tokenset.access_token!, + tokenType: user.tokenset.token_type ?? 'bearer', + scope: user.tokenset.scope!, + idToken, + refreshToken: user.tokenset.refresh_token, + }, + }); + }); + }; + + strategy.fail = (info: any) => { + reject(new Error(`Authentication rejected, ${info.message || ''}`)); + }; + + strategy.error = (error: Error) => { + reject(error); + }; + + strategy.redirect = () => { + reject(new Error('Unexpected redirect')); + }; + + strategy.authenticate(req); + }); + }, + + async refresh(input, ctx) { + const { client } = await ctx; + const tokenset = await client.refresh(input.refreshToken); + + return new Promise((resolve, reject) => { + if (!tokenset.access_token) { + reject(new Error('Refresh Failed')); + } + + resolve({ + fullProfile: { provider: '', id: '', displayName: '' }, + session: { + accessToken: tokenset.access_token!, + tokenType: tokenset.token_type ?? 'bearer', + scope: tokenset.scope!, + idToken: tokenset.id_token, + refreshToken: tokenset.refresh_token, + }, + }); + }); + }, +}); diff --git a/plugins/auth-backend-module-pinniped-provider/src/config.d.ts b/plugins/auth-backend-module-pinniped-provider/src/config.d.ts new file mode 100644 index 0000000000..50685abfb0 --- /dev/null +++ b/plugins/auth-backend-module-pinniped-provider/src/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 { + /** Configuration options for the auth plugin */ + auth?: { + providers?: { + pinniped?: { + [authEnv: string]: { + clientId: string; + federationDomain: string; + /** + * @visibility secret + */ + clientSecret: string; + scope?: string; + }; + }; + }; + }; +} diff --git a/plugins/auth-backend-module-pinniped-provider/src/index.ts b/plugins/auth-backend-module-pinniped-provider/src/index.ts new file mode 100644 index 0000000000..9a2ca6727e --- /dev/null +++ b/plugins/auth-backend-module-pinniped-provider/src/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. + */ + +/** + * The pinniped-provider backend module for the auth plugin. + * + * @packageDocumentation + */ + +export { pinnipedAuthenticator } from './authenticator'; +export { authModulePinnipedProvider } from './module'; diff --git a/plugins/auth-backend-module-pinniped-provider/src/module.test.ts b/plugins/auth-backend-module-pinniped-provider/src/module.test.ts new file mode 100644 index 0000000000..ed285cff86 --- /dev/null +++ b/plugins/auth-backend-module-pinniped-provider/src/module.test.ts @@ -0,0 +1,260 @@ +/* + * 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 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'; +import { JWK, SignJWT, exportJWK, generateKeyPair } from 'jose'; + +describe('authModulePinnipedProvider', () => { + let app: express.Express; + let backstageServer: Server; + let appUrl: string; + let providerRouteHandler: AuthProviderRouteHandlers; + let idToken: string; + let publicKey: JWK; + + const mswServer = setupServer(); + setupRequestMockHandlers(mswServer); + + const issuerMetadata = { + issuer: 'https://pinniped.test', + authorization_endpoint: 'https://pinniped.test/oauth2/authorize', + token_endpoint: 'https://pinniped.test/oauth2/token', + revocation_endpoint: 'https://pinniped.test/oauth2/revoke_token', + userinfo_endpoint: 'https://pinniped.test/idp/userinfo.openid', + introspection_endpoint: 'https://pinniped.test/introspect.oauth2', + jwks_uri: 'https://pinniped.test/jwks.json', + scopes_supported: [ + 'openid', + 'offline_access', + 'pinniped:request-audience', + 'username', + 'groups', + ], + claims_supported: ['email', 'username', 'groups', 'additionalClaims'], + response_types_supported: ['code'], + id_token_signing_alg_values_supported: ['RS256', 'RS512', 'HS256'], + token_endpoint_auth_signing_alg_values_supported: [ + 'RS256', + 'RS512', + 'HS256', + ], + request_object_signing_alg_values_supported: ['RS256', 'RS512', 'HS256'], + }; + + const clusterScopedIdToken = 'dummy-token'; + + beforeAll(async () => { + const keyPair = await generateKeyPair('ES256'); + const privateKey = await exportJWK(keyPair.privateKey); + publicKey = await exportJWK(keyPair.publicKey); + publicKey.alg = privateKey.alg = 'ES256'; + + idToken = await new SignJWT({ + sub: 'test', + iss: 'https://pinniped.test', + iat: Date.now(), + aud: 'clientId', + exp: Date.now() + 10000, + }) + .setProtectedHeader({ alg: privateKey.alg, kid: privateKey.kid }) + .sign(keyPair.privateKey); + }); + + beforeEach(async () => { + jest.clearAllMocks(); + + mswServer.use( + rest.get( + 'https://federationDomain.test/.well-known/openid-configuration', + (_req, res, ctx) => + res( + ctx.status(200), + ctx.set('Content-Type', 'application/json'), + ctx.json(issuerMetadata), + ), + ), + rest.get( + 'https://pinniped.test/oauth2/authorize', + async (req, res, ctx) => { + const callbackUrl = new URL( + req.url.searchParams.get('redirect_uri')!, + ); + callbackUrl.searchParams.set('code', 'authorization_code'); + callbackUrl.searchParams.set( + 'state', + req.url.searchParams.get('state')!, + ); + callbackUrl.searchParams.set('scope', 'test-scope'); + return res( + ctx.status(302), + ctx.set('Location', callbackUrl.toString()), + ); + }, + ), + rest.get('https://pinniped.test/jwks.json', async (_req, res, ctx) => + res(ctx.status(200), ctx.json({ keys: [{ ...publicKey }] })), + ), + rest.post('https://pinniped.test/oauth2/token', async (req, res, ctx) => { + const formBody = new URLSearchParams(await req.text()); + const isGrantTypeTokenExchange = + formBody.get('grant_type') === + 'urn:ietf:params:oauth:grant-type:token-exchange'; + const hasValidTokenExchangeParams = + formBody.get('subject_token') === 'accessToken' && + formBody.get('audience') === 'test_cluster' && + formBody.get('subject_token_type') === + 'urn:ietf:params:oauth:token-type:access_token' && + formBody.get('requested_token_type') === + 'urn:ietf:params:oauth:token-type:jwt'; + + return res( + req.headers.get('Authorization') && + (!isGrantTypeTokenExchange || hasValidTokenExchangeParams) + ? ctx.json({ + access_token: isGrantTypeTokenExchange + ? clusterScopedIdToken + : 'accessToken', + refresh_token: 'refreshToken', + ...(!isGrantTypeTokenExchange && { id_token: idToken }), + scope: 'testScope', + }) + : ctx.status(401), + ); + }), + ); + + 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: '' }, + }, + }), + 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); + }); + + afterEach(() => { + backstageServer.close(); + }); + + it('should start', async () => { + const agent = request.agent(backstageServer); + const startResponse = await agent.get( + `/api/auth/pinniped/start?env=development&audience=test_cluster`, + ); + + expect(startResponse.status).toBe(302); + }); + + it('/handler/frame exchanges authorization code from #start for Cluster Specific ID token', async () => { + const agent = request.agent(''); + + // make /start request with audience parameter + const startResponse = await agent.get( + `${appUrl}/api/auth/pinniped/start?env=development&audience=test_cluster`, + ); + // follow redirect to authorization endpoint + const authorizationResponse = await agent.get( + startResponse.header.location, + ); + // follow redirect to token_endpoint + const handlerResponse = await agent.get( + authorizationResponse.header.location, + ); + + expect(handlerResponse.text).toContain( + encodeURIComponent( + JSON.stringify({ + type: 'authorization_response', + response: { + profile: {}, + providerInfo: { + idToken: clusterScopedIdToken, + accessToken: 'accessToken', + scope: 'testScope', + }, + }, + }), + ), + ); + }); +}); diff --git a/plugins/auth-backend-module-pinniped-provider/src/module.ts b/plugins/auth-backend-module-pinniped-provider/src/module.ts new file mode 100644 index 0000000000..5fff30e82e --- /dev/null +++ b/plugins/auth-backend-module-pinniped-provider/src/module.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 { createBackendModule } from '@backstage/backend-plugin-api'; +import { + authProvidersExtensionPoint, + commonSignInResolvers, + createOAuthProviderFactory, +} from '@backstage/plugin-auth-node'; +import { pinnipedAuthenticator } from './authenticator'; + +/** @public */ +export const authModulePinnipedProvider = createBackendModule({ + pluginId: 'auth', + moduleId: 'pinniped-provider', + register(reg) { + reg.registerInit({ + deps: { + providers: authProvidersExtensionPoint, + }, + async init({ providers }) { + providers.registerProvider({ + providerId: 'pinniped', + factory: createOAuthProviderFactory({ + authenticator: pinnipedAuthenticator, + signInResolverFactories: { + ...commonSignInResolvers, + }, + }), + }); + }, + }); + }, +}); diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index f2eadd6c3d..d682f21c26 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,50 @@ # @backstage/plugin-auth-backend +## 0.19.3 + +### Patch Changes + +- 9ff7935152: Fixed bug in oidc refresh handler, if token endpoints response on refresh request does not contain a scope, the requested scope is used. +- 2d8f7e82c1: Migrated the Microsoft auth provider to new `@backstage/plugin-auth-backend-module-microsoft-provider` module package. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-auth-backend-module-github-provider@0.1.3 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.0 + - @backstage/plugin-auth-backend-module-microsoft-provider@0.1.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.3 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-backend-module-google-provider@0.1.3 + +## 0.19.3-next.2 + +### Patch Changes + +- 2d8f7e82c1: Migrated the Microsoft auth provider to new `@backstage/plugin-auth-backend-module-microsoft-provider` module package. +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-auth-backend-module-gcp-iap-provider@0.2.0-next.2 + - @backstage/plugin-auth-backend-module-microsoft-provider@0.1.0-next.0 + - @backstage/plugin-auth-backend-module-github-provider@0.1.3-next.2 + - @backstage/plugin-auth-backend-module-gitlab-provider@0.1.3-next.2 + - @backstage/plugin-auth-backend-module-oauth2-provider@0.1.3-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-auth-backend-module-google-provider@0.1.3-next.2 + ## 0.19.2-next.1 ### Patch Changes diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 6372c2ee60..41536f2a3f 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -538,9 +538,9 @@ export const providers: Readonly<{ | undefined, ) => AuthProviderFactory_2; resolvers: Readonly<{ - emailLocalPartMatchingUserEntityName: () => SignInResolver<unknown>; - emailMatchingUserEntityProfileEmail: () => SignInResolver<unknown>; - emailMatchingUserEntityAnnotation(): SignInResolver<OAuthResult>; + emailMatchingUserEntityProfileEmail: () => SignInResolver_2<OAuthResult>; + emailLocalPartMatchingUserEntityName: () => SignInResolver_2<OAuthResult>; + emailMatchingUserEntityAnnotation: () => SignInResolver_2<OAuthResult>; }>; }>; oauth2: Readonly<{ diff --git a/plugins/auth-backend/config.d.ts b/plugins/auth-backend/config.d.ts index e719468ac1..f8953e1588 100644 --- a/plugins/auth-backend/config.d.ts +++ b/plugins/auth-backend/config.d.ts @@ -179,18 +179,6 @@ export interface Config { }; }; /** @visibility frontend */ - microsoft?: { - [authEnv: string]: { - clientId: string; - /** - * @visibility secret - */ - clientSecret: string; - tenantId: string; - callbackUrl?: string; - }; - }; - /** @visibility frontend */ onelogin?: { [authEnv: string]: { clientId: string; diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 398814564e..61e7993ab3 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.19.2-next.1", + "version": "0.19.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -42,6 +42,7 @@ "@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-microsoft-provider": "workspace:^", "@backstage/plugin-auth-backend-module-oauth2-provider": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", diff --git a/plugins/auth-backend/src/providers/microsoft/__testUtils__/fake.test.ts b/plugins/auth-backend/src/providers/microsoft/__testUtils__/fake.test.ts deleted file mode 100644 index dee37f0f6b..0000000000 --- a/plugins/auth-backend/src/providers/microsoft/__testUtils__/fake.test.ts +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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 { FakeMicrosoftAPI } from './fake'; - -describe('FakeMicrosoftAPI', () => { - const api = new FakeMicrosoftAPI(); - - describe('#token', () => { - it('exchanges auth codes', () => { - const { access_token } = api.token( - new URLSearchParams({ - grant_type: 'authorization_code', - code: api.generateAuthCode('User.Read'), - }), - ); - - expect(api.tokenHasScope(access_token, 'User.Read')).toBe(true); - }); - - it('supports scopes for the first requested audience only', () => { - const { access_token } = api.token( - new URLSearchParams({ - grant_type: 'authorization_code', - code: api.generateAuthCode('someaudience/somescope User.Read'), - }), - ); - - expect(api.tokenHasScope(access_token, 'User.Read')).toBe(false); - }); - - it('special openid scopes do not count towards the 1-audience limit', () => { - const { access_token } = api.token( - new URLSearchParams({ - grant_type: 'authorization_code', - code: api.generateAuthCode('openid offline_access User.Read'), - }), - ); - - expect(api.tokenHasScope(access_token, 'User.Read')).toBe(true); - }); - - it('refreshes tokens', () => { - const { access_token } = api.token( - new URLSearchParams({ - grant_type: 'refresh_token', - refresh_token: api.generateRefreshToken( - 'email openid profile User.Read', - ), - }), - ); - - expect( - api.tokenHasScope(access_token, 'email openid profile User.Read'), - ).toBe(true); - }); - it('requires `openid` scope for ID token', () => { - const { id_token } = api.token( - new URLSearchParams({ - grant_type: 'authorization_code', - code: api.generateAuthCode('User.Read'), - }), - ); - - expect(id_token).toBeUndefined(); - }); - it('requires `offline_access` scope for refresh token', () => { - const { refresh_token } = api.token( - new URLSearchParams({ - grant_type: 'authorization_code', - code: api.generateAuthCode('User.Read'), - }), - ); - - expect(refresh_token).toBeUndefined(); - }); - }); -}); diff --git a/plugins/auth-backend/src/providers/microsoft/__testUtils__/fake.ts b/plugins/auth-backend/src/providers/microsoft/__testUtils__/fake.ts deleted file mode 100644 index 9b3ca09c57..0000000000 --- a/plugins/auth-backend/src/providers/microsoft/__testUtils__/fake.ts +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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 { decodeJwt } from 'jose'; - -type Claims = { aud: string; scp: string }; - -export class FakeMicrosoftAPI { - generateAccessToken(scope: string): string { - return this.tokenWithClaims(this.allClaimsForScope(scope)).access_token; - } - generateAuthCode(scope: string): string { - return this.encodeClaims(this.allClaimsForScope(scope)); - } - generateRefreshToken(scope: string): string { - return this.encodeClaims(this.allClaimsForScope(scope)); - } - token(formData: URLSearchParams): { - access_token: string; - scope: string; - refresh_token?: string; - id_token?: string; - } { - const scopeParameter = formData.get('scope'); - const claims = - (scopeParameter && this.allClaimsForScope(scopeParameter)) ?? - formData.get('grant_type') === 'refresh_token' - ? this.decodeClaims(formData.get('refresh_token')!) - : this.decodeClaims(formData.get('code')!); - return { - ...this.tokenWithClaims(claims), - ...(this.hasScope(claims, 'offline_access') && { - refresh_token: this.encodeClaims(claims), - }), - ...(this.hasScope(claims, 'openid') && { - id_token: 'header.e30K.microsoft', - }), - }; - } - tokenHasScope(token: string, scope: string): boolean { - const { aud, scp } = decodeJwt(token); - return this.hasScope({ aud: aud as string, scp: scp as string }, scope); - } - private tokenWithClaims(claims: Claims): { - access_token: string; - scope: string; - } { - const filteredClaims = { - ...claims, - scp: claims.scp - .split(' ') - .filter(s => s !== 'offline_access') - .join(' '), - }; - return { - access_token: `header.${Buffer.from( - JSON.stringify(filteredClaims), - ).toString('base64')}.signature`, - scope: this.scopeFromClaims(filteredClaims), - }; - } - private allClaimsForScope(scope: string): Claims { - const scopes = scope.split(' ').map(this.parseScope); - const firstAudience = scopes - .map(({ aud }) => aud) - .find(aud => aud !== 'openid'); - return { - aud: firstAudience ?? '00000003-0000-0000-c000-000000000000', - scp: scopes - .filter(({ aud }) => aud === 'openid' || aud === firstAudience) - .map(({ scp }) => scp) - .join(' '), - }; - } - // auth codes and refresh tokens in this fake system are base64-encoded JSON - // strings of claims - private encodeClaims(claims: Claims): string { - return Buffer.from(JSON.stringify(claims)).toString('base64'); - } - private decodeClaims(encoded: string): Claims { - return JSON.parse(Buffer.from(encoded, 'base64').toString()); - } - private hasScope(claims: Claims, scope: string): boolean { - return this.scopeFromClaims(claims).includes(scope); - } - private parseScope(s: string): Claims { - if (s.includes('/')) { - const [aud, scp] = s.split('/'); - return { aud, scp }; - } - switch (s) { - case 'email': - case 'openid': - case 'offline_access': - case 'profile': { - return { aud: 'openid', scp: s }; - } - default: - return { aud: '00000003-0000-0000-c000-000000000000', scp: s }; - } - } - private scopeFromClaims(claims: Claims): string { - return claims.scp - .split(' ') - .map(this.parseScope) - .map(({ aud, scp }) => - aud === 'openid' || - claims.aud === '00000003-0000-0000-c000-000000000000' - ? scp - : `${claims.aud}/${scp}`, - ) - .join(' '); - } -} diff --git a/plugins/auth-backend/src/providers/microsoft/provider.test.ts b/plugins/auth-backend/src/providers/microsoft/provider.test.ts deleted file mode 100644 index 7bbfd085d6..0000000000 --- a/plugins/auth-backend/src/providers/microsoft/provider.test.ts +++ /dev/null @@ -1,450 +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 { microsoft } from './provider'; -import { getVoidLogger } from '@backstage/backend-common'; -import { setupRequestMockHandlers } from '@backstage/backend-test-utils'; -import { ConfigReader } from '@backstage/config'; -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import { AuthProviderRouteHandlers, AuthResolverContext } from '../types'; -import express from 'express'; -import crypto from 'crypto'; -import { FakeMicrosoftAPI } from './__testUtils__/fake'; - -describe('MicrosoftAuthProvider', () => { - const nonce = 'AAAAAAAAAAAAAAAAAAAAAA=='; // 16 bytes of zeros in base64 - const state = Buffer.from( - `nonce=${encodeURIComponent(nonce)}&env=development`, - ).toString('hex'); - const mockBackstageToken = `header.${Buffer.from( - JSON.stringify({ sub: 'user:default/mock' }), - 'utf8', - ).toString('base64')}.backstage`; - - const server = setupServer(); - const microsoftApi = new FakeMicrosoftAPI(); - let provider: AuthProviderRouteHandlers; - let response: jest.Mocked<express.Response>; - - setupRequestMockHandlers(server); - - beforeEach(() => { - provider = microsoft.create({ - signIn: { - resolver: microsoft.resolvers.emailMatchingUserEntityAnnotation(), - }, - })({ - providerId: 'microsoft', - baseUrl: 'http://backstage.test/api/auth', - appUrl: 'http://backstage.test', - isOriginAllowed: _ => true, - globalConfig: { - baseUrl: 'http://backstage.test/api/auth', - appUrl: 'http://backstage.test', - isOriginAllowed: _ => true, - }, - config: new ConfigReader({ - development: { - tenantId: 'tenantId', - clientId: 'clientId', - clientSecret: 'clientSecret', - }, - }), - logger: getVoidLogger(), - resolverContext: { - issueToken: jest.fn(), - findCatalogUser: jest.fn(), - signInWithCatalogUser: async _ => ({ - token: mockBackstageToken, - }), - } as AuthResolverContext, - }) as AuthProviderRouteHandlers; - - server.use( - rest.post( - 'https://login.microsoftonline.com/tenantId/oauth2/v2.0/token', - async (req, res, ctx) => { - return res( - ctx.json({ - ...microsoftApi.token(new URLSearchParams(await req.text())), - token_type: 'Bearer', - expires_in: 123, - ext_expires_in: 123, - }), - ); - }, - ), - rest.get('https://graph.microsoft.com/v1.0/me/', (req, res, ctx) => { - if ( - !microsoftApi.tokenHasScope( - req.headers.get('authorization')!.replace(/^Bearer /, ''), - 'User.Read', - ) - ) { - return res(ctx.status(403)); - } - return res( - ctx.json({ - id: 'conrad', - displayName: 'Conrad', - surname: 'Ribas', - givenName: 'Francisco', - mail: 'conrad@example.com', - }), - ); - }), - rest.get( - 'https://graph.microsoft.com/v1.0/me/photos/*', - async (req, res, ctx) => { - if ( - !microsoftApi.tokenHasScope( - req.headers.get('authorization')!.replace(/^Bearer /, ''), - 'User.Read', - ) - ) { - return res(ctx.status(403)); - } - const imageBuffer = new Uint8Array([104, 111, 119, 100, 121]).buffer; - return res( - ctx.set('Content-Length', imageBuffer.byteLength.toString()), - ctx.set('Content-Type', 'image/jpeg'), - ctx.body(imageBuffer), - ); - }, - ), - ); - response = { - cookie: jest.fn(), - end: jest.fn(), - json: jest.fn(), - setHeader: jest.fn(), - status: jest.fn(), - } as unknown as jest.Mocked<express.Response>; - response.status.mockReturnValue(response); - }); - - describe('#start', () => { - const randomBytes = jest.spyOn( - crypto, - 'randomBytes', - ) as unknown as jest.MockedFunction<(size: number) => Buffer>; - - afterEach(() => { - randomBytes.mockRestore(); - }); - - it('redirects to authorize URL', async () => { - randomBytes.mockReturnValue(Buffer.from(nonce, 'base64')); - - await provider.start( - { - query: { - env: 'development', - scope: 'email openid profile User.Read', - }, - } as unknown as express.Request, - response, - ); - - expect(response.setHeader).toHaveBeenCalledWith( - 'Location', - 'https://login.microsoftonline.com/tenantId/oauth2/v2.0/authorize' + - '?response_type=code' + - `&redirect_uri=${encodeURIComponent( - 'http://backstage.test/api/auth/microsoft/handler/frame', - )}` + - `&scope=${encodeURIComponent('email openid profile User.Read')}` + - `&state=${state}` + - '&client_id=clientId', - ); - }); - }); - - describe('#handle', () => { - it('returns provider info and profile with photo data', async () => { - await provider.frameHandler( - { - query: { - env: 'development', - code: microsoftApi.generateAuthCode( - 'email openid profile User.Read', - ), - state, - }, - cookies: { - 'microsoft-nonce': nonce, - }, - } as unknown as express.Request, - response, - ); - - expect(response.end).toHaveBeenCalledWith( - expect.stringContaining( - encodeURIComponent( - JSON.stringify({ - type: 'authorization_response', - response: { - providerInfo: { - accessToken: microsoftApi.generateAccessToken( - 'email openid profile User.Read', - ), - scope: 'email openid profile User.Read', - expiresInSeconds: 123, - idToken: 'header.e30K.microsoft', - }, - profile: { - email: 'conrad@example.com', - picture: 'data:image/jpeg;base64,aG93ZHk=', - displayName: 'Conrad', - }, - backstageIdentity: { - token: mockBackstageToken, - identity: { - type: 'user', - userEntityRef: 'user:default/mock', - ownershipEntityRefs: [], - }, - }, - }, - }), - ), - ), - ); - }); - - it('returns access token for non-microsoft graph scope', async () => { - await provider.frameHandler( - { - query: { - env: 'development', - code: microsoftApi.generateAuthCode('aks-audience/user.read'), - state, - }, - cookies: { - 'microsoft-nonce': nonce, - }, - } as unknown as express.Request, - response, - ); - - expect(response.end).toHaveBeenCalledWith( - expect.stringContaining( - encodeURIComponent( - JSON.stringify({ - type: 'authorization_response', - response: { - providerInfo: { - accessToken: microsoftApi.generateAccessToken( - 'aks-audience/user.read', - ), - scope: 'aks-audience/user.read', - expiresInSeconds: 123, - }, - profile: {}, - }, - }), - ), - ), - ); - }); - - it('sets refresh token', async () => { - await provider.frameHandler( - { - query: { - env: 'development', - code: microsoftApi.generateAuthCode( - 'email offline_access openid profile User.Read', - ), - state, - }, - cookies: { - 'microsoft-nonce': nonce, - }, - } as unknown as express.Request, - response, - ); - - expect(response.cookie).toHaveBeenCalledWith( - 'microsoft-refresh-token', - microsoftApi.generateRefreshToken( - 'email offline_access openid profile User.Read', - ), - { - domain: 'backstage.test', - httpOnly: true, - maxAge: 86400000000, - path: '/api/auth/microsoft', - sameSite: 'lax', - secure: false, - }, - ); - }); - - it('omits photo data when fetching it fails', async () => { - server.use( - rest.get('https://graph.microsoft.com/v1.0/me/photos/*', (_, res) => - res.networkError('remote hung up'), - ), - ); - - await provider.frameHandler( - { - query: { - env: 'development', - code: microsoftApi.generateAuthCode( - 'email openid profile User.Read', - ), - state, - }, - cookies: { - 'microsoft-nonce': nonce, - }, - } as unknown as express.Request, - response, - ); - - expect(response.end).toHaveBeenCalledWith( - expect.stringContaining( - encodeURIComponent( - JSON.stringify({ - type: 'authorization_response', - response: { - providerInfo: { - accessToken: microsoftApi.generateAccessToken( - 'email openid profile User.Read', - ), - scope: 'email openid profile User.Read', - expiresInSeconds: 123, - idToken: 'header.e30K.microsoft', - }, - profile: { - email: 'conrad@example.com', - displayName: 'Conrad', - }, - backstageIdentity: { - token: mockBackstageToken, - identity: { - type: 'user', - userEntityRef: 'user:default/mock', - ownershipEntityRefs: [], - }, - }, - }, - }), - ), - ), - ); - }); - }); - - describe('#refresh', () => { - it('returns provider info and profile with photo data', async () => { - await provider.refresh!( - { - query: { - env: 'development', - scope: 'email openid profile User.Read', - }, - header: jest.fn(_ => 'XMLHttpRequest'), - cookies: { - 'microsoft-refresh-token': microsoftApi.generateRefreshToken( - 'email openid profile User.Read', - ), - }, - get: jest.fn(), - } as unknown as express.Request, - response, - ); - - expect(response.json).toHaveBeenCalledWith( - expect.objectContaining({ - providerInfo: { - accessToken: microsoftApi.generateAccessToken( - 'email openid profile User.Read', - ), - scope: 'email openid profile User.Read', - expiresInSeconds: 123, - idToken: 'header.e30K.microsoft', - }, - profile: { - email: 'conrad@example.com', - picture: 'data:image/jpeg;base64,aG93ZHk=', - displayName: 'Conrad', - }, - }), - ); - }); - - it('returns access token for non-microsoft graph scope', async () => { - await provider.refresh!( - { - query: { - env: 'development', - scope: 'aks-audience/user.read', - }, - header: jest.fn(_ => 'XMLHttpRequest'), - cookies: { - 'microsoft-refresh-token': microsoftApi.generateRefreshToken( - 'aks-audience/user.read', - ), - }, - get: jest.fn(), - } as unknown as express.Request, - response, - ); - - expect(response.json).toHaveBeenCalledWith({ - providerInfo: { - accessToken: microsoftApi.generateAccessToken( - 'aks-audience/user.read', - ), - expiresInSeconds: 123, - scope: 'aks-audience/user.read', - }, - profile: {}, - }); - }); - - it('returns backstage identity', async () => { - await provider.refresh!( - { - query: { - env: 'development', - scope: 'email openid profile User.Read', - }, - header: jest.fn(_ => 'XMLHttpRequest'), - cookies: { - 'microsoft-refresh-token': microsoftApi.generateRefreshToken( - 'email openid profile User.Read', - ), - }, - get: jest.fn(), - } as unknown as express.Request, - response, - ); - - expect(response.json).toHaveBeenCalledWith( - expect.objectContaining({ - backstageIdentity: expect.objectContaining({ - token: mockBackstageToken, - }), - }), - ); - }); - }); -}); diff --git a/plugins/auth-backend/src/providers/microsoft/provider.ts b/plugins/auth-backend/src/providers/microsoft/provider.ts index 8fc8459f10..8947c7432b 100644 --- a/plugins/auth-backend/src/providers/microsoft/provider.ts +++ b/plugins/auth-backend/src/providers/microsoft/provider.ts @@ -14,218 +14,25 @@ * limitations under the License. */ -import express from 'express'; -import passport from 'passport'; -import { Strategy as MicrosoftStrategy } from 'passport-microsoft'; -import { - encodeState, - OAuthAdapter, - OAuthEnvironmentHandler, - OAuthHandlers, - OAuthProviderOptions, - OAuthRefreshRequest, - OAuthResponse, - OAuthResult, - OAuthStartRequest, -} from '../../lib/oauth'; -import { - executeFetchUserProfileStrategy, - executeFrameHandlerStrategy, - executeRedirectStrategy, - executeRefreshTokenStrategy, - makeProfileInfo, - PassportDoneCallback, -} from '../../lib/passport'; -import { - AuthHandler, - OAuthStartResponse, - SignInResolver, - AuthResolverContext, -} from '../types'; +import { SignInResolver, AuthHandler } from '../types'; +import { OAuthResult } from '../../lib/oauth'; import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; import { - commonByEmailLocalPartResolver, - commonByEmailResolver, -} from '../resolvers'; -import { LoggerService } from '@backstage/backend-plugin-api'; -import fetch from 'node-fetch'; -import { decodeJwt } from 'jose'; -import { Profile as PassportProfile } from 'passport'; -import { BACKSTAGE_SESSION_EXPIRATION } from '../../lib/session'; - -type PrivateInfo = { - refreshToken: string; -}; - -type Options = OAuthProviderOptions & { - signInResolver?: SignInResolver<OAuthResult>; - authHandler: AuthHandler<OAuthResult>; - logger: LoggerService; - resolverContext: AuthResolverContext; - authorizationUrl?: string; - tokenUrl?: string; -}; - -export class MicrosoftAuthProvider implements OAuthHandlers { - private readonly _strategy: MicrosoftStrategy; - private readonly signInResolver?: SignInResolver<OAuthResult>; - private readonly authHandler: AuthHandler<OAuthResult>; - private readonly logger: LoggerService; - private readonly resolverContext: AuthResolverContext; - - constructor(options: Options) { - this.signInResolver = options.signInResolver; - this.authHandler = options.authHandler; - this.logger = options.logger; - this.resolverContext = options.resolverContext; - - this._strategy = new MicrosoftStrategy( - { - clientID: options.clientId, - clientSecret: options.clientSecret, - callbackURL: options.callbackUrl, - authorizationURL: options.authorizationUrl, - tokenURL: options.tokenUrl, - passReqToCallback: false, - skipUserProfile: ( - accessToken: string, - done: (err: unknown, skip: boolean) => void, - ) => { - done(null, this.skipUserProfile(accessToken)); - }, - }, - ( - accessToken: any, - refreshToken: any, - params: any, - fullProfile: passport.Profile, - done: PassportDoneCallback<OAuthResult, PrivateInfo>, - ) => { - done(undefined, { fullProfile, accessToken, params }, { refreshToken }); - }, - ); - } - - private skipUserProfile = (accessToken: string): boolean => { - const { aud, scp } = decodeJwt(accessToken); - const hasGraphReadScope = - aud === '00000003-0000-0000-c000-000000000000' && - (scp as string) - .split(' ') - .map(s => s.toLowerCase()) - .includes('user.read'); - return !hasGraphReadScope; - }; - - async start(req: OAuthStartRequest): Promise<OAuthStartResponse> { - return await executeRedirectStrategy(req, this._strategy, { - scope: req.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 { accessToken, refreshToken, params } = - await executeRefreshTokenStrategy( - this._strategy, - req.refreshToken, - req.scope, - ); - - return { - response: await this.handleResult({ - params, - accessToken, - ...(!this.skipUserProfile(accessToken) && { - fullProfile: await executeFetchUserProfileStrategy( - this._strategy, - accessToken, - ), - }), - }), - refreshToken, - }; - } - - private async handleResult(result: { - fullProfile?: PassportProfile; - params: { - id_token?: string; - scope: string; - expires_in: number; - }; - accessToken: string; - refreshToken?: string; - }): Promise<OAuthResponse> { - let profile = {}; - if (result.fullProfile) { - const photo = await this.getUserPhoto(result.accessToken); - result.fullProfile.photos = photo ? [{ value: photo }] : undefined; - ({ profile } = await this.authHandler( - result as OAuthResult, - this.resolverContext, - )); - } - - const expiresInSeconds = - result.params.expires_in === undefined - ? BACKSTAGE_SESSION_EXPIRATION - : Math.min(result.params.expires_in, BACKSTAGE_SESSION_EXPIRATION); - - return { - providerInfo: { - accessToken: result.accessToken, - scope: result.params.scope, - expiresInSeconds, - ...{ idToken: result.params.id_token }, - }, - profile, - ...(result.fullProfile && - this.signInResolver && { - backstageIdentity: await this.signInResolver( - { result: result as OAuthResult, profile }, - this.resolverContext, - ), - }), - }; - } - - private async getUserPhoto(accessToken: string): Promise<string | undefined> { - try { - const res = await fetch( - 'https://graph.microsoft.com/v1.0/me/photos/48x48/$value', - { - headers: { - Authorization: `Bearer ${accessToken}`, - }, - }, - ); - const data = await res.buffer(); - - return `data:image/jpeg;base64,${data.toString('base64')}`; - } catch (error) { - this.logger.warn( - `Could not retrieve user profile photo from Microsoft Graph API: ${error}`, - ); - return undefined; - } - } -} + commonSignInResolvers, + createOAuthProviderFactory, +} from '@backstage/plugin-auth-node'; +import { + adaptLegacyOAuthHandler, + adaptLegacyOAuthSignInResolver, + adaptOAuthSignInResolverToLegacy, +} from '../../lib/legacy'; +import { + microsoftAuthenticator, + microsoftSignInResolvers, +} from '@backstage/plugin-auth-backend-module-microsoft-provider'; /** - * Auth provider integration for Microsoft auth + * Auth provider integration for GitLab auth * * @public */ @@ -241,75 +48,21 @@ export const microsoft = createAuthProviderIntegration({ * 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<OAuthResult>; }; }) { - return ({ providerId, globalConfig, config, logger, resolverContext }) => - OAuthEnvironmentHandler.mapConfig(config, envConfig => { - const clientId = envConfig.getString('clientId'); - const clientSecret = envConfig.getString('clientSecret'); - const tenantId = envConfig.getString('tenantId'); - - const customCallbackUrl = envConfig.getOptionalString('callbackUrl'); - const callbackUrl = - customCallbackUrl || - `${globalConfig.baseUrl}/${providerId}/handler/frame`; - const authorizationUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/authorize`; - const tokenUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`; - - const authHandler: AuthHandler<OAuthResult> = options?.authHandler - ? options.authHandler - : async ({ fullProfile, params }) => ({ - profile: makeProfileInfo(fullProfile ?? {}, params.id_token), - }); - - const provider = new MicrosoftAuthProvider({ - clientId, - clientSecret, - callbackUrl, - authorizationUrl, - tokenUrl, - authHandler, - signInResolver: options?.signIn?.resolver, - logger, - resolverContext, - }); - - return OAuthAdapter.fromConfig(globalConfig, provider, { - providerId, - callbackUrl, - }); - }); - }, - 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 `microsoft.com/email` annotation. - */ - emailMatchingUserEntityAnnotation(): SignInResolver<OAuthResult> { - return async (info, ctx) => { - const { profile } = info; - - if (!profile.email) { - throw new Error('Microsoft profile contained no email'); - } - - return ctx.signInWithCatalogUser({ - annotations: { - 'microsoft.com/email': profile.email, - }, - }); - }; - }, + return createOAuthProviderFactory({ + authenticator: microsoftAuthenticator, + profileTransform: adaptLegacyOAuthHandler(options?.authHandler), + signInResolver: adaptLegacyOAuthSignInResolver(options?.signIn?.resolver), + }); }, + resolvers: adaptOAuthSignInResolverToLegacy({ + emailLocalPartMatchingUserEntityName: + commonSignInResolvers.emailLocalPartMatchingUserEntityName(), + emailMatchingUserEntityProfileEmail: + commonSignInResolvers.emailMatchingUserEntityProfileEmail(), + emailMatchingUserEntityAnnotation: + microsoftSignInResolvers.emailMatchingUserEntityAnnotation(), + }), }); diff --git a/plugins/auth-backend/src/providers/oidc/provider.ts b/plugins/auth-backend/src/providers/oidc/provider.ts index 7638027b01..b6608aebbd 100644 --- a/plugins/auth-backend/src/providers/oidc/provider.ts +++ b/plugins/auth-backend/src/providers/oidc/provider.ts @@ -130,6 +130,9 @@ export class OidcAuthProvider implements OAuthHandlers { if (!tokenset.access_token) { throw new Error('Refresh failed'); } + if (!tokenset.scope) { + tokenset.scope = req.scope; + } const userinfo = await client.userinfo(tokenset.access_token); return { diff --git a/plugins/auth-backend/src/service/standaloneServer.ts b/plugins/auth-backend/src/service/standaloneServer.ts index abda3a341c..834305553b 100644 --- a/plugins/auth-backend/src/service/standaloneServer.ts +++ b/plugins/auth-backend/src/service/standaloneServer.ts @@ -18,13 +18,13 @@ import { createServiceBuilder, loadBackendConfig, ServerTokenManager, - SingleHostDiscovery, - useHotMemoize, + HostDiscovery, + DatabaseManager, } from '@backstage/backend-common'; import { Server } from 'http'; -import Knex from 'knex'; import { LoggerService } from '@backstage/backend-plugin-api'; import { createRouter } from './router'; +import { ConfigReader } from '@backstage/config'; export interface ServerOptions { logger: LoggerService; @@ -35,29 +35,22 @@ export async function startStandaloneServer( ): Promise<Server> { const logger = options.logger.child({ service: 'auth-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); - const discovery = SingleHostDiscovery.fromConfig(config); + const discovery = HostDiscovery.fromConfig(config); - const database = useHotMemoize(module, () => { - const knex = Knex({ - client: 'better-sqlite3', - connection: ':memory:', - useNullAsDefault: true, - }); - knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { - resource.run('PRAGMA foreign_keys = ON', () => {}); - }); - return knex; - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('auth'); logger.debug('Starting application server...'); const router = await createRouter({ logger, config, - database: { - async getClient() { - return database; - }, - }, + database, discovery, tokenManager: ServerTokenManager.noop(), }); diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index 2dcd93dc51..b20ddd7697 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-auth-node +## 0.4.0 + +### Minor Changes + +- 6f142d5356: **BREAKING**: The recently introduced `ProxyAuthenticator.initialize()` method is no longer `async` to match the way the OAuth equivalent is implemented. + +### Patch Changes + +- 6c2b0793bf: Fix for persisted scopes not being properly restored on sign-in. +- 8b8b1d23ae: Fixed cookie persisted scope not returned in OAuth refresh handler response. +- ae34255836: Adding optional audience parameter to OAuthState type declaration +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.4.0-next.2 + +### Minor Changes + +- 6f142d5356: **BREAKING**: The recently introduced `ProxyAuthenticator.initialize()` method is no longer `async` to match the way the OAuth equivalent is implemented. + +### Patch Changes + +- 8b8b1d23ae: Fixed cookie persisted scope not returned in OAuth refresh handler response. +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + ## 0.3.2-next.1 ### Patch Changes diff --git a/plugins/auth-node/api-report.md b/plugins/auth-node/api-report.md index a782847d7a..4b1a8a1f27 100644 --- a/plugins/auth-node/api-report.md +++ b/plugins/auth-node/api-report.md @@ -399,6 +399,7 @@ export type OAuthState = { scope?: string; redirectUrl?: string; flow?: string; + audience?: string; }; // @public (undocumented) @@ -550,7 +551,7 @@ export interface ProxyAuthenticator<TContext, TResult> { // (undocumented) defaultProfileTransform: ProfileTransform<TResult>; // (undocumented) - initialize(ctx: { config: Config }): Promise<TContext>; + initialize(ctx: { config: Config }): TContext; } // @public (undocumented) diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index 91ae1b5e6a..bf2257c942 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.3.2-next.1", + "version": "0.4.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/auth-node/src/oauth/state.ts b/plugins/auth-node/src/oauth/state.ts index fc747d08a5..28f7d2fd2e 100644 --- a/plugins/auth-node/src/oauth/state.ts +++ b/plugins/auth-node/src/oauth/state.ts @@ -29,6 +29,7 @@ export type OAuthState = { scope?: string; redirectUrl?: string; flow?: string; + audience?: string; }; /** @public */ diff --git a/plugins/auth-node/src/proxy/types.ts b/plugins/auth-node/src/proxy/types.ts index 969b022abb..0f52feaac4 100644 --- a/plugins/auth-node/src/proxy/types.ts +++ b/plugins/auth-node/src/proxy/types.ts @@ -21,7 +21,7 @@ import { ProfileTransform } from '../types'; /** @public */ export interface ProxyAuthenticator<TContext, TResult> { defaultProfileTransform: ProfileTransform<TResult>; - initialize(ctx: { config: Config }): Promise<TContext>; + initialize(ctx: { config: Config }): TContext; authenticate( options: { req: Request }, ctx: TContext, diff --git a/plugins/azure-devops-backend/CHANGELOG.md b/plugins/azure-devops-backend/CHANGELOG.md index f38133089c..605bc9c81c 100644 --- a/plugins/azure-devops-backend/CHANGELOG.md +++ b/plugins/azure-devops-backend/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-azure-devops-backend +## 0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-devops-common@0.3.1 + +## 0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-azure-devops-common@0.3.1 + ## 0.4.2-next.1 ### Patch Changes diff --git a/plugins/azure-devops-backend/package.json b/plugins/azure-devops-backend/package.json index 1da72ae8dc..0186a9268b 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.2-next.1", + "version": "0.4.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-devops/CHANGELOG.md b/plugins/azure-devops/CHANGELOG.md index eee90fe4b2..1277fa0f1e 100644 --- a/plugins/azure-devops/CHANGELOG.md +++ b/plugins/azure-devops/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-azure-devops +## 0.3.7 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-azure-devops-common@0.3.1 + +## 0.3.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-azure-devops-common@0.3.1 + ## 0.3.7-next.1 ### Patch Changes diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index f47811bf58..7b5d8ee97a 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.7-next.1", + "version": "0.3.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -54,9 +54,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/azure-sites-backend/CHANGELOG.md b/plugins/azure-sites-backend/CHANGELOG.md index fe92430af1..203b9bab9c 100644 --- a/plugins/azure-sites-backend/CHANGELOG.md +++ b/plugins/azure-sites-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-azure-sites-backend +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + - @backstage/plugin-azure-sites-common@0.1.1 + +## 0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-azure-sites-common@0.1.1 + ## 0.1.15-next.1 ### Patch Changes diff --git a/plugins/azure-sites-backend/package.json b/plugins/azure-sites-backend/package.json index d1c9c6c2b7..aa5d700be2 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.15-next.1", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/azure-sites/CHANGELOG.md b/plugins/azure-sites/CHANGELOG.md index 3f044f2243..1d96a10e10 100644 --- a/plugins/azure-sites/CHANGELOG.md +++ b/plugins/azure-sites/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-azure-sites +## 0.1.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-azure-sites-common@0.1.1 + +## 0.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-azure-sites-common@0.1.1 + ## 0.1.14-next.1 ### Patch Changes diff --git a/plugins/azure-sites/package.json b/plugins/azure-sites/package.json index d7a4826be1..c00f1f21af 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.14-next.1", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -47,8 +47,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -56,9 +56,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/badges-backend/CHANGELOG.md b/plugins/badges-backend/CHANGELOG.md index 3081811eca..3bf44d0960 100644 --- a/plugins/badges-backend/CHANGELOG.md +++ b/plugins/badges-backend/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-badges-backend +## 0.3.3 + +### Patch Changes + +- 817f2acbb1: Make sure the default badge factory is used if nothing is defined +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + +## 0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + ## 0.3.2-next.1 ### Patch Changes diff --git a/plugins/badges-backend/package.json b/plugins/badges-backend/package.json index 4137092f17..fb2ab72985 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.2-next.1", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/badges-backend/src/service/router-obfuscated.test.ts b/plugins/badges-backend/src/service/router-obfuscated.test.ts index 3c9ec0d2b6..49d0368c7f 100644 --- a/plugins/badges-backend/src/service/router-obfuscated.test.ts +++ b/plugins/badges-backend/src/service/router-obfuscated.test.ts @@ -20,7 +20,7 @@ import { getVoidLogger, PluginEndpointDiscovery, ServerTokenManager, - SingleHostDiscovery, + HostDiscovery, } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; import type { Entity } from '@backstage/catalog-model'; @@ -138,7 +138,7 @@ describe('createRouter', () => { }; beforeAll(async () => { - discovery = SingleHostDiscovery.fromConfig(config); + discovery = HostDiscovery.fromConfig(config); const tokenManager = ServerTokenManager.noop(); const router = await createRouter({ badgeBuilder, diff --git a/plugins/badges-backend/src/service/router.test.ts b/plugins/badges-backend/src/service/router.test.ts index 2ecae6b452..6ccb8e3be7 100644 --- a/plugins/badges-backend/src/service/router.test.ts +++ b/plugins/badges-backend/src/service/router.test.ts @@ -20,7 +20,7 @@ import { getVoidLogger, PluginEndpointDiscovery, ServerTokenManager, - SingleHostDiscovery, + HostDiscovery, } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; import type { Entity } from '@backstage/catalog-model'; @@ -113,7 +113,7 @@ describe('createRouter', () => { }, ); - discovery = SingleHostDiscovery.fromConfig(config); + discovery = HostDiscovery.fromConfig(config); const tokenManager = ServerTokenManager.noop(); const router = await createRouter({ badgeBuilder, diff --git a/plugins/badges-backend/src/service/standaloneServer.ts b/plugins/badges-backend/src/service/standaloneServer.ts index b07e1fa3b1..661d218edb 100644 --- a/plugins/badges-backend/src/service/standaloneServer.ts +++ b/plugins/badges-backend/src/service/standaloneServer.ts @@ -20,13 +20,13 @@ import { createServiceBuilder, loadBackendConfig, ServerTokenManager, - SingleHostDiscovery, - useHotMemoize, + HostDiscovery, + DatabaseManager, } from '@backstage/backend-common'; import { createRouter } from './router'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { DatabaseBadgesStore } from '../database/badgesStore'; -import Knex from 'knex'; +import { ConfigReader } from '@backstage/config'; export interface ServerOptions { port: number; @@ -39,14 +39,15 @@ export async function startStandaloneServer( ): Promise<Server> { const logger = options.logger.child({ service: 'badges-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); - const discovery = SingleHostDiscovery.fromConfig(config); - const database = useHotMemoize(module, () => { - return Knex({ - client: 'better-sqlite3', - connection: ':memory:', - useNullAsDefault: true, - }); - }); + const discovery = HostDiscovery.fromConfig(config); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('badges'); logger.debug('Creating application...'); @@ -70,9 +71,7 @@ export async function startStandaloneServer( tokenManager, logger, identity, - badgeStore: await DatabaseBadgesStore.create({ - database: { getClient: async () => database }, - }), + badgeStore: await DatabaseBadgesStore.create({ database }), }); let service = createServiceBuilder(module) diff --git a/plugins/badges/CHANGELOG.md b/plugins/badges/CHANGELOG.md index c20dd1af3e..7ba4750487 100644 --- a/plugins/badges/CHANGELOG.md +++ b/plugins/badges/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-badges +## 0.2.49 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.2.49-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.2.49-next.1 ### Patch Changes diff --git a/plugins/badges/package.json b/plugins/badges/package.json index d0565cdaf9..6cb8fa7642 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.49-next.1", + "version": "0.2.49", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -52,7 +52,7 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/jest-dom": "^5.16.5" + "@testing-library/jest-dom": "^6.0.0" }, "files": [ "dist" diff --git a/plugins/bazaar-backend/CHANGELOG.md b/plugins/bazaar-backend/CHANGELOG.md index 3f3bfb6eaf..f5df21413d 100644 --- a/plugins/bazaar-backend/CHANGELOG.md +++ b/plugins/bazaar-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-bazaar-backend +## 0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## 0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.3.2-next.1 ### Patch Changes diff --git a/plugins/bazaar-backend/package.json b/plugins/bazaar-backend/package.json index 28358525ee..3fdfa32a7f 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.2-next.1", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/bazaar-backend/src/service/standaloneServer.ts b/plugins/bazaar-backend/src/service/standaloneServer.ts index a50e350f39..c222777aae 100644 --- a/plugins/bazaar-backend/src/service/standaloneServer.ts +++ b/plugins/bazaar-backend/src/service/standaloneServer.ts @@ -15,15 +15,15 @@ */ import { + DatabaseManager, createServiceBuilder, loadBackendConfig, - useHotMemoize, } from '@backstage/backend-common'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { Server } from 'http'; import { Logger } from 'winston'; import { createRouter } from './router'; -import knexFactory from 'knex'; +import { ConfigReader } from '@backstage/config'; export interface ServerOptions { port: number; @@ -37,23 +37,18 @@ export async function startStandaloneServer( const logger = options.logger.child({ service: 'bazaar-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); - const db = useHotMemoize(module, () => { - const knex = knexFactory({ - client: 'better-sqlite3', - connection: ':memory:', - useNullAsDefault: true, - }); - - knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { - resource.run('PRAGMA foreign_keys = ON', () => {}); - }); - - return knex; - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('bazaar'); const router = await createRouter({ logger, - database: { getClient: async () => db }, + database, config: config, identity: {} as IdentityApi, }); diff --git a/plugins/bazaar/CHANGELOG.md b/plugins/bazaar/CHANGELOG.md index d7c48b8802..e39456be88 100644 --- a/plugins/bazaar/CHANGELOG.md +++ b/plugins/bazaar/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-bazaar +## 0.2.17 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/plugin-catalog@1.14.0 + - @backstage/cli@0.23.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + +## 0.2.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.23.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-catalog@1.14.0-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + ## 0.2.17-next.1 ### Patch Changes diff --git a/plugins/bazaar/package.json b/plugins/bazaar/package.json index 4a6ac9530d..ed3428d7f9 100644 --- a/plugins/bazaar/package.json +++ b/plugins/bazaar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-bazaar", - "version": "0.2.17-next.1", + "version": "0.2.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -43,7 +43,7 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", "@material-ui/pickers": "^3.3.10", - "@testing-library/jest-dom": "^5.10.1", + "@testing-library/jest-dom": "^6.0.0", "@types/react": "^16.13.1 || ^17.0.0", "luxon": "^3.0.0", "material-ui-search-bar": "^1.0.0", @@ -51,14 +51,14 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/dev-utils": "workspace:^", - "@testing-library/jest-dom": "^5.10.1" + "@testing-library/jest-dom": "^6.0.0" }, "files": [ "dist" diff --git a/plugins/bitbucket-cloud-common/CHANGELOG.md b/plugins/bitbucket-cloud-common/CHANGELOG.md index 439fda1b41..ce604a6ef5 100644 --- a/plugins/bitbucket-cloud-common/CHANGELOG.md +++ b/plugins/bitbucket-cloud-common/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-bitbucket-cloud-common +## 0.2.13 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1 + +## 0.2.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1-next.1 + ## 0.2.13-next.0 ### Patch Changes diff --git a/plugins/bitbucket-cloud-common/package.json b/plugins/bitbucket-cloud-common/package.json index 5a109f3fb5..9f0488749e 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.13-next.0", + "version": "0.2.13", "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 6a1c85393c..175d1c20b0 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-bitrise +## 0.1.52 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 0.1.52-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + ## 0.1.52-next.1 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index bc88d84191..023472669b 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.52-next.1", + "version": "0.1.52", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -46,8 +46,8 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -55,9 +55,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/recharts": "^1.8.15", "msw": "^1.0.0" diff --git a/plugins/bitrise/src/components/BitriseBuildDetailsDialog/BitriseBuildDetailsDialog.test.tsx b/plugins/bitrise/src/components/BitriseBuildDetailsDialog/BitriseBuildDetailsDialog.test.tsx index 7992e08f37..65efb9b64f 100644 --- a/plugins/bitrise/src/components/BitriseBuildDetailsDialog/BitriseBuildDetailsDialog.test.tsx +++ b/plugins/bitrise/src/components/BitriseBuildDetailsDialog/BitriseBuildDetailsDialog.test.tsx @@ -18,6 +18,7 @@ import React from 'react'; import { render } from '@testing-library/react'; import { BitriseBuildDetailsDialog } from './BitriseBuildDetailsDialog'; import { BitriseBuildResult } from '../../api/bitriseApi.model'; +import userEvent from '@testing-library/user-event'; jest.mock('../BitriseArtifactsComponent', () => ({ BitriseArtifactsComponent: (_props: { build: string }) => <>VISIBLE</>, @@ -48,7 +49,7 @@ describe('BitriseArtifactsComponent', () => { expect(rendered.queryByText('VISIBLE')).not.toBeInTheDocument(); - btn.click(); + await userEvent.click(btn); expect(rendered.getByText('VISIBLE')).toBeInTheDocument(); }); diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index cba33bfb38..26971186d6 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,46 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.3.0 + +### Minor Changes + +- 5abc2fd4d6: AwsEksClusterProcessor supports Entity callback function and passes in region when initialize EKS cluster + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## 0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-kubernetes-common@0.7.0-next.1 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/integration-aws-node@0.1.7-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/api-report.md b/plugins/catalog-backend-module-aws/api-report.md index 83b072061b..a7a3f6816a 100644 --- a/plugins/catalog-backend-module-aws/api-report.md +++ b/plugins/catalog-backend-module-aws/api-report.md @@ -8,7 +8,9 @@ import { AwsCredentialsManager } from '@backstage/integration-aws-node'; import { CatalogProcessor } from '@backstage/plugin-catalog-node'; import { CatalogProcessorEmit } from '@backstage/plugin-catalog-node'; import { CatalogProcessorParser } from '@backstage/plugin-catalog-node'; +import type { Cluster } from '@aws-sdk/client-eks'; import { Config } from '@backstage/config'; +import type { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-node'; import { EntityProviderConnection } from '@backstage/plugin-catalog-node'; import { LocationSpec } from '@backstage/plugin-catalog-common'; @@ -17,6 +19,12 @@ import { PluginTaskScheduler } from '@backstage/backend-tasks'; import { TaskRunner } from '@backstage/backend-tasks'; import { UrlReader } from '@backstage/backend-common'; +// @public +export const ANNOTATION_AWS_ACCOUNT_ID: string; + +// @public +export const ANNOTATION_AWS_ARN: string; + // @public export type AWSCredentialFactory = ( awsAccountId: string, @@ -27,14 +35,18 @@ export class AwsEKSClusterProcessor implements CatalogProcessor { constructor(options: { credentialsFactory?: AWSCredentialFactory; credentialsManager?: AwsCredentialsManager; + clusterEntityTransformer?: EksClusterEntityTransformer; }); // (undocumented) - static fromConfig(configRoot: Config): AwsEKSClusterProcessor; + static fromConfig( + configRoot: Config, + options?: { + clusterEntityTransformer?: EksClusterEntityTransformer; + }, + ): AwsEKSClusterProcessor; // (undocumented) getProcessorName(): string; // (undocumented) - normalizeName(name: string): string; - // (undocumented) readLocation( location: LocationSpec, _optional: boolean, @@ -93,4 +105,10 @@ export class AwsS3EntityProvider implements EntityProvider { // (undocumented) refresh(logger: Logger): Promise<void>; } + +// @public +export type EksClusterEntityTransformer = ( + cluster: Cluster, + accountId: string, +) => Promise<Entity>; ``` diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index c4891dd2b7..a8999430fa 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.2.8-next.1", + "version": "0.3.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-aws/src/constants.ts b/plugins/catalog-backend-module-aws/src/constants.ts new file mode 100644 index 0000000000..7756031ed7 --- /dev/null +++ b/plugins/catalog-backend-module-aws/src/constants.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. + */ + +/** + * Annotation for specifying AWS account id + * + * @public + */ +export const ANNOTATION_AWS_ACCOUNT_ID: string = 'amazonaws.com/account-id'; +/** + * Annotation for specifying AWS arn + * + * @public + */ +export const ANNOTATION_AWS_ARN: string = 'amazonaws.com/arn'; diff --git a/plugins/catalog-backend-module-aws/src/index.ts b/plugins/catalog-backend-module-aws/src/index.ts index 212308edaa..72ddc6386a 100644 --- a/plugins/catalog-backend-module-aws/src/index.ts +++ b/plugins/catalog-backend-module-aws/src/index.ts @@ -23,3 +23,4 @@ export * from './processors'; export * from './providers'; export * from './types'; +export * from './constants'; diff --git a/plugins/catalog-backend-module-aws/src/lib/defaultTransformers.ts b/plugins/catalog-backend-module-aws/src/lib/defaultTransformers.ts new file mode 100644 index 0000000000..9de79e9811 --- /dev/null +++ b/plugins/catalog-backend-module-aws/src/lib/defaultTransformers.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 { type Cluster } from '@aws-sdk/client-eks'; +import { + ANNOTATION_KUBERNETES_API_SERVER, + ANNOTATION_KUBERNETES_API_SERVER_CA, + ANNOTATION_KUBERNETES_AUTH_PROVIDER, +} from '@backstage/plugin-kubernetes-common'; +import type { EksClusterEntityTransformer } from '../processors/types'; +import { ANNOTATION_AWS_ACCOUNT_ID, ANNOTATION_AWS_ARN } from '../constants'; + +/** + * Default transformer for EKS Cluster to Resource Entity + * @public + */ +export const defaultEksClusterEntityTransformer: EksClusterEntityTransformer = + async (cluster: Cluster, accountId: string) => { + const { arn, endpoint, certificateAuthority, name } = cluster; + return { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Resource', + metadata: { + annotations: { + [ANNOTATION_AWS_ACCOUNT_ID]: accountId, + [ANNOTATION_AWS_ARN]: arn || '', + [ANNOTATION_KUBERNETES_API_SERVER]: endpoint || '', + [ANNOTATION_KUBERNETES_API_SERVER_CA]: + certificateAuthority?.data || '', + [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'aws', + }, + name: normalizeName(name as string), + namespace: 'default', + }, + spec: { + type: 'kubernetes-cluster', + owner: 'unknown', + }, + }; + }; + +function normalizeName(name: string): string { + return name + .trim() + .toLocaleLowerCase('en-US') + .replace(/[^a-zA-Z0-9\-]/g, '-'); +} diff --git a/plugins/catalog-backend-module-aws/src/lib/index.ts b/plugins/catalog-backend-module-aws/src/lib/index.ts new file mode 100644 index 0000000000..1dc70c98f3 --- /dev/null +++ b/plugins/catalog-backend-module-aws/src/lib/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './defaultTransformers'; diff --git a/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts b/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts index 4a19b9eb7f..a491dbab7d 100644 --- a/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts +++ b/plugins/catalog-backend-module-aws/src/processors/AwsEKSClusterProcessor.ts @@ -19,11 +19,6 @@ import { CatalogProcessorEmit, } from '@backstage/plugin-catalog-node'; import { LocationSpec } from '@backstage/plugin-catalog-common'; -import { - ANNOTATION_KUBERNETES_API_SERVER, - ANNOTATION_KUBERNETES_API_SERVER_CA, - ANNOTATION_KUBERNETES_AUTH_PROVIDER, -} from '@backstage/plugin-kubernetes-common'; import { EKS } from '@aws-sdk/client-eks'; import { AWSCredentialFactory } from '../types'; import { AwsCredentialIdentity, Provider } from '@aws-sdk/types'; @@ -33,8 +28,8 @@ import { } from '@backstage/integration-aws-node'; import { Config } from '@backstage/config'; -const ACCOUNTID_ANNOTATION: string = 'amazonaws.com/account-id'; -const ARN_ANNOTATION: string = 'amazonaws.com/arn'; +import type { EksClusterEntityTransformer } from './types'; +import { defaultEksClusterEntityTransformer } from '../lib'; /** * A processor for automatic discovery of resources from EKS clusters. Handles the @@ -46,34 +41,39 @@ const ARN_ANNOTATION: string = 'amazonaws.com/arn'; export class AwsEKSClusterProcessor implements CatalogProcessor { private credentialsFactory?: AWSCredentialFactory; private credentialsManager?: AwsCredentialsManager; + private readonly clusterEntityTransformer: EksClusterEntityTransformer; - static fromConfig(configRoot: Config): AwsEKSClusterProcessor { + static fromConfig( + configRoot: Config, + options?: { + clusterEntityTransformer?: EksClusterEntityTransformer; + }, + ): AwsEKSClusterProcessor { const awsCredentaislManager = DefaultAwsCredentialsManager.fromConfig(configRoot); return new AwsEKSClusterProcessor({ credentialsManager: awsCredentaislManager, + ...options, }); } constructor(options: { credentialsFactory?: AWSCredentialFactory; credentialsManager?: AwsCredentialsManager; + clusterEntityTransformer?: EksClusterEntityTransformer; }) { this.credentialsFactory = options.credentialsFactory; this.credentialsManager = options.credentialsManager; + + // If the callback function is not passed in, then default to the one upstream is using + this.clusterEntityTransformer = + options.clusterEntityTransformer || defaultEksClusterEntityTransformer; } getProcessorName(): string { return 'aws-eks'; } - normalizeName(name: string): string { - return name - .trim() - .toLocaleLowerCase('en-US') - .replace(/[^a-zA-Z0-9\-]/g, '-'); - } - async readLocation( location: LocationSpec, _optional: boolean, @@ -108,6 +108,7 @@ export class AwsEKSClusterProcessor implements CatalogProcessor { const eksClient = new EKS({ credentials, credentialDefaultProvider: providerFunction, + region, }); const clusters = await eksClient.listClusters({}); if (clusters.clusters === undefined) { @@ -119,27 +120,11 @@ export class AwsEKSClusterProcessor implements CatalogProcessor { .map(async describedClusterPromise => { const describedCluster = await describedClusterPromise; if (describedCluster.cluster) { - const entity = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Resource', - metadata: { - annotations: { - [ACCOUNTID_ANNOTATION]: accountId, - [ARN_ANNOTATION]: describedCluster.cluster.arn || '', - [ANNOTATION_KUBERNETES_API_SERVER]: - describedCluster.cluster.endpoint || '', - [ANNOTATION_KUBERNETES_API_SERVER_CA]: - describedCluster.cluster.certificateAuthority?.data || '', - [ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'aws', - }, - name: this.normalizeName(describedCluster.cluster.name as string), - namespace: 'default', - }, - spec: { - type: 'kubernetes-cluster', - owner: 'unknown', - }, - }; + const entity = await this.clusterEntityTransformer( + describedCluster.cluster, + accountId, + ); + emit({ type: 'entity', entity, diff --git a/plugins/catalog-backend-module-aws/src/processors/index.ts b/plugins/catalog-backend-module-aws/src/processors/index.ts index 63b8a47139..e5bf93ceaf 100644 --- a/plugins/catalog-backend-module-aws/src/processors/index.ts +++ b/plugins/catalog-backend-module-aws/src/processors/index.ts @@ -17,3 +17,4 @@ export { AwsEKSClusterProcessor } from './AwsEKSClusterProcessor'; export { AwsOrganizationCloudAccountProcessor } from './AwsOrganizationCloudAccountProcessor'; export { AwsS3DiscoveryProcessor } from './AwsS3DiscoveryProcessor'; +export * from './types'; diff --git a/plugins/catalog-backend-module-aws/src/processors/types.ts b/plugins/catalog-backend-module-aws/src/processors/types.ts new file mode 100644 index 0000000000..22e9e4982d --- /dev/null +++ b/plugins/catalog-backend-module-aws/src/processors/types.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 type { Cluster } from '@aws-sdk/client-eks'; +import type { Entity } from '@backstage/catalog-model'; + +/** + * Options for the EKS cluster entity callback function + * + * @public + */ +export type EksClusterEntityTransformer = ( + cluster: Cluster, + accountId: string, +) => Promise<Entity>; diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index 6d1613bf1e..315d39baab 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.1.25 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## 0.1.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + ## 0.1.24-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index f8849b4925..ef21110f7b 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.24-next.1", + "version": "0.1.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index 4a989d8214..7682992e01 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.1.21 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-bitbucket-cloud-common@0.2.13 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-events-node@0.2.15 + +## 0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-bitbucket-cloud-common@0.2.13-next.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-events-node@0.2.15-next.2 + ## 0.1.20-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 40f83d3717..ed10c8433e 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.20-next.1", + "version": "0.1.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index db98df3fc1..67ea880c96 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.1.19 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## 0.1.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.1.18-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index d86127555f..e0f395a1a2 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.18-next.1", + "version": "0.1.19", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md index 756ad9f1dd..cf7e871bc5 100644 --- a/plugins/catalog-backend-module-bitbucket/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-catalog-backend-module-bitbucket +## 0.2.21 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-bitbucket-cloud-common@0.2.13 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.2.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-bitbucket-cloud-common@0.2.13-next.1 + ## 0.2.20-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket/package.json b/plugins/catalog-backend-module-bitbucket/package.json index 41827dc369..a68cb1e674 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.20-next.1", + "version": "0.2.21", "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 0b50b8bf3b..c755f7a72b 100644 --- a/plugins/catalog-backend-module-gcp/CHANGELOG.md +++ b/plugins/catalog-backend-module-gcp/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-catalog-backend-module-gcp +## 0.1.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## 0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-kubernetes-common@0.7.0-next.1 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.1.5-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gcp/package.json b/plugins/catalog-backend-module-gcp/package.json index dc3ae7395d..70bf6f7b88 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.5-next.1", + "version": "0.1.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index cbfd993b9f..e55d30ed12 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.1.22 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## 0.1.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.1.21-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index 9690978a3b..576f772968 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.21-next.1", + "version": "0.1.22", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-github-org/.eslintrc.js b/plugins/catalog-backend-module-github-org/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/catalog-backend-module-github-org/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/catalog-backend-module-github-org/CHANGELOG.md b/plugins/catalog-backend-module-github-org/CHANGELOG.md new file mode 100644 index 0000000000..e0a24889c4 --- /dev/null +++ b/plugins/catalog-backend-module-github-org/CHANGELOG.md @@ -0,0 +1,33 @@ +# @backstage/plugin-catalog-backend-module-github-org + +## 0.1.0 + +### Minor Changes + +- c101e683d5: Added `catalogModuleGithubOrgEntityProvider` to ingest users and teams from multiple Github organizations. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-backend-module-github@0.4.4 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## 0.1.0-next.0 + +### Minor Changes + +- c101e683d5: Added `catalogModuleGithubOrgEntityProvider` to ingest users and teams from multiple Github organizations. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-catalog-backend-module-github@0.4.4-next.2 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 diff --git a/plugins/catalog-backend-module-github-org/README.md b/plugins/catalog-backend-module-github-org/README.md new file mode 100644 index 0000000000..6b03dc299d --- /dev/null +++ b/plugins/catalog-backend-module-github-org/README.md @@ -0,0 +1,5 @@ +# @backstage/plugin-catalog-backend-module-github-org + +The github-org backend module for the catalog plugin. + +_This plugin was created through the Backstage CLI_ diff --git a/plugins/catalog-backend-module-github-org/api-report.md b/plugins/catalog-backend-module-github-org/api-report.md new file mode 100644 index 0000000000..e39c98182c --- /dev/null +++ b/plugins/catalog-backend-module-github-org/api-report.md @@ -0,0 +1,30 @@ +## API Report File for "@backstage/plugin-catalog-backend-module-github-org" + +> 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 { ExtensionPoint } from '@backstage/backend-plugin-api'; +import { GithubMultiOrgEntityProvider } from '@backstage/plugin-catalog-backend-module-github'; +import { TeamTransformer } from '@backstage/plugin-catalog-backend-module-github'; +import { UserTransformer } from '@backstage/plugin-catalog-backend-module-github'; + +// @public +const catalogModuleGithubOrgEntityProvider: () => BackendFeature; +export default catalogModuleGithubOrgEntityProvider; + +export { GithubMultiOrgEntityProvider }; + +// @public +export interface GithubOrgEntityProviderTransformsExtensionPoint { + setTeamTransformer(transformer: TeamTransformer): void; + setUserTransformer(transformer: UserTransformer): void; +} + +// @public +export const githubOrgEntityProviderTransformsExtensionPoint: ExtensionPoint<GithubOrgEntityProviderTransformsExtensionPoint>; + +export { TeamTransformer }; + +export { UserTransformer }; +``` diff --git a/plugins/catalog-backend-module-github-org/catalog-info.yaml b/plugins/catalog-backend-module-github-org/catalog-info.yaml new file mode 100644 index 0000000000..a785727e76 --- /dev/null +++ b/plugins/catalog-backend-module-github-org/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-catalog-backend-module-github-org + title: '@backstage/plugin-catalog-backend-module-github-org' + description: A Backstage catalog backend module that ingests users and teams from multiple Github organizations +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: catalog-maintainers diff --git a/plugins/catalog-backend-module-github-org/package.json b/plugins/catalog-backend-module-github-org/package.json new file mode 100644 index 0000000000..7ad96c65e2 --- /dev/null +++ b/plugins/catalog-backend-module-github-org/package.json @@ -0,0 +1,41 @@ +{ + "name": "@backstage/plugin-catalog-backend-module-github-org", + "description": "The github-org backend module for the catalog plugin.", + "version": "0.1.0", + "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/backend-tasks": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/plugin-catalog-backend-module-github": "workspace:^", + "@backstage/plugin-catalog-node": "workspace:^" + }, + "devDependencies": { + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "luxon": "^3.0.0" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/catalog-backend-module-github-org/src/index.ts b/plugins/catalog-backend-module-github-org/src/index.ts new file mode 100644 index 0000000000..03d22b1a79 --- /dev/null +++ b/plugins/catalog-backend-module-github-org/src/index.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. + */ + +/** + * The github-org backend module for the catalog plugin. + * + * @packageDocumentation + */ +export { + catalogModuleGithubOrgEntityProvider as default, + type GithubOrgEntityProviderTransformsExtensionPoint, + githubOrgEntityProviderTransformsExtensionPoint, +} from './module'; +/** + * + * TODO(djamaile): GithubMultiOrgEntityProvider should be mirgated over to this module. + * Afterwards, mark it as deprecated in catalog-backend-module-github and export them there from this module. + */ +export { + GithubMultiOrgEntityProvider, + type TeamTransformer, + type UserTransformer, +} from '@backstage/plugin-catalog-backend-module-github'; diff --git a/plugins/catalog-backend-module-github/src/module/catalogModuleGithubOrgEntityProvider.test.ts b/plugins/catalog-backend-module-github-org/src/module.test.ts similarity index 96% rename from plugins/catalog-backend-module-github/src/module/catalogModuleGithubOrgEntityProvider.test.ts rename to plugins/catalog-backend-module-github-org/src/module.test.ts index 1b8b115a96..9f8e9119d9 100644 --- a/plugins/catalog-backend-module-github/src/module/catalogModuleGithubOrgEntityProvider.test.ts +++ b/plugins/catalog-backend-module-github-org/src/module.test.ts @@ -19,7 +19,7 @@ import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; import { EntityProvider } from '@backstage/plugin-catalog-node'; import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; import { Duration } from 'luxon'; -import { catalogModuleGithubOrgEntityProvider } from './catalogModuleGithubOrgEntityProvider'; +import { catalogModuleGithubOrgEntityProvider } from './module'; describe('catalogModuleGithubOrgEntityProvider', () => { it('should register provider at the catalog extension point', async () => { diff --git a/plugins/catalog-backend-module-github/src/module/catalogModuleGithubOrgEntityProvider.ts b/plugins/catalog-backend-module-github-org/src/module.ts similarity index 97% rename from plugins/catalog-backend-module-github/src/module/catalogModuleGithubOrgEntityProvider.ts rename to plugins/catalog-backend-module-github-org/src/module.ts index 4838be54e1..e510464bb7 100644 --- a/plugins/catalog-backend-module-github/src/module/catalogModuleGithubOrgEntityProvider.ts +++ b/plugins/catalog-backend-module-github-org/src/module.ts @@ -35,7 +35,7 @@ import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/ /** * Interface for {@link githubOrgEntityProviderTransformsExtensionPoint}. * - * @alpha + * @public */ export interface GithubOrgEntityProviderTransformsExtensionPoint { /** @@ -52,9 +52,9 @@ export interface GithubOrgEntityProviderTransformsExtensionPoint { } /** - * Extension point for runtime configuration of {@link catalogModuleGithubOrgEntityProvider}. + * Extension point for runtime configuration of catalogModuleGithubOrgEntityProvider. * - * @alpha + * @public */ export const githubOrgEntityProviderTransformsExtensionPoint = createExtensionPoint<GithubOrgEntityProviderTransformsExtensionPoint>({ @@ -64,7 +64,7 @@ export const githubOrgEntityProviderTransformsExtensionPoint = /** * Registers the `GithubMultiOrgEntityProvider` with the catalog processing extension point. * - * @alpha + * @public */ export const catalogModuleGithubOrgEntityProvider = createBackendModule({ pluginId: 'catalog', diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index 1cb45ad261..21e8ad0e1b 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,46 @@ # @backstage/plugin-catalog-backend-module-github +## 0.4.4 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- 0b55f773a7: Removed some unused dependencies +- 4f16e60e6d: Request slightly smaller pages of data from GitHub +- b4b1cbf9fa: Make `defaultUserTransformer` resolve to `UserEntity` instead of `Entity` +- c101e683d5: Removed `catalogModuleGithubOrgEntityProvider`. Import from `@backstage/plugin-catalog-backend-module-github-org` instead. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-events-node@0.2.15 + +## 0.4.4-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- c101e683d5: Removed `catalogModuleGithubOrgEntityProvider`. Import from `@backstage/plugin-catalog-backend-module-github-org` instead. +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-catalog-backend@1.14.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-events-node@0.2.15-next.2 + ## 0.4.3-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/alpha-api-report.md b/plugins/catalog-backend-module-github/alpha-api-report.md index 3bf72c449b..cd5344f728 100644 --- a/plugins/catalog-backend-module-github/alpha-api-report.md +++ b/plugins/catalog-backend-module-github/alpha-api-report.md @@ -4,25 +4,10 @@ ```ts import { BackendFeature } from '@backstage/backend-plugin-api'; -import { ExtensionPoint } from '@backstage/backend-plugin-api'; -import { TeamTransformer } from '@backstage/plugin-catalog-backend-module-github'; -import { UserTransformer } from '@backstage/plugin-catalog-backend-module-github'; // @alpha const catalogModuleGithubEntityProvider: () => BackendFeature; export default catalogModuleGithubEntityProvider; -// @alpha -export const catalogModuleGithubOrgEntityProvider: () => BackendFeature; - -// @alpha -export interface GithubOrgEntityProviderTransformsExtensionPoint { - setTeamTransformer(transformer: TeamTransformer): void; - setUserTransformer(transformer: UserTransformer): void; -} - -// @alpha -export const githubOrgEntityProviderTransformsExtensionPoint: ExtensionPoint<GithubOrgEntityProviderTransformsExtensionPoint>; - // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 8f22af5f62..f2c321f84a 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.3-next.1", + "version": "0.4.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -51,13 +51,11 @@ "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", - "@backstage/errors": "workspace:^", "@backstage/integration": "workspace:^", "@backstage/plugin-catalog-backend": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", "@backstage/plugin-events-node": "workspace:^", - "@backstage/types": "workspace:^", "@octokit/graphql": "^5.0.0", "@octokit/rest": "^19.0.3", "git-url-parse": "^13.0.0", diff --git a/plugins/catalog-backend-module-github/src/lib/github.ts b/plugins/catalog-backend-module-github/src/lib/github.ts index 073e6c1587..cf6b400443 100644 --- a/plugins/catalog-backend-module-github/src/lib/github.ts +++ b/plugins/catalog-backend-module-github/src/lib/github.ts @@ -462,7 +462,7 @@ export async function getOrganizationRepositories( query repositories($org: String!, $catalogPathRef: String!, $cursor: String) { repositoryOwner(login: $org) { login - repositories(first: 100, after: $cursor) { + repositories(first: 50, after: $cursor) { nodes { name catalogInfoFile: object(expression: $catalogPathRef) { diff --git a/plugins/catalog-backend-module-github/src/module/index.ts b/plugins/catalog-backend-module-github/src/module/index.ts index 7e8a214ca3..9c9331763c 100644 --- a/plugins/catalog-backend-module-github/src/module/index.ts +++ b/plugins/catalog-backend-module-github/src/module/index.ts @@ -15,8 +15,3 @@ */ export { catalogModuleGithubEntityProvider as default } from './catalogModuleGithubEntityProvider'; -export { - catalogModuleGithubOrgEntityProvider, - githubOrgEntityProviderTransformsExtensionPoint, - type GithubOrgEntityProviderTransformsExtensionPoint, -} from './catalogModuleGithubOrgEntityProvider'; diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index 6a3633aa8a..5378ba5448 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,67 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.3.3 + +### Patch Changes + +- 4f70fdfc93: fix: use REST API to get root group memberships for GitLab SaaS users listing + + This API is the only one that shows `email` field for enterprise users and + allows to filter out bot users not using a license using the `is_using_seat` + field. + + We also added the annotation `gitlab.com/saml-external-uid` taking the value + of `group_saml_identity.extern_uid` of the `groups/:group-id/members` endpoint + response. This is useful in case you want to create a `SignInResolver` that + references the user with the id of your identity provider (e.g. OneLogin). + + ref: + + https://docs.gitlab.com/ee/user/enterprise_user/#get-users-email-addresses-through-the-api + https://docs.gitlab.com/ee/api/members.html#limitations + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- 0b55f773a7: Removed some unused dependencies +- 6ae7f12abb: Make sure the archived projects are skipped with the Gitlab API +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## 0.3.3-next.2 + +### Patch Changes + +- 4f70fdfc93: fix: use REST API to get root group memberships for GitLab SaaS users listing + + This API is the only one that shows `email` field for enterprise users and + allows to filter out bot users not using a license using the `is_using_seat` + field. + + We also added the annotation `gitlab.com/saml-external-uid` taking the value + of `group_saml_identity.extern_uid` of the `groups/:group-id/members` endpoint + response. This is useful in case you want to create a `SignInResolver` that + references the user with the id of your identity provider (e.g. OneLogin). + + ref: + + https://docs.gitlab.com/ee/user/enterprise_user/#get-users-email-addresses-through-the-api + https://docs.gitlab.com/ee/api/members.html#limitations + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.3.2-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index b3fc853c26..2c5966bb68 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.2-next.1", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -50,10 +50,8 @@ "@backstage/backend-tasks": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", - "@backstage/errors": "workspace:^", "@backstage/integration": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", - "@backstage/types": "workspace:^", "lodash": "^4.17.21", "node-fetch": "^2.6.7", "uuid": "^8.0.0", diff --git a/plugins/catalog-backend-module-gitlab/src/lib/client.test.ts b/plugins/catalog-backend-module-gitlab/src/lib/client.test.ts index dad126e3e4..99f6e7869b 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/client.test.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/client.test.ts @@ -421,7 +421,7 @@ describe('GitLabClient', () => { user: { id: 'gid://gitlab/User/1', username: 'user1', - commitEmail: 'user1@example.com', + publicEmail: 'user1@example.com', name: 'user1', state: 'active', webUrl: 'user1.com', @@ -525,7 +525,7 @@ describe('GitLabClient', () => { user: { id: 'gid://gitlab/User/1', username: 'user1', - commitEmail: 'user1@example.com', + publicEmail: 'user1@example.com', name: 'user1', state: 'active', webUrl: 'user1.com', @@ -538,7 +538,7 @@ describe('GitLabClient', () => { user: { id: 'gid://gitlab/User/2', username: 'user2', - commitEmail: 'user2@example.com', + publicEmail: 'user2@example.com', name: 'user2', state: 'active', webUrl: 'user2.com', @@ -772,7 +772,7 @@ describe('GitLabClient', () => { user: { id: 'gid://gitlab/User/1', username: 'user1', - commitEmail: 'user1@example.com', + publicEmail: 'user1@example.com', name: 'user1', state: 'active', webUrl: 'user1.com', diff --git a/plugins/catalog-backend-module-gitlab/src/lib/client.ts b/plugins/catalog-backend-module-gitlab/src/lib/client.ts index daf82245e8..722f079a21 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/client.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/client.ts @@ -91,6 +91,22 @@ export class GitLabClient { }); } + async listSaaSUsers( + groupPath: string, + options?: CommonListOptions, + ): Promise<PagedResponse<GitLabUser>> { + return this.pagedRequest( + `/groups/${encodeURIComponent(groupPath)}/members`, + { + ...options, + show_seat_info: true, + }, + ).then(resp => { + resp.items = resp.items.filter(user => user.is_using_seat); + return resp; + }); + } + async listGroups( options?: CommonListOptions, ): Promise<PagedResponse<GitLabGroup>> { @@ -205,7 +221,7 @@ export class GitLabClient { user { id username - commitEmail + publicEmail name state webUrl @@ -240,7 +256,7 @@ export class GitLabClient { const formattedUserResponse = { id: Number(userItem.user.id.replace(/^gid:\/\/gitlab\/User\//, '')), username: userItem.user.username, - email: userItem.user.commitEmail, + email: userItem.user.publicEmail, name: userItem.user.name, state: userItem.user.state, web_url: userItem.user.webUrl, diff --git a/plugins/catalog-backend-module-gitlab/src/lib/types.ts b/plugins/catalog-backend-module-gitlab/src/lib/types.ts index a339ac57e4..946317a11a 100644 --- a/plugins/catalog-backend-module-gitlab/src/lib/types.ts +++ b/plugins/catalog-backend-module-gitlab/src/lib/types.ts @@ -39,12 +39,17 @@ export type GitLabProject = { export type GitLabUser = { id: number; username: string; - email: string; + email?: string; name: string; state: string; web_url: string; avatar_url: string; groups?: GitLabGroup[]; + group_saml_identity?: GitLabGroupSamlIdentity; +}; + +export type GitLabGroupSamlIdentity = { + extern_uid: string; }; export type GitLabGroup = { @@ -64,7 +69,7 @@ export type GitLabGroupMembersResponse = { user: { id: string; username: string; - commitEmail: string; + publicEmail: string; name: string; state: string; webUrl: string; diff --git a/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.test.ts b/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.test.ts index ce00510140..ad930ea23d 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.test.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.test.ts @@ -548,46 +548,6 @@ describe('GitlabOrgDiscoveryEntityProvider', () => { }), ), ), - graphql - .link('https://gitlab.com/api/graphql') - .query('getGroupMembers', async (_, res, ctx) => - res( - ctx.data({ - group: { - groupMembers: { - nodes: [ - { - user: { - id: 'gid://gitlab/User/12', - username: 'testuser1', - commitEmail: 'testuser1@example.com', - state: 'active', - name: 'Test User 1', - webUrl: 'https://gitlab.com/testuser1', - avatarUrl: 'https://secure.gravatar.com/', - }, - }, - { - user: { - id: 'gid://gitlab/User/34', - username: 'testuser2', - commitEmail: 'testuser2@example.com', - state: 'active', - name: 'Test User 2', - webUrl: 'https://gitlab.com/testuser2', - avatarUrl: 'https://secure.gravatar.com/', - }, - }, - ], - pageInfo: { - endCursor: 'end', - hasNextPage: false, - }, - }, - }, - }), - ), - ), graphql .link('https://gitlab.com/api/graphql') .query('getGroupMembers', async (req, res, ctx) => @@ -608,6 +568,67 @@ describe('GitlabOrgDiscoveryEntityProvider', () => { }), ), ), + rest.get( + `https://gitlab.com/api/v4/groups/group1/members`, + (_req, res, ctx) => { + const response = [ + { + access_level: 30, + created_at: '2023-07-17T08:58:34.984Z', + expires_at: null, + id: 12, + username: 'testuser1', + name: 'Test User 1', + state: 'active', + avatar_url: 'https://secure.gravatar.com/', + web_url: 'https://gitlab.com/testuser1', + email: 'testuser1@example.com', + group_saml_identity: { + provider: 'group_saml', + extern_uid: '51', + saml_provider_id: 1, + }, + is_using_seat: true, + membership_state: 'active', + }, + { + access_level: 30, + created_at: '2023-07-19T08:58:34.984Z', + expires_at: null, + id: 34, + username: 'testuser2', + name: 'Test User 2', + state: 'active', + avatar_url: 'https://secure.gravatar.com/', + web_url: 'https://gitlab.com/testuser2', + email: 'testuser2@example.com', + group_saml_identity: { + provider: 'group_saml', + extern_uid: '52', + saml_provider_id: 1, + }, + is_using_seat: true, + membership_state: 'active', + }, + { + access_level: 50, + created_at: '2023-07-15T08:58:34.984Z', + expires_at: '2023-10-26', + id: 54, + username: 'group_100_bot_23dc8057bef66e05181f39be4652577c', + name: 'Token Bot', + state: 'active', + avatar_url: 'https://secure.gravatar.com/', + web_url: + 'https://gitlab.com/group_100_bot_23dc8057bef66e05181f39be4652577c', + group_saml_identity: null, + is_using_seat: false, + membership_state: 'active', + }, + ]; + return res(ctx.json(response)); + }, + ), ); await provider.connect(entityProviderConnection); @@ -630,11 +651,12 @@ describe('GitlabOrgDiscoveryEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://gitlab.com/testuser1', 'gitlab.com/user-login': 'https://gitlab.com/testuser1', + 'gitlab.com/saml-external-uid': '51', }, name: 'testuser1', }, spec: { - memberOf: ['group2', 'group3'], + memberOf: ['group2'], profile: { displayName: 'Test User 1', email: 'testuser1@example.com', @@ -655,11 +677,12 @@ describe('GitlabOrgDiscoveryEntityProvider', () => { 'backstage.io/managed-by-origin-location': 'url:https://gitlab.com/testuser2', 'gitlab.com/user-login': 'https://gitlab.com/testuser2', + 'gitlab.com/saml-external-uid': '52', }, name: 'testuser2', }, spec: { - memberOf: ['group2', 'group3'], + memberOf: ['group3'], profile: { displayName: 'Test User 2', email: 'testuser2@example.com', diff --git a/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts b/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts index fcf6a33a22..732f9f9fac 100644 --- a/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts +++ b/plugins/catalog-backend-module-gitlab/src/providers/GitlabOrgDiscoveryEntityProvider.ts @@ -193,12 +193,14 @@ export class GitlabOrgDiscoveryEntityProvider implements EntityProvider { }); } else { groups = (await client.listDescendantGroups(this.config.group)).items; - users = ( - await client.getGroupMembers(this.config.group.split('/')[0], [ - 'DIRECT', - 'DESCENDANTS', - ]) - ).items; + const rootGroup = this.config.group.split('/')[0]; + users = paginated<GitLabUser>( + options => client.listSaaSUsers(rootGroup, options), + { + page: 1, + per_page: 100, + }, + ); } const idMappedUser: { [userId: number]: GitLabUser } = {}; @@ -332,6 +334,10 @@ export class GitlabOrgDiscoveryEntityProvider implements EntityProvider { const annotations: { [annotationName: string]: string } = {}; annotations[`${host}/user-login`] = user.web_url; + if (user?.group_saml_identity?.extern_uid) { + annotations[`${host}/saml-external-uid`] = + user.group_saml_identity.extern_uid; + } const entity: UserEntity = { apiVersion: 'backstage.io/v1alpha1', diff --git a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md index 870514fc08..58e19beae8 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md +++ b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-catalog-backend-module-incremental-ingestion +## 0.4.10 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + +## 0.4.10-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-catalog-backend@1.14.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-events-node@0.2.15-next.2 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 0.4.9-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 1d0709b7da..a0df7f5449 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.9-next.1", + "version": "0.4.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -60,13 +60,11 @@ "express": "^4.17.1", "express-promise-router": "^4.1.0", "knex": "^2.0.0", - "lodash": "^4.17.21", "luxon": "^3.0.0", "uuid": "^8.3.2", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-app-api": "workspace:^", "@backstage/backend-defaults": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^" diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index cdf7473ff9..f9d38ee033 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.5.21 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## 0.5.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + ## 0.5.20-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index d38d746563..36c1e6c46f 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.20-next.1", + "version": "0.5.21", "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 7d7f6f3039..3cb7b30b3d 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.5.13 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## 0.5.13-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + ## 0.5.12-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 112d0b7c34..91459e847e 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.12-next.1", + "version": "0.5.13", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index b103bd920d..65b55833ca 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.1.23 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## 0.1.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-catalog-backend@1.14.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + ## 0.1.22-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index 52659c8d03..1f85d0d844 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.22-next.1", + "version": "0.1.23", "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 7e74c43039..7ce2b70e20 100644 --- a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md +++ b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-catalog-backend-module-puppetdb +## 0.1.11 + +### Patch Changes + +- 890e3b5ad4: Make sure to include the error message when ingestion fails +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + ## 0.1.10-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-puppetdb/package.json b/plugins/catalog-backend-module-puppetdb/package.json index 3ec71d1042..db267bc22e 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.10-next.1", + "version": "0.1.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md index 1be951bf47..b077261f25 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md +++ b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-catalog-backend-module-scaffolder-entity-model +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-scaffolder-common@1.4.2 + +## 0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-scaffolder-common@1.4.2-next.0 + ## 0.1.2-next.1 ### 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 35f573ec1e..f20a772a30 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.2-next.1", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md index 2c229f113e..310f3b9b5f 100644 --- a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md +++ b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-catalog-backend-module-unprocessed +## 0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + +## 0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + ## 0.3.2-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-unprocessed/package.json b/plugins/catalog-backend-module-unprocessed/package.json index 2a923fdf87..5adc6e1f5f 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.2-next.1", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 6e74d0d408..f6dee7b12f 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,60 @@ # @backstage/plugin-catalog-backend +## 1.14.0 + +### Minor Changes + +- 78af9433c8: Instrumenting some missing metrics with `OpenTelemetry` + +### Patch Changes + +- 7a2e2924c7: Marked the `LocationEntityProcessor` as deprecated, as it is no longer used internally since way back and can even be harmful at this point. +- 0b55f773a7: Removed some unused dependencies +- 348e8c1cdb: Fixes a bug where eagerly deleted entities did not properly trigger re-stitching of entities that they had relations to. +- b97e9790f0: Internal refactors, laying the foundation for later introducing deferred stitching (see #18062). +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-openapi-utils@0.0.5 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-module-catalog@0.1.10 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-events-node@0.2.15 + - @backstage/plugin-permission-common@0.7.9 + +## 1.14.0-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-openapi-utils@0.0.5-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/plugin-search-backend-module-catalog@0.1.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-events-node@0.2.15-next.2 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 1.14.0-next.1 ### Patch Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 45826a1f39..388f6b5ffc 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.14.0-next.1", + "version": "1.14.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -60,16 +60,13 @@ "@backstage/plugin-events-node": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-permission-node": "workspace:^", - "@backstage/plugin-scaffolder-common": "workspace:^", "@backstage/plugin-search-backend-module-catalog": "workspace:^", - "@backstage/plugin-search-common": "workspace:^", "@backstage/types": "workspace:^", "@opentelemetry/api": "^1.3.0", "@types/express": "^4.17.6", "codeowners-utils": "^1.0.2", "core-js": "^3.6.5", "express": "^4.17.1", - "express-promise-router": "^4.1.0", "fast-json-stable-stringify": "^2.1.0", "fs-extra": "10.1.0", "git-url-parse": "^13.0.0", @@ -91,7 +88,6 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", - "@backstage/plugin-search-backend-node": "workspace:^", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", "@types/lodash": "^4.14.151", diff --git a/plugins/catalog-backend/src/service/standaloneServer.ts b/plugins/catalog-backend/src/service/standaloneServer.ts index e48515fb8b..995a607ab5 100644 --- a/plugins/catalog-backend/src/service/standaloneServer.ts +++ b/plugins/catalog-backend/src/service/standaloneServer.ts @@ -19,9 +19,8 @@ import { DatabaseManager, loadBackendConfig, ServerTokenManager, - SingleHostDiscovery, + HostDiscovery, UrlReaders, - useHotMemoize, } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { ServerPermissionClient } from '@backstage/plugin-permission-node'; @@ -43,17 +42,15 @@ export async function startStandaloneServer( const logger = options.logger.child({ service: 'catalog-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); const reader = UrlReaders.default({ logger, config }); - const database = useHotMemoize(module, () => { - const manager = DatabaseManager.fromConfig( - new ConfigReader({ - backend: { - database: { client: 'better-sqlite3', connection: ':memory:' }, - }, - }), - ); - return manager.forPlugin('catalog'); - }); - const discovery = SingleHostDiscovery.fromConfig(config); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('catalog'); + const discovery = HostDiscovery.fromConfig(config); const tokenManager = ServerTokenManager.fromConfig(config, { logger, }); diff --git a/plugins/catalog-common/CHANGELOG.md b/plugins/catalog-common/CHANGELOG.md index b33835b2b6..3dbde65433 100644 --- a/plugins/catalog-common/CHANGELOG.md +++ b/plugins/catalog-common/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-catalog-common +## 1.0.17 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## 1.0.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 1.0.16 ### Patch Changes diff --git a/plugins/catalog-common/package.json b/plugins/catalog-common/package.json index ce78ffd5f0..68ab60e7c3 100644 --- a/plugins/catalog-common/package.json +++ b/plugins/catalog-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-common", "description": "Common functionalities for the catalog plugin", - "version": "1.0.16", + "version": "1.0.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index a9fc8ea29d..5d10ff94f3 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-catalog-graph +## 0.2.37 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + +## 0.2.37-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/types@1.1.1 + ## 0.2.37-next.1 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 77cdee4476..0afb6d92f7 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.2.37-next.1", + "version": "0.2.37", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -47,8 +47,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -57,10 +57,9 @@ "@backstage/dev-utils": "workspace:^", "@backstage/plugin-catalog": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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" }, "files": [ diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CurveFilter.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CurveFilter.tsx index 6cda334cf1..2f3278dc6b 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/CurveFilter.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CurveFilter.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Select } from '@backstage/core-components'; +import { Select, SelectedItems } from '@backstage/core-components'; import { Box } from '@material-ui/core'; import React, { useCallback } from 'react'; @@ -31,7 +31,10 @@ export type Props = { const curves: Array<Curve> = ['curveMonotoneX', 'curveStepBefore']; export const CurveFilter = ({ value, onChange }: Props) => { - const handleChange = useCallback(v => onChange(v as Curve), [onChange]); + const handleChange = useCallback( + (v: SelectedItems) => onChange(v as Curve), + [onChange], + ); return ( <Box pb={1} pt={1}> diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/DirectionFilter.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/DirectionFilter.tsx index 815ed1f292..c614ed2b58 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/DirectionFilter.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/DirectionFilter.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Select } from '@backstage/core-components'; +import { Select, SelectedItems } from '@backstage/core-components'; import { Box } from '@material-ui/core'; import React, { useCallback } from 'react'; import { Direction } from '../EntityRelationsGraph'; @@ -31,7 +31,10 @@ export type Props = { }; export const DirectionFilter = ({ value, onChange }: Props) => { - const handleChange = useCallback(v => onChange(v as Direction), [onChange]); + const handleChange = useCallback( + (v: SelectedItems) => onChange(v as Direction), + [onChange], + ); return ( <Box pb={1} pt={1}> diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.test.ts b/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.test.ts index 7a4d836365..a89fa353d6 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.test.ts +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/useCatalogGraphPage.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { RELATION_MEMBER_OF } from '@backstage/catalog-model'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import { useLocation as useLocationMocked } from 'react-router-dom'; import { Direction } from '../EntityRelationsGraph'; import { useCatalogGraphPage } from './useCatalogGraphPage'; diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx index 2556cd06d7..0ba9a3375a 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.test.tsx @@ -29,7 +29,44 @@ import userEvent from '@testing-library/user-event'; import React, { FunctionComponent } from 'react'; import { EntityRelationsGraph } from './EntityRelationsGraph'; -describe('<EntityRelationsGraph/>', () => { +/* + The tests in this file have been disabled for the following error: + + TypeError: Cannot read properties of null (reading 'document') + + at document (../../../node_modules/d3-drag/src/nodrag.js:5:19) + at SVGSVGElement.mousedowned (../../../node_modules/d3-zoom/src/zoom.js:279:16) + at SVGSVGElement.call (../../../node_modules/d3-selection/src/selection/on.js:3:14) + at SVGSVGElement.callTheUserObjectsOperation (../../../node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30) + at innerInvokeEventListeners (../../../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:350:25) + at invokeEventListeners (../../../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:286:3) + at SVGElementImpl._dispatch (../../../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:233:9) + at SVGElementImpl.dispatchEvent (../../../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:104:17) + at SVGElement.dispatchEvent (../../../node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:241:34) + at ../../../node_modules/@testing-library/user-event/dist/cjs/event/dispatchEvent.js:47:43 + at cb (../../../node_modules/@testing-library/react/dist/pure.js:66:16) + at batchedUpdates$1 (../../../node_modules/react-dom/cjs/react-dom.development.js:22380:12) + at act (../../../node_modules/react-dom/cjs/react-dom-test-utils.development.js:1042:14) + at Object.eventWrapper (../../../node_modules/@testing-library/react/dist/pure.js:65:26) + at Object.wrapEvent (../../../node_modules/@testing-library/user-event/dist/cjs/event/wrapEvent.js:29:24) + at Object.dispatchEvent (../../../node_modules/@testing-library/user-event/dist/cjs/event/dispatchEvent.js:47:22) + at Object.dispatchUIEvent (../../../node_modules/@testing-library/user-event/dist/cjs/event/dispatchEvent.js:24:26) + at Mouse.down (../../../node_modules/@testing-library/user-event/dist/cjs/system/pointer/mouse.js:83:34) + at PointerHost.press (../../../node_modules/@testing-library/user-event/dist/cjs/system/pointer/index.js:39:24) + at pointerAction (../../../node_modules/@testing-library/user-event/dist/cjs/pointer/index.js:59:43) + at Object.pointer (../../../node_modules/@testing-library/user-event/dist/cjs/pointer/index.js:35:15) + at ../../../node_modules/@testing-library/react/dist/pure.js:59:16 + + This has started happening after upgrading to the later version of @testing-library/user-event, and the d3-drag library + where it happens seems to be unmaintained. Skipping for now. + + https://github.com/d3/d3-drag/issues/79#issuecomment-1631409544 + + https://github.com/d3/d3-drag/issues/89 +*/ + +// eslint-disable-next-line jest/no-disabled-tests +describe.skip('<EntityRelationsGraph/>', () => { let Wrapper: FunctionComponent<React.PropsWithChildren<{}>>; const entities: { [ref: string]: Entity } = { 'b:d/c': { diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts index 7e0cd411ce..420af5345c 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationGraph.test.ts @@ -19,7 +19,7 @@ import { RELATION_OWNER_OF, RELATION_PART_OF, } from '@backstage/catalog-model'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { pick } from 'lodash'; import { useEntityRelationGraph } from './useEntityRelationGraph'; import { useEntityStore as useEntityStoreMocked } from './useEntityStore'; diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts index c2ee918e5b..d17e8b1c9d 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityRelationNodesAndEdges.test.ts @@ -21,7 +21,7 @@ import { RELATION_PART_OF, stringifyEntityRef, } from '@backstage/catalog-model'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import { filter, keyBy } from 'lodash'; import { useEntityRelationGraph as useEntityRelationGraphMocked } from './useEntityRelationGraph'; import { useEntityRelationNodesAndEdges } from './useEntityRelationNodesAndEdges'; @@ -163,7 +163,7 @@ describe('useEntityRelationNodesAndEdges', () => { }); test('should generate unidirectional graph with merged relations', async () => { - const { result, waitForValueToChange } = renderHook(() => + const { result } = renderHook(() => useEntityRelationNodesAndEdges({ rootEntityRefs: ['b:d/c'], unidirectional: true, @@ -171,9 +171,9 @@ describe('useEntityRelationNodesAndEdges', () => { }), ); - await waitForValueToChange( - () => result.current.nodes && result.current.edges, - ); + await waitFor(() => { + expect(result.current.nodes && result.current.edges).toBeDefined(); + }); const { nodes, edges, loading, error } = result.current; @@ -236,7 +236,7 @@ describe('useEntityRelationNodesAndEdges', () => { }); test('should generate unidirectional graph', async () => { - const { result, waitForValueToChange } = renderHook(() => + const { result } = renderHook(() => useEntityRelationNodesAndEdges({ rootEntityRefs: ['b:d/c'], unidirectional: true, @@ -244,9 +244,9 @@ describe('useEntityRelationNodesAndEdges', () => { }), ); - await waitForValueToChange( - () => result.current.nodes && result.current.edges, - ); + await waitFor(() => { + expect(result.current.nodes && result.current.edges).toBeDefined(); + }); const { nodes, edges, loading, error } = result.current; @@ -309,7 +309,7 @@ describe('useEntityRelationNodesAndEdges', () => { }); test('should generate bidirectional graph with merged relations', async () => { - const { result, waitForValueToChange } = renderHook(() => + const { result } = renderHook(() => useEntityRelationNodesAndEdges({ rootEntityRefs: ['b:d/c'], unidirectional: false, @@ -317,9 +317,9 @@ describe('useEntityRelationNodesAndEdges', () => { }), ); - await waitForValueToChange( - () => result.current.nodes && result.current.edges, - ); + await waitFor(() => { + expect(result.current.nodes && result.current.edges).toBeDefined(); + }); const { nodes, edges, loading, error } = result.current; @@ -412,7 +412,7 @@ describe('useEntityRelationNodesAndEdges', () => { }); test('should generate bidirectional graph with all relations', async () => { - const { result, waitForValueToChange } = renderHook(() => + const { result } = renderHook(() => useEntityRelationNodesAndEdges({ rootEntityRefs: ['b:d/c'], unidirectional: false, @@ -420,9 +420,9 @@ describe('useEntityRelationNodesAndEdges', () => { }), ); - await waitForValueToChange( - () => result.current.nodes && result.current.edges, - ); + await waitFor(() => { + expect(result.current.nodes && result.current.edges).toBeDefined(); + }); const { nodes, edges, loading, error } = result.current; @@ -515,15 +515,15 @@ describe('useEntityRelationNodesAndEdges', () => { }); test('should generate graph with multiple root nodes', async () => { - const { result, waitForValueToChange } = renderHook(() => + const { result } = renderHook(() => useEntityRelationNodesAndEdges({ rootEntityRefs: ['b:d/c', 'b:d/c2'], }), ); - await waitForValueToChange( - () => result.current.nodes && result.current.edges, - ); + await waitFor(() => { + expect(result.current.nodes && result.current.edges).toBeDefined(); + }); const { nodes, edges, loading, error } = result.current; @@ -586,16 +586,16 @@ describe('useEntityRelationNodesAndEdges', () => { }); test('should filter by relation', async () => { - const { result, waitForValueToChange } = renderHook(() => + const { result } = renderHook(() => useEntityRelationNodesAndEdges({ rootEntityRefs: ['b:d/c'], relations: [RELATION_OWNER_OF], }), ); - await waitForValueToChange( - () => result.current.nodes && result.current.edges, - ); + await waitFor(() => { + expect(result.current.nodes && result.current.edges).toBeDefined(); + }); const { nodes, edges, loading, error } = result.current; @@ -646,16 +646,16 @@ describe('useEntityRelationNodesAndEdges', () => { }); test('should filter by kind', async () => { - const { result, waitForValueToChange } = renderHook(() => + const { result } = renderHook(() => useEntityRelationNodesAndEdges({ rootEntityRefs: ['b:d/c'], kinds: ['b'], }), ); - await waitForValueToChange( - () => result.current.nodes && result.current.edges, - ); + await waitFor(() => { + expect(result.current.nodes && result.current.edges).toBeDefined(); + }); const { nodes, edges, loading, error } = result.current; diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts index 802f993802..0d75fabc3b 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.test.ts @@ -16,7 +16,7 @@ import { Entity } from '@backstage/catalog-model'; import { useApi as useApiMocked } from '@backstage/core-plugin-api'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook, waitFor } from '@testing-library/react'; import { useEntityStore } from './useEntityStore'; jest.mock('@backstage/core-plugin-api'); @@ -65,7 +65,7 @@ describe('useEntityStore', () => { catalogApi.getEntityByRef.mockResolvedValue(entity); - const { result, waitFor } = renderHook(() => useEntityStore()); + const { result } = renderHook(() => useEntityStore()); act(() => { result.current.requestEntities(['kind:namespace/name']); @@ -85,7 +85,7 @@ describe('useEntityStore', () => { const err = new Error('Hello World'); catalogApi.getEntityByRef.mockRejectedValue(err); - const { result, waitFor } = renderHook(() => useEntityStore()); + const { result } = renderHook(() => useEntityStore()); act(() => { result.current.requestEntities(['kind:namespace/name']); @@ -134,7 +134,7 @@ describe('useEntityStore', () => { catalogApi.getEntityByRef.mockResolvedValue(entity1); - const { result, waitFor } = renderHook(() => useEntityStore()); + const { result } = renderHook(() => useEntityStore()); act(() => { result.current.requestEntities(['kind:namespace/name1']); @@ -189,7 +189,7 @@ describe('useEntityStore', () => { catalogApi.getEntityByRef.mockResolvedValue(entity1); - const { result, waitFor } = renderHook(() => useEntityStore()); + const { result } = renderHook(() => useEntityStore()); act(() => { result.current.requestEntities(['kind:namespace/name1']); diff --git a/plugins/catalog-graphql/CHANGELOG.md b/plugins/catalog-graphql/CHANGELOG.md index e34136f8eb..0a08803e7d 100644 --- a/plugins/catalog-graphql/CHANGELOG.md +++ b/plugins/catalog-graphql/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-catalog-graphql +## 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 diff --git a/plugins/catalog-graphql/README.md b/plugins/catalog-graphql/README.md index e05672e3a5..021d0d1b20 100644 --- a/plugins/catalog-graphql/README.md +++ b/plugins/catalog-graphql/README.md @@ -1,11 +1,3 @@ # Catalog GraphQL Plugin -## Getting Started - -This is the Catalog GraphQL plugin. - -It provides the `catalog` part of the GraphQL schema. - -To register it with the GraphQL backend, be sure to follow the [Getting Started](../graphql-backend/README.md#getting-started) guide of the GraphQL plugin. - -<!-- TODO: Need to make the GraphQL plugin compatible with non forked repos > +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/package.json b/plugins/catalog-graphql/package.json index e853f308f3..d8869e2578 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-graphql", - "description": "An experimental Backstage catalog GraphQL module", - "version": "0.3.23", + "description": "Deprecated, consider using @frontside/backstage-plugin-graphql-backend instead", + "version": "0.4.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -47,8 +47,8 @@ "winston": "^3.2.1" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 97a6070230..8a84c211e5 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-catalog-import +## 0.10.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: The `app.title` configuration is now properly required to be a string. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## 0.10.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + ## 0.10.1-next.1 ### Patch Changes diff --git a/plugins/catalog-import/alpha-api-report.md b/plugins/catalog-import/alpha-api-report.md new file mode 100644 index 0000000000..63e2cda339 --- /dev/null +++ b/plugins/catalog-import/alpha-api-report.md @@ -0,0 +1,19 @@ +## API Report File for "@backstage/plugin-catalog-import" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; +import { RouteRef } from '@backstage/frontend-plugin-api'; + +// @alpha (undocumented) +const _default: BackstagePlugin< + { + importPage: RouteRef<undefined>; + }, + {} +>; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index a982b13373..e892338dea 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,14 +1,27 @@ { "name": "@backstage/plugin-catalog-import", "description": "A Backstage plugin the helps you import entities into your catalog", - "version": "0.10.1-next.1", + "version": "0.10.1", "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" + "access": "public" + }, + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.tsx", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.tsx" + ], + "package.json": [ + "package.json" + ] + } }, "backstage": { "role": "frontend-plugin" @@ -39,6 +52,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "@backstage/integration": "workspace:^", "@backstage/integration-react": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", @@ -56,8 +70,8 @@ "yaml": "^2.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -65,10 +79,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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", "msw": "^1.0.0" }, diff --git a/plugins/catalog-import/src/alpha.tsx b/plugins/catalog-import/src/alpha.tsx new file mode 100644 index 0000000000..bde1048f13 --- /dev/null +++ b/plugins/catalog-import/src/alpha.tsx @@ -0,0 +1,84 @@ +/* + * 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 { + configApiRef, + createApiFactory, + discoveryApiRef, + identityApiRef, +} from '@backstage/core-plugin-api'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; +import { + createApiExtension, + createPageExtension, + createPlugin, +} from '@backstage/frontend-plugin-api'; +import { + scmAuthApiRef, + scmIntegrationsApiRef, +} from '@backstage/integration-react'; +import React from 'react'; +import { CatalogImportClient, catalogImportApiRef } from './api'; +import { rootRouteRef } from './plugin'; +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 => <m.ImportPage />), +}); + +const CatalogImportService = createApiExtension({ + factory: createApiFactory({ + api: catalogImportApiRef, + deps: { + discoveryApi: discoveryApiRef, + scmAuthApi: scmAuthApiRef, + identityApi: identityApiRef, + scmIntegrationsApi: scmIntegrationsApiRef, + catalogApi: catalogApiRef, + configApi: configApiRef, + }, + factory: ({ + discoveryApi, + scmAuthApi, + identityApi, + scmIntegrationsApi, + catalogApi, + configApi, + }) => + new CatalogImportClient({ + discoveryApi, + scmAuthApi, + scmIntegrationsApi, + identityApi, + catalogApi, + configApi, + }), + }), +}); + +/** @alpha */ +export default createPlugin({ + id: 'catalog-import', + extensions: [CatalogImportService, CatalogImportPageExtension], + routes: { + importPage: convertLegacyRouteRef(rootRouteRef), + }, +}); diff --git a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx index c777953808..16000465b9 100644 --- a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx @@ -36,7 +36,7 @@ export const DefaultImportPage = () => { const theme = useTheme(); const configApi = useApi(configApiRef); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); - const appTitle = configApi.getOptional('app.title') || 'Backstage'; + const appTitle = configApi.getOptionalString('app.title') || 'Backstage'; const contentItems = [ <Grid item xs={12} md={4} lg={6} xl={8}> diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx index f7086fce19..26b6b8eb52 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx @@ -43,7 +43,7 @@ export const ImportInfoCard = (props: ImportInfoCardProps) => { } = props; const configApi = useApi(configApiRef); - const appTitle = configApi.getOptional('app.title') || 'Backstage'; + const appTitle = configApi.getOptionalString('app.title') || 'Backstage'; const catalogImportApi = useApi(catalogImportApiRef); const hasGithubIntegration = configApi.has('integrations.github'); diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx index 0a6960cdc7..4e737bd115 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx @@ -19,7 +19,7 @@ import { configApiRef } from '@backstage/core-plugin-api'; import { MockConfigApi, TestApiProvider } from '@backstage/test-utils'; import { makeStyles } from '@material-ui/core'; import { render, screen } from '@testing-library/react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import React from 'react'; import { PreviewCatalogInfoComponent } from './PreviewCatalogInfoComponent'; diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewPullRequestComponent.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewPullRequestComponent.test.tsx index d983b6d359..53485bedb5 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewPullRequestComponent.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewPullRequestComponent.test.tsx @@ -16,7 +16,7 @@ import { makeStyles } from '@material-ui/core'; import { render, screen } from '@testing-library/react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import React from 'react'; import { PreviewPullRequestComponent } from './PreviewPullRequestComponent'; diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx index 36f1217c37..079b010ec6 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.test.tsx @@ -18,7 +18,7 @@ import { configApiRef, errorApiRef } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { TestApiProvider, MockConfigApi } from '@backstage/test-utils'; import { TextField } from '@material-ui/core'; -import { act, render, screen } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { AnalyzeResult, catalogImportApiRef } from '../../api'; @@ -101,36 +101,34 @@ describe('<StepPrepareCreatePullRequest />', () => { it('renders without exploding', async () => { catalogApi.getEntities.mockReturnValue(Promise.resolve({ items: [] })); - await act(async () => { - render( - <StepPrepareCreatePullRequest - analyzeResult={analyzeResult} - onPrepare={onPrepareFn} - renderFormFields={({ register }) => { - return ( - <> - <TextField {...asInputRef(register('title'))} /> - <TextField {...asInputRef(register('body'))} /> - <TextField {...asInputRef(register('componentName'))} /> - <TextField {...asInputRef(register('owner'))} /> - </> - ); - }} - />, - { - wrapper: Wrapper, - }, - ); + render( + <StepPrepareCreatePullRequest + analyzeResult={analyzeResult} + onPrepare={onPrepareFn} + renderFormFields={({ register }) => { + return ( + <> + <TextField {...asInputRef(register('title'))} /> + <TextField {...asInputRef(register('body'))} /> + <TextField {...asInputRef(register('componentName'))} /> + <TextField {...asInputRef(register('owner'))} /> + </> + ); + }} + />, + { + wrapper: Wrapper, + }, + ); - const title = await screen.findByText('My title'); - const description = await screen.findByText('body', { - selector: 'strong', - }); - expect(title).toBeInTheDocument(); - expect(title).toBeVisible(); - expect(description).toBeInTheDocument(); - expect(description).toBeVisible(); + const title = await screen.findByText('My title'); + const description = await screen.findByText('body', { + selector: 'strong', }); + expect(title).toBeInTheDocument(); + expect(title).toBeVisible(); + expect(description).toBeInTheDocument(); + expect(description).toBeVisible(); }); it('should submit created PR', async () => { @@ -142,39 +140,37 @@ describe('<StepPrepareCreatePullRequest />', () => { }), ); - await act(async () => { - render( - <StepPrepareCreatePullRequest - analyzeResult={analyzeResult} - onPrepare={onPrepareFn} - renderFormFields={({ register }) => { - return ( - <> - <TextField {...asInputRef(register('title'))} /> - <TextField {...asInputRef(register('body'))} /> - <TextField - {...asInputRef(register('componentName'))} - id="name" - label="name" - /> - <TextField - {...asInputRef(register('owner'))} - id="owner" - label="owner" - /> - </> - ); - }} - />, - { - wrapper: Wrapper, - }, - ); + render( + <StepPrepareCreatePullRequest + analyzeResult={analyzeResult} + onPrepare={onPrepareFn} + renderFormFields={({ register }) => { + return ( + <> + <TextField {...asInputRef(register('title'))} /> + <TextField {...asInputRef(register('body'))} /> + <TextField + {...asInputRef(register('componentName'))} + id="name" + label="name" + /> + <TextField + {...asInputRef(register('owner'))} + id="owner" + label="owner" + /> + </> + ); + }} + />, + { + wrapper: Wrapper, + }, + ); - await userEvent.type(await screen.findByLabelText('name'), '-changed'); - await userEvent.type(await screen.findByLabelText('owner'), '-changed'); - await userEvent.click(screen.getByRole('button', { name: /Create PR/i })); - }); + await userEvent.type(await screen.findByLabelText('name'), '-changed'); + await userEvent.type(await screen.findByLabelText('owner'), '-changed'); + await userEvent.click(screen.getByRole('button', { name: /Create PR/i })); expect(catalogImportApi.submitPullRequest).toHaveBeenCalledTimes(1); expect(catalogImportApi.submitPullRequest.mock.calls[0]).toMatchObject([ @@ -226,31 +222,29 @@ spec: new Error('some error'), ); - await act(async () => { - render( - <StepPrepareCreatePullRequest - analyzeResult={analyzeResult} - onPrepare={onPrepareFn} - renderFormFields={({ register }) => { - return ( - <> - <TextField {...asInputRef(register('title'))} /> - <TextField {...asInputRef(register('body'))} /> - <TextField {...asInputRef(register('componentName'))} /> - <TextField {...asInputRef(register('owner'))} /> - </> - ); - }} - />, - { - wrapper: Wrapper, - }, - ); + render( + <StepPrepareCreatePullRequest + analyzeResult={analyzeResult} + onPrepare={onPrepareFn} + renderFormFields={({ register }) => { + return ( + <> + <TextField {...asInputRef(register('title'))} /> + <TextField {...asInputRef(register('body'))} /> + <TextField {...asInputRef(register('componentName'))} /> + <TextField {...asInputRef(register('owner'))} /> + </> + ); + }} + />, + { + wrapper: Wrapper, + }, + ); - await userEvent.click( - await screen.findByRole('button', { name: /Create PR/i }), - ); - }); + await userEvent.click( + await screen.findByRole('button', { name: /Create PR/i }), + ); expect(screen.getByText('some error')).toBeInTheDocument(); expect(catalogImportApi.submitPullRequest).toHaveBeenCalledTimes(1); @@ -273,30 +267,26 @@ spec: }), ); - await act(async () => { - render( - <StepPrepareCreatePullRequest - analyzeResult={analyzeResult} - onPrepare={onPrepareFn} - renderFormFields={renderFormFieldsFn} - />, - { - wrapper: Wrapper, - }, - ); + render( + <StepPrepareCreatePullRequest + analyzeResult={analyzeResult} + onPrepare={onPrepareFn} + renderFormFields={renderFormFieldsFn} + />, + { + wrapper: Wrapper, + }, + ); + + await waitFor(() => { + expect(catalogApi.getEntities).toHaveBeenCalledTimes(1); }); - expect(catalogApi.getEntities).toHaveBeenCalledTimes(1); expect(renderFormFieldsFn).toHaveBeenCalled(); expect(renderFormFieldsFn.mock.calls[0][0]).toMatchObject({ - groups: [], - groupsLoading: true, + groups: ['my-group'], + groupsLoading: false, }); - expect( - renderFormFieldsFn.mock.calls[ - renderFormFieldsFn.mock.calls.length - 1 - ][0], - ).toMatchObject({ groups: ['my-group'], groupsLoading: false }); }); describe('generateEntities', () => { diff --git a/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx b/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx index 74ebd973d0..b0db174787 100644 --- a/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx +++ b/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx @@ -42,7 +42,7 @@ export const StepReviewLocation = ({ const configApi = useApi(configApiRef); const analytics = useAnalytics(); - const appTitle = configApi.getOptional('app.title') || 'Backstage'; + const appTitle = configApi.getOptionalString('app.title') || 'Backstage'; const [submitted, setSubmitted] = useState(false); const [error, setError] = useState<string>(); diff --git a/plugins/catalog-import/src/components/useImportState.test.tsx b/plugins/catalog-import/src/components/useImportState.test.tsx index 155adb8290..dc2cb30f6f 100644 --- a/plugins/catalog-import/src/components/useImportState.test.tsx +++ b/plugins/catalog-import/src/components/useImportState.test.tsx @@ -16,7 +16,7 @@ import { Entity, CompoundEntityRef } from '@backstage/catalog-model'; import { cleanup } from '@testing-library/react'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import { AnalyzeResult } from '../api'; import { @@ -73,7 +73,6 @@ describe('useImportState', () => { describe('onAnalysis & onPrepare & onReview & onReset', () => { it('should work', async () => { const { result } = renderHook(() => useImportState()); - await cleanup(); expect(result.current).toMatchObject({ activeFlow: 'unknown', @@ -148,7 +147,6 @@ describe('useImportState', () => { it('should work skipped', async () => { const { result } = renderHook(() => useImportState()); - await cleanup(); expect(result.current).toMatchObject({ activeFlow: 'unknown', @@ -198,7 +196,6 @@ describe('useImportState', () => { it('should ignore on invalid state', async () => { const { result } = renderHook(() => useImportState()); - await cleanup(); // state 'analyze' act(() => { @@ -264,7 +261,6 @@ describe('useImportState', () => { describe('onGoBack', () => { it('should work', async () => { const { result } = renderHook(() => useImportState()); - await cleanup(); expect(result.current.activeStepNumber).toBe(0); expect(result.current.onGoBack).toBeUndefined(); @@ -303,7 +299,6 @@ describe('useImportState', () => { it('should work for skipped', async () => { const { result } = renderHook(() => useImportState()); - await cleanup(); expect(result.current.activeStepNumber).toBe(0); expect(result.current.onGoBack).toBeUndefined(); @@ -329,7 +324,6 @@ describe('useImportState', () => { describe('should consider prepareNotRepeatable', () => { it('as true', async () => { const { result } = renderHook(() => useImportState()); - await cleanup(); expect(result.current.onGoBack).toBeUndefined(); @@ -351,7 +345,6 @@ describe('useImportState', () => { it('as false', async () => { const { result } = renderHook(() => useImportState()); - await cleanup(); expect(result.current.onGoBack).toBeUndefined(); diff --git a/plugins/catalog-node/CHANGELOG.md b/plugins/catalog-node/CHANGELOG.md index 0126011e83..22a2319142 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-catalog-node +## 1.4.7 + +### Patch Changes + +- 7a2e2924c7: Added docs to `processingResult` +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + +## 1.4.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + ## 1.4.6-next.1 ### Patch Changes diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index 61e9823ea6..2817703044 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.4.6-next.1", + "version": "1.4.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index 467f134119..9d6dbd2840 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,47 @@ # @backstage/plugin-catalog-react +## 1.8.5 + +### Patch Changes + +- a402e1dfb9: Fixed an issue causing `EntityPage` to show an error for entities containing special characters +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: The `spec.type` field in entities will now always be rendered as a string. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.6 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + +## 1.8.5-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-permission-react@0.4.16-next.1 + ## 1.8.5-next.1 ### Patch Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 637f83fcee..bb18160595 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.8.5-next.1", + "version": "1.8.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -64,7 +64,6 @@ "@react-hookz/web": "^23.0.0", "@types/react": "^16.13.1 || ^17.0.0", "classnames": "^2.2.6", - "jwt-decode": "^3.1.0", "lodash": "^4.17.21", "material-ui-popup-state": "^1.9.3", "qs": "^6.9.4", @@ -73,8 +72,8 @@ "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -83,12 +82,10 @@ "@backstage/plugin-catalog-common": "workspace:^", "@backstage/plugin-scaffolder-common": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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/jwt-decode": "^3.1.0", "@types/zen-observable": "^0.8.0", "react-test-renderer": "^16.13.1" }, diff --git a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx index 38edb9b064..32e66dc578 100644 --- a/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.test.tsx @@ -179,9 +179,7 @@ describe('<EntityAutocompletePicker/>', () => { </TestApiProvider>, ); await waitFor(() => - expect(updateFilters).toHaveBeenLastCalledWith({ - options: undefined, - }), + expect(screen.getByTestId('options-picker-expand')).toBeInTheDocument(), ); fireEvent.click(screen.getByTestId('options-picker-expand')); diff --git a/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx b/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx index 19554f18b7..de40f90c55 100644 --- a/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.test.tsx @@ -74,9 +74,10 @@ describe('<EntityLifecyclePicker/>', () => { </TestApiProvider>, ); - await waitFor(() => expect(catalogApi.getEntityFacets).toHaveBeenCalled()); - expect(updateFilters).toHaveBeenLastCalledWith({ - lifecycles: new EntityLifecycleFilter(['experimental']), + await waitFor(() => { + expect(updateFilters).toHaveBeenLastCalledWith({ + lifecycles: new EntityLifecycleFilter(['experimental']), + }); }); }); @@ -119,9 +120,10 @@ describe('<EntityLifecyclePicker/>', () => { </TestApiProvider>, ); - await waitFor(() => expect(catalogApi.getEntityFacets).toHaveBeenCalled()); - expect(updateFilters).toHaveBeenLastCalledWith({ - lifecycles: new EntityLifecycleFilter(['production']), + await waitFor(() => { + expect(updateFilters).toHaveBeenLastCalledWith({ + lifecycles: new EntityLifecycleFilter(['production']), + }); }); fireEvent.click(screen.getByTestId('lifecycles-picker-expand')); expect(screen.getByLabelText('production')).toBeChecked(); @@ -147,9 +149,10 @@ describe('<EntityLifecyclePicker/>', () => { </TestApiProvider>, ); - await waitFor(() => expect(catalogApi.getEntityFacets).toHaveBeenCalled()); - expect(updateFilters).toHaveBeenLastCalledWith({ - lifecycles: new EntityLifecycleFilter(['experimental']), + await waitFor(() => { + expect(updateFilters).toHaveBeenLastCalledWith({ + lifecycles: new EntityLifecycleFilter(['experimental']), + }); }); rendered.rerender( @@ -210,9 +213,10 @@ describe('<EntityLifecyclePicker/>', () => { </TestApiProvider>, ); - await waitFor(() => expect(catalogApi.getEntityFacets).toHaveBeenCalled()); - expect(updateFilters).toHaveBeenLastCalledWith({ - lifecycles: new EntityLifecycleFilter(['production']), + await waitFor(() => { + expect(updateFilters).toHaveBeenLastCalledWith({ + lifecycles: new EntityLifecycleFilter(['production']), + }); }); }); }); diff --git a/plugins/catalog-react/src/components/EntityNamespacePicker/EntityNamespacePicker.test.tsx b/plugins/catalog-react/src/components/EntityNamespacePicker/EntityNamespacePicker.test.tsx index 7dd13620c7..c4b5e64c9d 100644 --- a/plugins/catalog-react/src/components/EntityNamespacePicker/EntityNamespacePicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityNamespacePicker/EntityNamespacePicker.test.tsx @@ -113,9 +113,7 @@ describe('<EntityNamespacePicker/>', () => { </TestApiProvider>, ); await waitFor(() => - expect(updateFilters).toHaveBeenLastCalledWith({ - namespace: undefined, - }), + expect(screen.getByTestId('namespace-picker-expand')).toBeInTheDocument(), ); fireEvent.click(screen.getByTestId('namespace-picker-expand')); diff --git a/plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.test.ts b/plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.test.ts index 6f6da43307..1d0d1130a6 100644 --- a/plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.test.ts +++ b/plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.test.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import { useFacetsEntities } from './useFacetsEntities'; import { CatalogApi } from '@backstage/catalog-client'; @@ -50,9 +50,7 @@ describe('useFacetsEntities', () => { }, }); - const { result, waitFor } = renderHook(() => - useFacetsEntities({ enabled: true }), - ); + const { result } = renderHook(() => useFacetsEntities({ enabled: true })); result.current[1]({ text: '' }); await waitFor(() => { @@ -91,9 +89,7 @@ describe('useFacetsEntities', () => { }, }); - const { result, waitFor } = renderHook(() => - useFacetsEntities({ enabled: true }), - ); + const { result } = renderHook(() => useFacetsEntities({ enabled: true })); result.current[1]({ text: '' }); await waitFor(() => { @@ -147,9 +143,7 @@ describe('useFacetsEntities', () => { }, }); - const { result, waitFor } = renderHook(() => - useFacetsEntities({ enabled: true }), - ); + const { result } = renderHook(() => useFacetsEntities({ enabled: true })); result.current[1]({ text: '' }, { limit: 2 }); await waitFor(() => { @@ -261,9 +255,7 @@ describe('useFacetsEntities', () => { }, }); - const { result, waitFor } = renderHook(() => - useFacetsEntities({ enabled: true }), - ); + const { result } = renderHook(() => useFacetsEntities({ enabled: true })); result.current[1]({ text: 'der ' }); await waitFor(() => { diff --git a/plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.test.ts b/plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.test.ts index d974709d34..64cc7769a6 100644 --- a/plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.test.ts +++ b/plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.test.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import { CatalogApi } from '@backstage/catalog-client'; import { useQueryEntities } from './useQueryEntities'; @@ -62,7 +62,7 @@ describe('useQueryEntities', () => { totalItems: 2, }); - const { result, waitFor } = renderHook(() => useQueryEntities()); + const { result } = renderHook(() => useQueryEntities()); const [, fetch] = result.current!; fetch({ text: 'text' }); diff --git a/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.test.tsx b/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.test.tsx index f665ca6c00..85a477801a 100644 --- a/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.test.tsx +++ b/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.test.tsx @@ -49,7 +49,7 @@ const apis = TestApiRegistry.from([catalogApiRef, catalogApi]); describe('<EntityPeekAheadPopover/>', () => { it('renders all owners', async () => { - renderInTestApp( + await renderInTestApp( <ApiProvider apis={apis}> <EntityPeekAheadPopover entityRef="component:default/service1"> <Button data-testid="popover1">s1</Button> diff --git a/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.tsx b/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.tsx index 91d60d4f13..077274a6e9 100644 --- a/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.tsx +++ b/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.tsx @@ -164,7 +164,7 @@ export const EntityPeekAheadPopover = (props: EntityPeekAheadPopoverProps) => { {entity.metadata.description} </Typography> )} - <Typography>{entity.spec?.type}</Typography> + <Typography>{entity.spec?.type?.toString()}</Typography> <Box marginTop="0.5em"> {(entity.metadata.tags || []) .slice(0, maxTagChips) diff --git a/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx b/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx index bfaa689190..917ece047c 100644 --- a/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx +++ b/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.test.tsx @@ -14,7 +14,13 @@ * limitations under the License. */ -import { fireEvent, render, waitFor, screen } from '@testing-library/react'; +import { + fireEvent, + render, + waitFor, + screen, + act, +} from '@testing-library/react'; import React from 'react'; import { MockEntityListContextProvider } from '../../testUtils/providers'; import { EntityTagFilter } from '../../filters'; @@ -127,9 +133,7 @@ describe('<EntityTagPicker/>', () => { </TestApiProvider>, ); await waitFor(() => - expect(updateFilters).toHaveBeenLastCalledWith({ - tags: undefined, - }), + expect(screen.getByTestId('tags-picker-expand')).toBeInTheDocument(), ); fireEvent.click(screen.getByTestId('tags-picker-expand')); @@ -218,13 +222,16 @@ describe('<EntityTagPicker/>', () => { </TestApiProvider>, ); await waitFor(() => - expect(updateFilters).toHaveBeenLastCalledWith({ - tags: new EntityTagFilter(['tag1']), - }), + expect(screen.getByTestId('tags-picker-expand')).toBeInTheDocument(), ); - fireEvent.click(screen.getByTestId('tags-picker-expand')); - fireEvent.click(screen.getByLabelText('tag2')); - expect(screen.getByLabelText('tag2')).toBeChecked(); + + await act(async () => { + fireEvent.click(screen.getByTestId('tags-picker-expand')); + }); + await act(async () => { + fireEvent.click(screen.getByLabelText('tag2')); + }); + expect(updateFilters).toHaveBeenLastCalledWith({ tags: new EntityTagFilter(['tag1', 'tag2']), }); diff --git a/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx b/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx index 09b944605f..d2eb6d4266 100644 --- a/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx +++ b/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx @@ -74,7 +74,10 @@ export function OverviewPage(props: { entity: AlphaEntity }) { </ListItem> {spec?.type && ( <ListItem> - <ListItemText primary="spec.type" secondary={spec.type} /> + <ListItemText + primary="spec.type" + secondary={spec.type?.toString()} + /> </ListItem> )} {metadata.uid && ( diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx index e458e7d157..f0da550d0b 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx @@ -17,16 +17,9 @@ import { CatalogApi, Location } from '@backstage/catalog-client'; import { Entity, ANNOTATION_ORIGIN_LOCATION } from '@backstage/catalog-model'; import { catalogApiRef } from '../../api'; -import { - act, - renderHook, - RenderHookResult, -} from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import React from 'react'; -import { - UseUnregisterEntityDialogState, - useUnregisterEntityDialogState, -} from './useUnregisterEntityDialogState'; +import { useUnregisterEntityDialogState } from './useUnregisterEntityDialogState'; import { TestApiProvider } from '@backstage/test-utils'; function defer<T>(): { promise: Promise<T>; resolve: (value: T) => void } { @@ -85,28 +78,23 @@ describe('useUnregisterEntityDialogState', () => { }); it('goes through the happy unregister path', async () => { - let rendered: RenderHookResult<unknown, UseUnregisterEntityDialogState>; - act(() => { - rendered = renderHook(() => useUnregisterEntityDialogState(entity), { - wrapper: Wrapper, - }); + const rendered = renderHook(() => useUnregisterEntityDialogState(entity), { + wrapper: Wrapper, }); - expect(rendered!.result.current).toEqual({ type: 'loading' }); + expect(rendered.result.current).toEqual({ type: 'loading' }); resolveLocation({ type: 'url', target: 'https://example.com', id: 'x' }); resolveColocatedEntities([entity]); - await act(async () => { - await rendered!.waitForNextUpdate(); - }); - - expect(rendered!.result.current).toEqual({ - type: 'unregister', - location: 'url:https://example.com', - colocatedEntities: [{ kind: 'Component', namespace: 'ns', name: 'n' }], - unregisterLocation: expect.any(Function), - deleteEntity: expect.any(Function), + await waitFor(() => { + expect(rendered.result.current).toEqual({ + type: 'unregister', + location: 'url:https://example.com', + colocatedEntities: [{ kind: 'Component', namespace: 'ns', name: 'n' }], + unregisterLocation: expect.any(Function), + deleteEntity: expect.any(Function), + }); }); }); @@ -114,65 +102,53 @@ describe('useUnregisterEntityDialogState', () => { entity.metadata.annotations![ANNOTATION_ORIGIN_LOCATION] = 'bootstrap:bootstrap'; - let rendered: RenderHookResult<unknown, UseUnregisterEntityDialogState>; - act(() => { - rendered = renderHook(() => useUnregisterEntityDialogState(entity), { - wrapper: Wrapper, - }); + const rendered = renderHook(() => useUnregisterEntityDialogState(entity), { + wrapper: Wrapper, }); resolveLocation({ type: 'bootstrap', target: 'bootstrap', id: 'x' }); resolveColocatedEntities([]); - await act(async () => { - await rendered!.waitForNextUpdate(); - }); - expect(rendered!.result.current).toEqual({ - type: 'bootstrap', - location: 'bootstrap:bootstrap', - deleteEntity: expect.any(Function), + await waitFor(() => { + expect(rendered.result.current).toEqual({ + type: 'bootstrap', + location: 'bootstrap:bootstrap', + deleteEntity: expect.any(Function), + }); }); }); it('chooses only-delete when there was no location annotation', async () => { delete entity.metadata.annotations![ANNOTATION_ORIGIN_LOCATION]; - let rendered: RenderHookResult<unknown, UseUnregisterEntityDialogState>; - act(() => { - rendered = renderHook(() => useUnregisterEntityDialogState(entity), { - wrapper: Wrapper, - }); + const rendered = renderHook(() => useUnregisterEntityDialogState(entity), { + wrapper: Wrapper, }); resolveLocation(undefined); resolveColocatedEntities([]); - await act(async () => { - await rendered!.waitForNextUpdate(); - }); - expect(rendered!.result.current).toEqual({ - type: 'only-delete', - deleteEntity: expect.any(Function), + await waitFor(() => { + expect(rendered.result.current).toEqual({ + type: 'only-delete', + deleteEntity: expect.any(Function), + }); }); }); it('chooses only-delete when the location could not be found', async () => { - let rendered: RenderHookResult<unknown, UseUnregisterEntityDialogState>; - act(() => { - rendered = renderHook(() => useUnregisterEntityDialogState(entity), { - wrapper: Wrapper, - }); + const rendered = renderHook(() => useUnregisterEntityDialogState(entity), { + wrapper: Wrapper, }); resolveLocation(undefined); resolveColocatedEntities([]); - await act(async () => { - await rendered!.waitForNextUpdate(); - }); - expect(rendered!.result.current).toEqual({ - type: 'only-delete', - deleteEntity: expect.any(Function), + await waitFor(() => { + expect(rendered.result.current).toEqual({ + type: 'only-delete', + deleteEntity: expect.any(Function), + }); }); }); }); diff --git a/plugins/catalog-react/src/hooks/useEntity.test.tsx b/plugins/catalog-react/src/hooks/useEntity.test.tsx index 8fc388654a..3b1190de2b 100644 --- a/plugins/catalog-react/src/hooks/useEntity.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntity.test.tsx @@ -15,7 +15,7 @@ */ import React, { PropsWithChildren } from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useEntity, useAsyncEntity, @@ -31,13 +31,13 @@ const entity = { metadata: { name: 'my-entity' }, kind: 'MyKind' } as Entity; describe('useEntity', () => { it('should throw if no entity is provided', async () => { - const { result } = renderHook(() => useEntity(), { - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( - <EntityProvider children={children} /> - ), - }); - - expect(result.error?.message).toMatch(/entity has not been loaded/); + expect(() => + renderHook(() => useEntity(), { + wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + <EntityProvider children={children} /> + ), + }), + ).toThrow(/entity has not been loaded/); }); it('should provide an entity', async () => { diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx index da27c61dcb..d77655ebcc 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx @@ -25,7 +25,7 @@ import { storageApiRef, } from '@backstage/core-plugin-api'; import { MockStorageApi, TestApiProvider } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook, waitFor } from '@testing-library/react'; import qs from 'qs'; import React, { PropsWithChildren } from 'react'; import { MemoryRouter } from 'react-router-dom'; @@ -119,10 +119,14 @@ describe('<EntityListProvider />', () => { }); it('resolves backend filters', async () => { - const { result, waitForValueToChange } = renderHook(() => useEntityList(), { + const { result } = renderHook(() => useEntityList(), { wrapper, }); - await waitForValueToChange(() => result.current.backendEntities); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBeGreaterThan(0); + }); + expect(result.current.backendEntities.length).toBe(2); expect(mockCatalogApi.getEntities).toHaveBeenCalledWith({ filter: { kind: 'component' }, @@ -130,13 +134,16 @@ describe('<EntityListProvider />', () => { }); it('resolves frontend filters', async () => { - const { result, waitFor } = renderHook(() => useEntityList(), { + const { result } = renderHook(() => useEntityList(), { wrapper, initialProps: { userFilter: 'all', }, }); - await waitFor(() => !!result.current.entities.length); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBeGreaterThan(0); + }); expect(result.current.backendEntities.length).toBe(2); act(() => @@ -160,13 +167,14 @@ describe('<EntityListProvider />', () => { const query = qs.stringify({ filters: { kind: 'component', type: 'service' }, }); - const { result, waitFor } = renderHook(() => useEntityList(), { - wrapper, - initialProps: { - location: `/catalog?${query}`, - }, + const { result } = renderHook(() => useEntityList(), { + wrapper: ({ children }) => + wrapper({ location: `/catalog?${query}`, children }), + }); + + await waitFor(() => { + expect(result.current.queryParameters).toBeTruthy(); }); - await act(() => waitFor(() => !!result.current.queryParameters)); expect(result.current.queryParameters).toEqual({ kind: 'component', type: 'service', @@ -174,7 +182,7 @@ describe('<EntityListProvider />', () => { }); it('does not fetch when only frontend filters change', async () => { - const { result, waitFor } = renderHook(() => useEntityList(), { + const { result } = renderHook(() => useEntityList(), { wrapper, }); @@ -200,32 +208,34 @@ describe('<EntityListProvider />', () => { }); it('debounces multiple filter changes', async () => { - const { result, waitForNextUpdate, waitForValueToChange } = renderHook( - () => useEntityList(), - { - wrapper, - }, - ); - await waitForValueToChange(() => result.current.backendEntities); + const { result } = renderHook(() => useEntityList(), { + wrapper, + }); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBeGreaterThan(0); + }); expect(result.current.backendEntities.length).toBe(2); expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(1); - act(() => { + await act(async () => { result.current.updateFilters({ kind: new EntityKindFilter('component') }); result.current.updateFilters({ type: new EntityTypeFilter('service') }); }); - await waitForNextUpdate(); - expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(2); + + await waitFor(() => { + expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(2); + }); }); it('returns an error on catalogApi failure', async () => { - const { result, waitForValueToChange, waitFor } = renderHook( - () => useEntityList(), - { - wrapper, - }, - ); - await waitForValueToChange(() => result.current.backendEntities); + const { result } = renderHook(() => useEntityList(), { + wrapper, + }); + + await waitFor(() => { + expect(result.current.backendEntities.length).toBeGreaterThan(0); + }); expect(result.current.backendEntities.length).toBe(2); mockCatalogApi.getEntities = jest.fn().mockRejectedValue('error'); diff --git a/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx b/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx index dc400b5c90..6c9519eb08 100644 --- a/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityOwnership.test.tsx @@ -18,7 +18,7 @@ import { CatalogApi } from '@backstage/catalog-client'; import { ComponentEntity, RELATION_OWNED_BY } from '@backstage/catalog-model'; import { IdentityApi, identityApiRef } from '@backstage/core-plugin-api'; import { TestApiProvider } from '@backstage/test-utils'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import React from 'react'; import { catalogApiRef } from '../api'; import { useEntityOwnership } from './useEntityOwnership'; @@ -83,19 +83,15 @@ describe('useEntityOwnership', () => { }); mockCatalogApi.getEntityByRef.mockResolvedValue(undefined); - const { result, waitForValueToChange } = renderHook( - () => useEntityOwnership(), - { - wrapper: Wrapper, - }, - ); + const { result } = renderHook(() => useEntityOwnership(), { + wrapper: Wrapper, + }); expect(result.current.loading).toBe(true); expect(result.current.isOwnedEntity(ownedEntity)).toBe(false); - await waitForValueToChange(() => result.current.loading); + await waitFor(() => expect(result.current.loading).toBe(false)); - expect(result.current.loading).toBe(false); expect(result.current.isOwnedEntity(ownedEntity)).toBe(true); }); }); diff --git a/plugins/catalog-react/src/hooks/useEntityPermission.test.tsx b/plugins/catalog-react/src/hooks/useEntityPermission.test.tsx index aed6676838..0c389de747 100644 --- a/plugins/catalog-react/src/hooks/useEntityPermission.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityPermission.test.tsx @@ -15,7 +15,7 @@ */ import { catalogEntityDeletePermission } from '@backstage/plugin-catalog-common/alpha'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useEntityPermission } from './useEntityPermission'; import { useAsyncEntity } from './useEntity'; import { usePermission } from '@backstage/plugin-permission-react'; diff --git a/plugins/catalog-react/src/hooks/useRelatedEntities.test.tsx b/plugins/catalog-react/src/hooks/useRelatedEntities.test.tsx index 8de7822d59..092f8e164e 100644 --- a/plugins/catalog-react/src/hooks/useRelatedEntities.test.tsx +++ b/plugins/catalog-react/src/hooks/useRelatedEntities.test.tsx @@ -16,8 +16,8 @@ import { Entity } from '@backstage/catalog-model'; import { TestApiProvider } from '@backstage/test-utils'; -import { WrapperComponent, renderHook } from '@testing-library/react-hooks'; -import React, { PropsWithChildren } from 'react'; +import { renderHook, waitFor } from '@testing-library/react'; +import React, { ComponentType, PropsWithChildren } from 'react'; import { catalogApiRef } from '../api'; import { useRelatedEntities } from './useRelatedEntities'; @@ -50,7 +50,7 @@ describe('useRelatedEntities', () => { getEntitiesByRefs: jest.fn(), }; - const wrapper: WrapperComponent<PropsWithChildren<{}>> = ({ children }) => { + const wrapper: ComponentType<PropsWithChildren<{}>> = ({ children }) => { return ( <TestApiProvider apis={[[catalogApiRef, catalogApi]]}> {children} @@ -70,7 +70,9 @@ describe('useRelatedEntities', () => { expect(rendered.result.current).toEqual({ loading: true }); - await rendered.waitForValueToChange(() => rendered.result.current.loading); + await waitFor(() => { + expect(rendered.result.current.loading).toBe(false); + }); expect(catalogApi.getEntitiesByRefs).toHaveBeenCalledWith({ entityRefs: ['group:default/the-owners-1', 'group:default/the-owners-2'], diff --git a/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx b/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx index f21b3cb710..e3010a0f4a 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx +++ b/plugins/catalog-react/src/hooks/useStarredEntities.test.tsx @@ -16,7 +16,7 @@ import { Entity } from '@backstage/catalog-model'; import { TestApiProvider } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook, waitFor } from '@testing-library/react'; import React, { PropsWithChildren } from 'react'; import { starredEntitiesApiRef, @@ -56,14 +56,13 @@ describe('useStarredEntities', () => { }); it('should return an empty set', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useStarredEntities(), - { wrapper }, - ); + const { result } = renderHook(() => useStarredEntities(), { + wrapper, + }); - await waitForNextUpdate(); - - expect(result.current.starredEntities.size).toBe(0); + await waitFor(() => { + expect(result.current.starredEntities.size).toBe(0); + }); }); it('should return a set with the current items', async () => { @@ -72,25 +71,21 @@ describe('useStarredEntities', () => { mockApi.toggleStarred(id); } - const { result, waitForNextUpdate } = renderHook( - () => useStarredEntities(), - { wrapper }, - ); + const { result } = renderHook(() => useStarredEntities(), { + wrapper, + }); - await waitForNextUpdate(); - - for (const item of expectedIds) { - expect(result.current.starredEntities.has(item)).toBeTruthy(); - } + await waitFor(() => { + for (const item of expectedIds) { + expect(result.current.starredEntities.has(item)).toBeTruthy(); + } + }); }); it('should listen to changes when the storage is set elsewhere', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useStarredEntities(), - { wrapper }, - ); - - await waitForNextUpdate(); + const { result } = renderHook(() => useStarredEntities(), { + wrapper, + }); expect(result.current.starredEntities.size).toBe(0); expect(result.current.isStarredEntity(mockEntity)).toBeFalsy(); @@ -99,42 +94,37 @@ describe('useStarredEntities', () => { // catch when the hook re-renders with the latest data setTimeout(() => result.current.toggleStarredEntity(mockEntity), 1); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.starredEntities.size).toBe(1); + }); - expect(result.current.starredEntities.size).toBe(1); expect(result.current.isStarredEntity(mockEntity)).toBeTruthy(); }); it('should write new entries to the local store when adding a toggling entity', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useStarredEntities(), - { wrapper }, - ); - - act(() => { - result.current.toggleStarredEntity(mockEntity); + const { result } = renderHook(() => useStarredEntities(), { + wrapper, }); - await waitForNextUpdate(); + await act(async () => { + result.current.toggleStarredEntity(mockEntity); + }); expect(result.current.isStarredEntity(mockEntity)).toBeTruthy(); expect(result.current.isStarredEntity(secondMockEntity)).toBeFalsy(); }); it('should remove an existing entity when toggling entries', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useStarredEntities(), - { wrapper }, - ); + const { result } = renderHook(() => useStarredEntities(), { + wrapper, + }); - act(() => { + await act(async () => { result.current.toggleStarredEntity(mockEntity); result.current.toggleStarredEntity(secondMockEntity); result.current.toggleStarredEntity(mockEntity); }); - await waitForNextUpdate(); - expect(result.current.isStarredEntity(mockEntity)).toBeFalsy(); expect(result.current.isStarredEntity(secondMockEntity)).toBeTruthy(); }); diff --git a/plugins/catalog-react/src/hooks/useStarredEntities.ts b/plugins/catalog-react/src/hooks/useStarredEntities.ts index 328a26e0f8..7e63aed10f 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntities.ts +++ b/plugins/catalog-react/src/hooks/useStarredEntities.ts @@ -20,7 +20,7 @@ import { stringifyEntityRef, } from '@backstage/catalog-model'; import { useApi } from '@backstage/core-plugin-api'; -import { useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; import useObservable from 'react-use/lib/useObservable'; import { starredEntitiesApiRef } from '../apis'; @@ -45,7 +45,7 @@ export function useStarredEntities(): { const starredEntitiesApi = useApi(starredEntitiesApiRef); const starredEntities = useObservable( - starredEntitiesApi.starredEntitie$(), + useMemo(() => starredEntitiesApi.starredEntitie$(), [starredEntitiesApi]), new Set<string>(), ); diff --git a/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx b/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx index d24b27f903..e64a9bbdf8 100644 --- a/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx +++ b/plugins/catalog-react/src/hooks/useStarredEntity.test.tsx @@ -16,7 +16,7 @@ import { Entity, CompoundEntityRef } from '@backstage/catalog-model'; import { TestApiProvider } from '@backstage/test-utils'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import React, { PropsWithChildren } from 'react'; import Observable from 'zen-observable'; import { StarredEntitiesApi, starredEntitiesApiRef } from '../apis'; @@ -83,18 +83,16 @@ describe('useStarredEntity', () => { ); mockStarredEntitiesApi.toggleStarred.mockResolvedValue(); - const { result, waitForNextUpdate } = renderHook( - () => useStarredEntity(entityOrRef), - { - wrapper, - }, - ); + const { result } = renderHook(() => useStarredEntity(entityOrRef), { + wrapper, + }); // the initial value will always be false because the observable triggers async expect(result.current.isStarredEntity).toBe(false); - await waitForNextUpdate(); - expect(result.current.isStarredEntity).toBe(true); + await waitFor(() => { + expect(result.current.isStarredEntity).toBe(true); + }); }); }); }); diff --git a/plugins/catalog-unprocessed-entities/CHANGELOG.md b/plugins/catalog-unprocessed-entities/CHANGELOG.md index 612c02a9a1..afd3890a12 100644 --- a/plugins/catalog-unprocessed-entities/CHANGELOG.md +++ b/plugins/catalog-unprocessed-entities/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-catalog-unprocessed-entities +## 0.1.4 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.1.4-next.1 ### Patch Changes diff --git a/plugins/catalog-unprocessed-entities/package.json b/plugins/catalog-unprocessed-entities/package.json index 735cb05f8d..b4d95ac20a 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.4-next.1", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -41,8 +41,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -50,8 +50,8 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 648fa4d7a4..6b5ba8b956 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,73 @@ # @backstage/plugin-catalog +## 1.14.0 + +### Minor Changes + +- 28f1ab2e1a: The catalog plugin no longer implements the experimental reconfiguration API. The create button title can now instead be configured using the new experimental internationalization API, via the `catalogTranslationRef` exported at `/alpha`. For example: + + ```ts + import { catalogTranslationRef } from '@backstage/plugin-catalog/alpha'; + + const app = createApp({ + __experimentalTranslations: { + resources: [ + createTranslationMessages({ + ref: catalogTranslationRef, + catalog_page_create_button_title: 'Create Software', + }), + ], + }, + }); + ``` + +- f3561a2935: include owner chip in catalog search result item + +### Patch Changes + +- 7c4a8e4d5f: Create an experimental `CatalogSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- 0296f272b4: The `spec.lifecycle' field in entities will now always be rendered as a string. +- 0b55f773a7: Removed some unused dependencies +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- e5a2956dd2: Migrate catalog api to declarative integration system, it is exported from `/alpha` subpath. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-scaffolder-common@1.4.2 + - @backstage/plugin-search-common@1.2.7 + +## 1.14.0-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-scaffolder-common@1.4.2-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 1.14.0-next.1 ### Patch Changes diff --git a/plugins/catalog/alpha-api-report.md b/plugins/catalog/alpha-api-report.md index e89807ac34..aba33fc092 100644 --- a/plugins/catalog/alpha-api-report.md +++ b/plugins/catalog/alpha-api-report.md @@ -3,8 +3,14 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +/// <reference types="react" /> + +import { AnyExtensionInputMap } from '@backstage/frontend-plugin-api'; import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } 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'; // @alpha (undocumented) export const CatalogApi: Extension<{}>; @@ -15,7 +21,45 @@ export const CatalogSearchResultListItemExtension: Extension<{ }>; // @alpha (undocumented) -const _default: BackstagePlugin; +export function createCatalogFilterExtension< + TInputs extends AnyExtensionInputMap, + TConfig = never, +>(options: { + id: string; + inputs?: TInputs; + configSchema?: PortableSchema<TConfig>; + loader: (options: { config: TConfig }) => Promise<JSX.Element>; +}): Extension<TConfig>; + +// @alpha (undocumented) +const _default: BackstagePlugin< + { + catalogIndex: RouteRef<undefined>; + catalogEntity: RouteRef<{ + name: string; + kind: string; + namespace: string; + }>; + }, + { + viewTechDoc: ExternalRouteRef< + { + name: string; + kind: string; + namespace: string; + }, + true + >; + createComponent: ExternalRouteRef<undefined, true>; + createFromTemplate: ExternalRouteRef< + { + namespace: string; + templateName: string; + }, + true + >; + } +>; export default _default; // @alpha (undocumented) diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index f779220669..56ae771314 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.14.0-next.1", + "version": "1.14.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -67,13 +67,12 @@ "history": "^5.0.0", "lodash": "^4.17.21", "pluralize": "^8.0.0", - "react-helmet": "6.1.0", "react-use": "^17.2.4", "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -82,9 +81,9 @@ "@backstage/dev-utils": "workspace:^", "@backstage/plugin-permission-react": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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" }, "files": [ diff --git a/plugins/catalog/src/alpha.tsx b/plugins/catalog/src/alpha.tsx index 5e78a52f9b..6eda8c3d26 100644 --- a/plugins/catalog/src/alpha.tsx +++ b/plugins/catalog/src/alpha.tsx @@ -14,23 +14,45 @@ * limitations under the License. */ +import React from 'react'; +import HomeIcon from '@material-ui/icons/Home'; import { createApiFactory, discoveryApiRef, fetchApiRef, storageApiRef, } from '@backstage/core-plugin-api'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; import { CatalogClient } from '@backstage/catalog-client'; import { + createSchemaFromZod, createApiExtension, + createPageExtension, createPlugin, + createNavItemExtension, + createExtension, + coreExtensionData, + AnyExtensionInputMap, + PortableSchema, + ExtensionBoundary, + createExtensionInput, } from '@backstage/frontend-plugin-api'; import { + AsyncEntityProvider, catalogApiRef, + entityRouteRef, starredEntitiesApiRef, } from '@backstage/plugin-catalog-react'; import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; import { DefaultStarredEntitiesApi } from './apis'; +import { + createComponentRouteRef, + createFromTemplateRouteRef, + rootRouteRef, + viewTechDocRouteRef, +} from './routes'; +import { Progress } from '@backstage/core-components'; +import { useEntityFromUrl } from './components/CatalogEntityPage/useEntityFromUrl'; /** @alpha */ export const CatalogApi = createApiExtension({ @@ -65,12 +87,200 @@ export const CatalogSearchResultListItemExtension = ), }); +/** @alpha */ +export function createCatalogFilterExtension< + TInputs extends AnyExtensionInputMap, + TConfig = never, +>(options: { + id: string; + inputs?: TInputs; + configSchema?: PortableSchema<TConfig>; + loader: (options: { config: TConfig }) => Promise<JSX.Element>; +}) { + return createExtension({ + id: `catalog.filter.${options.id}`, + attachTo: { id: 'plugin.catalog.page.index', input: 'filters' }, + inputs: options.inputs ?? {}, + configSchema: options.configSchema, + output: { + element: coreExtensionData.reactElement, + }, + factory({ bind, config, source }) { + const LazyComponent = React.lazy(() => + options + .loader({ config }) + .then(element => ({ default: () => element })), + ); + + bind({ + element: ( + <ExtensionBoundary source={source}> + <React.Suspense fallback={<Progress />}> + <LazyComponent /> + </React.Suspense> + </ExtensionBoundary> + ), + }); + }, + }); +} + +const CatalogEntityTagFilter = createCatalogFilterExtension({ + id: 'entity.tag', + loader: async () => { + const { EntityTagPicker } = await import('@backstage/plugin-catalog-react'); + return <EntityTagPicker />; + }, +}); + +const CatalogEntityKindFilter = createCatalogFilterExtension({ + id: 'entity.kind', + configSchema: createSchemaFromZod(z => + z.object({ + initialFilter: z.string().default('component'), + }), + ), + loader: async ({ config }) => { + const { EntityKindPicker } = await import( + '@backstage/plugin-catalog-react' + ); + return <EntityKindPicker initialFilter={config.initialFilter} />; + }, +}); + +const CatalogEntityTypeFilter = createCatalogFilterExtension({ + id: 'entity.type', + loader: async () => { + const { EntityTypePicker } = await import( + '@backstage/plugin-catalog-react' + ); + return <EntityTypePicker />; + }, +}); + +const CatalogEntityOwnerFilter = createCatalogFilterExtension({ + id: 'entity.mode', + configSchema: createSchemaFromZod(z => + z.object({ + mode: z.enum(['owners-only', 'all']).optional(), + }), + ), + loader: async ({ config }) => { + const { EntityOwnerPicker } = await import( + '@backstage/plugin-catalog-react' + ); + return <EntityOwnerPicker mode={config.mode} />; + }, +}); + +const CatalogEntityNamespaceFilter = createCatalogFilterExtension({ + id: 'entity.namespace', + loader: async () => { + const { EntityNamespacePicker } = await import( + '@backstage/plugin-catalog-react' + ); + return <EntityNamespacePicker />; + }, +}); + +const CatalogEntityLifecycleFilter = createCatalogFilterExtension({ + id: 'entity.lifecycle', + loader: async () => { + const { EntityLifecyclePicker } = await import( + '@backstage/plugin-catalog-react' + ); + return <EntityLifecyclePicker />; + }, +}); + +const CatalogEntityProcessingStatusFilter = createCatalogFilterExtension({ + id: 'entity.processing.status', + loader: async () => { + const { EntityProcessingStatusPicker } = await import( + '@backstage/plugin-catalog-react' + ); + return <EntityProcessingStatusPicker />; + }, +}); + +const CatalogUserListFilter = createCatalogFilterExtension({ + id: 'user.list', + configSchema: createSchemaFromZod(z => + z.object({ + initialFilter: z.enum(['owned', 'starred', 'all']).default('owned'), + }), + ), + loader: async ({ config }) => { + const { UserListPicker } = await import('@backstage/plugin-catalog-react'); + return <UserListPicker initialFilter={config.initialFilter} />; + }, +}); + +const CatalogIndexPage = createPageExtension({ + id: 'plugin.catalog.page.index', + defaultPath: '/catalog', + routeRef: convertLegacyRouteRef(rootRouteRef), + inputs: { + filters: createExtensionInput({ + element: coreExtensionData.reactElement, + }), + }, + loader: async ({ inputs }) => { + const { BaseCatalogPage } = await import('./components/CatalogPage'); + const filters = inputs.filters.map(filter => filter.element); + return <BaseCatalogPage filters={<>{filters}</>} />; + }, +}); + +const CatalogEntityPage = createPageExtension({ + id: 'plugin.catalog.page.entity', + defaultPath: '/catalog/:namespace/:kind/:name', + routeRef: convertLegacyRouteRef(entityRouteRef), + loader: async () => { + const Component = () => { + return ( + <AsyncEntityProvider {...useEntityFromUrl()}> + <div>🚧 Work In Progress</div> + </AsyncEntityProvider> + ); + }; + return <Component />; + }, +}); + +const CatalogNavItem = createNavItemExtension({ + id: 'catalog.nav.index', + routeRef: convertLegacyRouteRef(rootRouteRef), + title: 'Catalog', + icon: HomeIcon, +}); + /** @alpha */ export default createPlugin({ id: 'catalog', + routes: { + catalogIndex: convertLegacyRouteRef(rootRouteRef), + catalogEntity: convertLegacyRouteRef(entityRouteRef), + }, + externalRoutes: { + viewTechDoc: convertLegacyRouteRef(viewTechDocRouteRef), + createComponent: convertLegacyRouteRef(createComponentRouteRef), + createFromTemplate: convertLegacyRouteRef(createFromTemplateRouteRef), + }, extensions: [ CatalogApi, StarredEntitiesApi, CatalogSearchResultListItemExtension, + CatalogEntityKindFilter, + CatalogEntityTypeFilter, + CatalogUserListFilter, + CatalogEntityOwnerFilter, + CatalogEntityLifecycleFilter, + CatalogEntityTagFilter, + CatalogEntityProcessingStatusFilter, + CatalogEntityNamespaceFilter, + CatalogIndexPage, + CatalogEntityPage, + CatalogNavItem, ], }); diff --git a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx index fb9b282d57..e50c69b8ec 100644 --- a/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/DefaultCatalogPage.tsx @@ -44,6 +44,41 @@ import { CatalogTable, CatalogTableRow } from '../CatalogTable'; import { catalogTranslationRef } from '../../translation'; import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; +/** @internal */ +export interface BaseCatalogPageProps { + filters: ReactNode; + content?: ReactNode; +} + +/** @internal */ +export function BaseCatalogPage(props: BaseCatalogPageProps) { + const { filters, content = <CatalogTable /> } = props; + const orgName = + useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage'; + const createComponentLink = useRouteRef(createComponentRouteRef); + const { t } = useTranslationRef(catalogTranslationRef); + + return ( + <PageWithHeader title={t('catalog_page_title', { orgName })} themeId="home"> + <Content> + <ContentHeader title=""> + <CreateButton + title={t('catalog_page_create_button_title')} + to={createComponentLink && createComponentLink()} + /> + <SupportButton>All your software catalog entities</SupportButton> + </ContentHeader> + <EntityListProvider> + <CatalogFilterLayout> + <CatalogFilterLayout.Filters>{filters}</CatalogFilterLayout.Filters> + <CatalogFilterLayout.Content>{content}</CatalogFilterLayout.Content> + </CatalogFilterLayout> + </EntityListProvider> + </Content> + </PageWithHeader> + ); +} + /** * Props for root catalog pages. * @@ -69,44 +104,29 @@ export function DefaultCatalogPage(props: DefaultCatalogPageProps) { emptyContent, ownerPickerMode, } = props; - const orgName = - useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage'; - const createComponentLink = useRouteRef(createComponentRouteRef); - const { t } = useTranslationRef(catalogTranslationRef); return ( - <PageWithHeader title={t('catalog_page_title', { orgName })} themeId="home"> - <Content> - <ContentHeader title=""> - <CreateButton - title={t('catalog_page_create_button_title')} - to={createComponentLink && createComponentLink()} - /> - <SupportButton>All your software catalog entities</SupportButton> - </ContentHeader> - <EntityListProvider> - <CatalogFilterLayout> - <CatalogFilterLayout.Filters> - <EntityKindPicker initialFilter={initialKind} /> - <EntityTypePicker /> - <UserListPicker initialFilter={initiallySelectedFilter} /> - <EntityOwnerPicker mode={ownerPickerMode} /> - <EntityLifecyclePicker /> - <EntityTagPicker /> - <EntityProcessingStatusPicker /> - <EntityNamespacePicker /> - </CatalogFilterLayout.Filters> - <CatalogFilterLayout.Content> - <CatalogTable - columns={columns} - actions={actions} - tableOptions={tableOptions} - emptyContent={emptyContent} - /> - </CatalogFilterLayout.Content> - </CatalogFilterLayout> - </EntityListProvider> - </Content> - </PageWithHeader> + <BaseCatalogPage + filters={ + <> + <EntityKindPicker initialFilter={initialKind} /> + <EntityTypePicker /> + <UserListPicker initialFilter={initiallySelectedFilter} /> + <EntityOwnerPicker mode={ownerPickerMode} /> + <EntityLifecyclePicker /> + <EntityTagPicker /> + <EntityProcessingStatusPicker /> + <EntityNamespacePicker /> + </> + } + content={ + <CatalogTable + columns={columns} + actions={actions} + tableOptions={tableOptions} + emptyContent={emptyContent} + /> + } + /> ); } diff --git a/plugins/catalog/src/components/CatalogPage/index.ts b/plugins/catalog/src/components/CatalogPage/index.ts index 9a3d083f41..258fedf15c 100644 --- a/plugins/catalog/src/components/CatalogPage/index.ts +++ b/plugins/catalog/src/components/CatalogPage/index.ts @@ -15,5 +15,8 @@ */ export { CatalogPage } from './CatalogPage'; -export { DefaultCatalogPage } from './DefaultCatalogPage'; -export type { DefaultCatalogPageProps } from './DefaultCatalogPage'; +export { BaseCatalogPage, DefaultCatalogPage } from './DefaultCatalogPage'; +export type { + BaseCatalogPageProps, + DefaultCatalogPageProps, +} from './DefaultCatalogPage'; diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx index a190984ffe..9505dad889 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx @@ -128,7 +128,10 @@ function EntityLabels(props: { entity: Entity }) { /> )} {entity.spec?.lifecycle && ( - <HeaderLabel label="Lifecycle" value={entity.spec.lifecycle} /> + <HeaderLabel + label="Lifecycle" + value={entity.spec.lifecycle?.toString()} + /> )} </> ); diff --git a/plugins/catalog/src/components/EntitySwitch/EntitySwitch.test.tsx b/plugins/catalog/src/components/EntitySwitch/EntitySwitch.test.tsx index d9998b0ca5..aebdd6b9c2 100644 --- a/plugins/catalog/src/components/EntitySwitch/EntitySwitch.test.tsx +++ b/plugins/catalog/src/components/EntitySwitch/EntitySwitch.test.tsx @@ -19,7 +19,7 @@ import { AsyncEntityProvider, EntityProvider, } from '@backstage/plugin-catalog-react'; -import { render, screen, waitFor } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import React, { useEffect } from 'react'; import { isKind } from './conditions'; import { EntitySwitch } from './EntitySwitch'; @@ -517,9 +517,7 @@ describe('EntitySwitch', () => { </Wrapper>, ); - await waitFor(() => expect(shouldRender).toHaveBeenCalled()); - - expect(screen.getByText('C')).toBeInTheDocument(); + await expect(screen.findByText('C')).resolves.toBeInTheDocument(); expect(screen.queryByText('A')).not.toBeInTheDocument(); expect(screen.queryByText('B')).not.toBeInTheDocument(); }); diff --git a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md index a1952616bb..b0cb0fb020 100644 --- a/plugins/cicd-statistics-module-gitlab/CHANGELOG.md +++ b/plugins/cicd-statistics-module-gitlab/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-cicd-statistics-module-gitlab +## 0.1.21 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-cicd-statistics@0.1.27 + - @backstage/catalog-model@1.4.3 + +## 0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/plugin-cicd-statistics@0.1.27-next.2 + - @backstage/catalog-model@1.4.3-next.0 + ## 0.1.21-next.1 ### Patch Changes diff --git a/plugins/cicd-statistics-module-gitlab/package.json b/plugins/cicd-statistics-module-gitlab/package.json index afdd1cd758..6c7f3c150f 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.21-next.1", + "version": "0.1.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -43,8 +43,8 @@ "p-limit": "^4.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/cicd-statistics/CHANGELOG.md b/plugins/cicd-statistics/CHANGELOG.md index 4abb69de10..9fe1717192 100644 --- a/plugins/cicd-statistics/CHANGELOG.md +++ b/plugins/cicd-statistics/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-cicd-statistics +## 0.1.27 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + +## 0.1.27-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + ## 0.1.27-next.1 ### Patch Changes diff --git a/plugins/cicd-statistics/catalog-info.yaml b/plugins/cicd-statistics/catalog-info.yaml index 83021cc033..eab84c1283 100644 --- a/plugins/cicd-statistics/catalog-info.yaml +++ b/plugins/cicd-statistics/catalog-info.yaml @@ -7,4 +7,4 @@ metadata: spec: lifecycle: experimental type: backstage-frontend-plugin - owner: maintainers + owner: sharks diff --git a/plugins/cicd-statistics/package.json b/plugins/cicd-statistics/package.json index 60668da35a..fb8b736035 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.27-next.1", + "version": "0.1.27", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -50,13 +50,12 @@ "humanize-duration": "^3.27.0", "lodash": "^4.17.21", "luxon": "^3.0.0", - "prop-types": "^15.7.2", "react-use": "^17.3.1", "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "files": [ diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index 38e797dc35..c8ba1ae27f 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-circleci +## 0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 0.3.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + ## 0.3.25-next.1 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index c1c4c07004..ddec70c2de 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.25-next.1", + "version": "0.3.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -50,8 +50,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -59,9 +59,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/humanize-duration": "^3.25.1", "cross-fetch": "^3.1.5", diff --git a/plugins/circleci/src/setupTests.ts b/plugins/circleci/src/setupTests.ts index 83a0078a28..d3232290a7 100644 --- a/plugins/circleci/src/setupTests.ts +++ b/plugins/circleci/src/setupTests.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -import '@testing-library/jest-dom/extend-expect'; +export {}; diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index 3affd61ba7..a322da009c 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-cloudbuild +## 0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 0.3.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + ## 0.3.25-next.1 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index d09f2372ab..8b64387aa8 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.25-next.1", + "version": "0.3.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -57,9 +57,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/code-climate/CHANGELOG.md b/plugins/code-climate/CHANGELOG.md index 9e32befc60..65dda2e3f5 100644 --- a/plugins/code-climate/CHANGELOG.md +++ b/plugins/code-climate/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-code-climate +## 0.1.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 0.1.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + ## 0.1.25-next.1 ### Patch Changes diff --git a/plugins/code-climate/package.json b/plugins/code-climate/package.json index 800c97652f..dc01c52a13 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.25-next.1", + "version": "0.1.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -43,17 +43,17 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/humanize-duration": "^3.27.1", "@types/luxon": "^3.0.0", diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index 817fe0d57d..2cc9d85f3b 100644 --- a/plugins/code-coverage-backend/CHANGELOG.md +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-code-coverage-backend +## 0.2.20 + +### Patch Changes + +- 4aa27aa200: Added option to set body size limit +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + +## 0.2.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + ## 0.2.19-next.1 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 761fccda23..9ee98d52ad 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.19-next.1", + "version": "0.2.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/code-coverage-backend/src/service/standaloneServer.ts b/plugins/code-coverage-backend/src/service/standaloneServer.ts index 23eaf981c1..a2207b86d9 100644 --- a/plugins/code-coverage-backend/src/service/standaloneServer.ts +++ b/plugins/code-coverage-backend/src/service/standaloneServer.ts @@ -16,17 +16,17 @@ import { createServiceBuilder, + DatabaseManager, HostDiscovery, loadBackendConfig, UrlReaders, - useHotMemoize, } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; import { CompoundEntityRef, parseEntityRef } from '@backstage/catalog-model'; import { Server } from 'http'; -import knexFactory from 'knex'; import { Logger } from 'winston'; import { createRouter } from './router'; +import { ConfigReader } from '@backstage/config'; export interface ServerOptions { port: number; @@ -40,19 +40,14 @@ export async function startStandaloneServer( const logger = options.logger.child({ service: 'code-coverage-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); - const db = useHotMemoize(module, () => { - const knex = knexFactory({ - client: 'better-sqlite3', - connection: ':memory:', - useNullAsDefault: true, - }); - - knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { - resource.run('PRAGMA foreign_keys = ON', () => {}); - }); - - return knex; - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('code-coverage'); const catalogApi = { async getEntityByRef(entityRef: string | CompoundEntityRef) { @@ -69,7 +64,7 @@ export async function startStandaloneServer( logger.debug('Starting application server...'); const router = await createRouter({ - database: { getClient: async () => db }, + database, config, discovery: HostDiscovery.fromConfig(config), urlReader: UrlReaders.default({ logger, config }), diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md index 3801f63f61..f5ba60eeb4 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-code-coverage +## 0.2.18 + +### Patch Changes + +- 88b0b32547: Fixed the coverage history statistics to compare newest with oldest record +- 0296f272b4: The warning for missing code coverage will now render the entity as a reference. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- a468544fa9: Updated layout to improve contrasts and consistency with other plugins +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## 0.2.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + ## 0.2.18-next.1 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index f47a44221a..15343a8212 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.18-next.1", + "version": "0.2.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -47,8 +47,8 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -56,9 +56,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/highlightjs": "^10.1.0", "@types/react": "^16.13.1 || ^17.0.0", diff --git a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx index 4017ba8264..57bb9a2be0 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { useEntity } from '@backstage/plugin-catalog-react'; +import { humanizeEntityRef, useEntity } from '@backstage/plugin-catalog-react'; import { Box, Modal, makeStyles } from '@material-ui/core'; import FolderIcon from '@material-ui/icons/Folder'; import FileOutlinedIcon from '@material-ui/icons/InsertDriveFileOutlined'; @@ -181,7 +181,9 @@ export const FileExplorer = () => { } if (!value) { return ( - <Alert severity="warning">No code coverage found for ${entity}</Alert> + <Alert severity="warning"> + No code coverage found for {humanizeEntityRef(entity)} + </Alert> ); } diff --git a/plugins/codescene/CHANGELOG.md b/plugins/codescene/CHANGELOG.md index 15f34acaf0..29f0700e65 100644 --- a/plugins/codescene/CHANGELOG.md +++ b/plugins/codescene/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-codescene +## 0.1.18 + +### Patch Changes + +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## 0.1.18-next.2 + +### Patch Changes + +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + ## 0.1.18-next.1 ### Patch Changes diff --git a/plugins/codescene/README.md b/plugins/codescene/README.md index fa44506964..bbfb58e68f 100644 --- a/plugins/codescene/README.md +++ b/plugins/codescene/README.md @@ -2,8 +2,6 @@ [CodeScene](https://codescene.com/) is a multi-purpose tool bridging code, business and people. See hidden risks and social patterns in your code. Prioritize and reduce technical debt. -![codescene-logo](./src/assets/codescene.icon.svg) - The CodeScene Backstage Plugin exposes a page component that will list the existing projects and their analysis data on your CodeScene instance. ![screenshot](./docs/codescene-plugin-screenshot.png) diff --git a/plugins/codescene/dev/index.tsx b/plugins/codescene/dev/index.tsx index 28ef638131..e6074f74fc 100644 --- a/plugins/codescene/dev/index.tsx +++ b/plugins/codescene/dev/index.tsx @@ -20,11 +20,13 @@ import { CodeScenePage, CodeSceneProjectDetailsPage, } from '../src/plugin'; +import { CodeSceneIcon } from '../src'; createDevApp() .registerPlugin(codescenePlugin) .addPage({ element: <CodeScenePage />, + icon: CodeSceneIcon, title: 'Root Page', path: '/codescene', }) diff --git a/plugins/codescene/package.json b/plugins/codescene/package.json index c57a9c53af..e36c8e5575 100644 --- a/plugins/codescene/package.json +++ b/plugins/codescene/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-codescene", - "version": "0.1.18-next.1", + "version": "0.1.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -42,8 +42,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -51,9 +51,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/codescene/src/CodeSceneIcon.tsx b/plugins/codescene/src/CodeSceneIcon.tsx new file mode 100644 index 0000000000..ac694126da --- /dev/null +++ b/plugins/codescene/src/CodeSceneIcon.tsx @@ -0,0 +1,31 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import SvgIcon from '@material-ui/core/SvgIcon'; +import { IconComponent } from '@backstage/core-plugin-api'; + +/** + * @public + */ +export const CodeSceneIcon: IconComponent = () => ( + <SvgIcon> + <g> + <path d="M 21.898438 6.167969 C 20.5 2.242188 17.015625 0.00390625 12.003906 0.00390625 C 6.988281 0.00390625 3.5 2.242188 2.101562 6.167969 C 0.894531 6.589844 0 8.871094 0 11.707031 C 0 14.855469 1.101562 17.320312 2.511719 17.320312 C 2.542969 17.320312 2.574219 17.320312 2.605469 17.316406 C 3.089844 18.292969 3.722656 19.042969 4.511719 19.585938 C 6.425781 20.90625 9.085938 20.996094 11.886719 20.996094 L 12.113281 20.996094 C 12.148438 20.996094 12.183594 20.996094 12.21875 20.996094 C 14.988281 20.996094 17.601562 20.886719 19.488281 19.585938 C 20.277344 19.042969 20.914062 18.292969 21.394531 17.316406 C 21.425781 17.320312 21.457031 17.320312 21.488281 17.320312 C 22.898438 17.320312 24 14.855469 24 11.707031 C 24 8.871094 23.105469 6.589844 21.898438 6.167969 Z M 0.46875 11.707031 C 0.46875 9.285156 1.125 7.496094 1.886719 6.847656 C 1.578125 7.9375 1.417969 9.140625 1.417969 10.453125 C 1.417969 13.144531 1.730469 15.242188 2.382812 16.824219 C 1.4375 16.660156 0.46875 14.648438 0.46875 11.707031 Z M 21.132812 16.75 C 21.066406 16.902344 21 17.046875 20.929688 17.183594 C 20.488281 18.039062 19.921875 18.703125 19.222656 19.1875 C 17.453125 20.40625 15.03125 20.535156 12.226562 20.535156 C 12.1875 20.535156 12.148438 20.535156 12.113281 20.535156 L 11.886719 20.535156 C 9.03125 20.535156 6.566406 20.425781 4.777344 19.1875 C 4.078125 18.703125 3.515625 18.039062 3.070312 17.183594 C 3 17.046875 2.933594 16.902344 2.867188 16.75 C 2.207031 15.226562 1.886719 13.15625 1.886719 10.453125 C 1.886719 9.023438 2.085938 7.730469 2.46875 6.582031 C 2.519531 6.417969 2.582031 6.257812 2.640625 6.101562 C 4.035156 2.523438 7.320312 0.484375 12 0.484375 C 16.679688 0.484375 19.964844 2.523438 21.359375 6.101562 C 21.421875 6.257812 21.480469 6.417969 21.53125 6.582031 C 21.914062 7.730469 22.113281 9.023438 22.113281 10.453125 C 22.113281 13.15625 21.792969 15.222656 21.132812 16.75 Z M 21.617188 16.824219 C 22.269531 15.246094 22.582031 13.148438 22.582031 10.453125 C 22.582031 9.140625 22.421875 7.9375 22.113281 6.847656 C 22.875 7.5 23.53125 9.289062 23.53125 11.710938 C 23.53125 14.648438 22.5625 16.660156 21.617188 16.824219 Z M 21.617188 16.824219 " /> + <path d="M 12 3.476562 C 5.652344 3.476562 2.824219 6.046875 2.824219 11.816406 C 2.824219 17.425781 5.824219 20.152344 12 20.152344 C 18.175781 20.152344 21.175781 17.425781 21.175781 11.816406 C 21.175781 6.046875 18.347656 3.476562 12 3.476562 Z M 12 19.671875 C 6.058594 19.671875 3.292969 17.175781 3.292969 11.8125 C 3.292969 8.152344 4.28125 3.953125 12 3.953125 C 19.71875 3.953125 20.707031 8.152344 20.707031 11.8125 C 20.707031 17.175781 17.941406 19.671875 12 19.671875 Z M 12 19.671875 " /> + </g> + </SvgIcon> +); diff --git a/plugins/codescene/src/assets/codescene.icon.svg b/plugins/codescene/src/assets/codescene.icon.svg deleted file mode 100644 index e8102a4116..0000000000 --- a/plugins/codescene/src/assets/codescene.icon.svg +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 21" version="1.1"> -<g id="surface1"> -<path d="M 21.898438 6.167969 C 20.5 2.242188 17.015625 0.00390625 12.003906 0.00390625 C 6.988281 0.00390625 3.5 2.242188 2.101562 6.167969 C 0.894531 6.589844 0 8.871094 0 11.707031 C 0 14.855469 1.101562 17.320312 2.511719 17.320312 C 2.542969 17.320312 2.574219 17.320312 2.605469 17.316406 C 3.089844 18.292969 3.722656 19.042969 4.511719 19.585938 C 6.425781 20.90625 9.085938 20.996094 11.886719 20.996094 L 12.113281 20.996094 C 12.148438 20.996094 12.183594 20.996094 12.21875 20.996094 C 14.988281 20.996094 17.601562 20.886719 19.488281 19.585938 C 20.277344 19.042969 20.914062 18.292969 21.394531 17.316406 C 21.425781 17.320312 21.457031 17.320312 21.488281 17.320312 C 22.898438 17.320312 24 14.855469 24 11.707031 C 24 8.871094 23.105469 6.589844 21.898438 6.167969 Z M 0.46875 11.707031 C 0.46875 9.285156 1.125 7.496094 1.886719 6.847656 C 1.578125 7.9375 1.417969 9.140625 1.417969 10.453125 C 1.417969 13.144531 1.730469 15.242188 2.382812 16.824219 C 1.4375 16.660156 0.46875 14.648438 0.46875 11.707031 Z M 21.132812 16.75 C 21.066406 16.902344 21 17.046875 20.929688 17.183594 C 20.488281 18.039062 19.921875 18.703125 19.222656 19.1875 C 17.453125 20.40625 15.03125 20.535156 12.226562 20.535156 C 12.1875 20.535156 12.148438 20.535156 12.113281 20.535156 L 11.886719 20.535156 C 9.03125 20.535156 6.566406 20.425781 4.777344 19.1875 C 4.078125 18.703125 3.515625 18.039062 3.070312 17.183594 C 3 17.046875 2.933594 16.902344 2.867188 16.75 C 2.207031 15.226562 1.886719 13.15625 1.886719 10.453125 C 1.886719 9.023438 2.085938 7.730469 2.46875 6.582031 C 2.519531 6.417969 2.582031 6.257812 2.640625 6.101562 C 4.035156 2.523438 7.320312 0.484375 12 0.484375 C 16.679688 0.484375 19.964844 2.523438 21.359375 6.101562 C 21.421875 6.257812 21.480469 6.417969 21.53125 6.582031 C 21.914062 7.730469 22.113281 9.023438 22.113281 10.453125 C 22.113281 13.15625 21.792969 15.222656 21.132812 16.75 Z M 21.617188 16.824219 C 22.269531 15.246094 22.582031 13.148438 22.582031 10.453125 C 22.582031 9.140625 22.421875 7.9375 22.113281 6.847656 C 22.875 7.5 23.53125 9.289062 23.53125 11.710938 C 23.53125 14.648438 22.5625 16.660156 21.617188 16.824219 Z M 21.617188 16.824219 "/> -<path d="M 12 3.476562 C 5.652344 3.476562 2.824219 6.046875 2.824219 11.816406 C 2.824219 17.425781 5.824219 20.152344 12 20.152344 C 18.175781 20.152344 21.175781 17.425781 21.175781 11.816406 C 21.175781 6.046875 18.347656 3.476562 12 3.476562 Z M 12 19.671875 C 6.058594 19.671875 3.292969 17.175781 3.292969 11.8125 C 3.292969 8.152344 4.28125 3.953125 12 3.953125 C 19.71875 3.953125 20.707031 8.152344 20.707031 11.8125 C 20.707031 17.175781 17.941406 19.671875 12 19.671875 Z M 12 19.671875 "/> -</g> -</svg> diff --git a/plugins/codescene/src/index.ts b/plugins/codescene/src/index.ts index 355ff4eb31..301b4377a7 100644 --- a/plugins/codescene/src/index.ts +++ b/plugins/codescene/src/index.ts @@ -18,11 +18,4 @@ export { CodeScenePage, CodeSceneProjectDetailsPage, } from './plugin'; -import CodeSceneIconComponent from './assets/codescene.icon.svg'; -import { IconComponent } from '@backstage/core-plugin-api'; - -/** - * @public - */ -export const CodeSceneIcon: IconComponent = - CodeSceneIconComponent as IconComponent; +export { CodeSceneIcon } from './CodeSceneIcon'; diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index 2c2ac53154..3e09c6dd98 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-config-schema +## 0.1.46 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.1.46-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + ## 0.1.46-next.1 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index c623a59dfa..387921650b 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.46-next.1", + "version": "0.1.46", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,8 +45,8 @@ "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -54,9 +54,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index a51c19f324..a60e531966 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-cost-insights +## 0.12.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- ba4820883c: Updated dependency `@types/pluralize` to `^0.0.31`. +- 959aa2a09f: The experimental plugin configuration has been removed. The trend line can now instead be hidden by setting `costInsights.hideTrendLine` to `true` in the configuration. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-cost-insights-common@0.1.2 + +## 0.12.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-cost-insights-common@0.1.2 + ## 0.12.14-next.1 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index c204616fe4..5cd7c3458b 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.14-next.1", + "version": "0.12.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -57,8 +57,8 @@ "yup": "^0.32.9" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -66,9 +66,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/pluralize": "^0.0.31", "@types/recharts": "^1.8.14", diff --git a/plugins/cost-insights/src/components/BarChart/BarChartTooltip.test.tsx b/plugins/cost-insights/src/components/BarChart/BarChartTooltip.test.tsx index 3a6dca9417..4e255917d8 100644 --- a/plugins/cost-insights/src/components/BarChart/BarChartTooltip.test.tsx +++ b/plugins/cost-insights/src/components/BarChart/BarChartTooltip.test.tsx @@ -33,8 +33,9 @@ const items = [ }, ]; -const tooltipItems = () => - items.map(item => <BarChartTooltipItem key={item.label} item={item} />); +const tooltipItems = items.map(item => ( + <BarChartTooltipItem key={item.label} item={item} /> +)); describe('<BarChartTooltip/>', () => { it('formats label and tooltip item text correctly', async () => { diff --git a/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx b/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx index 7dd5b4253f..3a2f30bbfe 100644 --- a/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx +++ b/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React from 'react'; +import React, { ComponentType } from 'react'; import { getByRole, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { ProjectSelect } from './ProjectSelect'; @@ -28,7 +28,7 @@ const mockProjects = [ ]; describe('<ProjectSelect />', () => { - let Component: React.ReactNode; + let Component: ComponentType; beforeEach(() => { Component = () => ( <MockFilterProvider> diff --git a/plugins/devtools-backend/CHANGELOG.md b/plugins/devtools-backend/CHANGELOG.md index 7fc9c01be5..fd9108d28d 100644 --- a/plugins/devtools-backend/CHANGELOG.md +++ b/plugins/devtools-backend/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-devtools-backend +## 0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/config-loader@1.5.1 + - @backstage/errors@1.2.3 + - @backstage/cli-common@0.1.13 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.5 + - @backstage/plugin-permission-common@0.7.9 + +## 0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/config-loader@1.5.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/cli-common@0.1.13-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.5-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 0.2.2-next.1 ### Patch Changes diff --git a/plugins/devtools-backend/package.json b/plugins/devtools-backend/package.json index f5311f9cf3..acf7788d8c 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.2-next.1", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/devtools-backend/src/service/standaloneServer.ts b/plugins/devtools-backend/src/service/standaloneServer.ts index d2fdce169d..43edb47935 100644 --- a/plugins/devtools-backend/src/service/standaloneServer.ts +++ b/plugins/devtools-backend/src/service/standaloneServer.ts @@ -16,7 +16,7 @@ import { ServerTokenManager, - SingleHostDiscovery, + HostDiscovery, createServiceBuilder, loadBackendConfig, } from '@backstage/backend-common'; @@ -37,7 +37,7 @@ export async function startStandaloneServer( ): Promise<Server> { const logger = options.logger.child({ service: 'devtools-backend-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); - const discovery = SingleHostDiscovery.fromConfig(config); + const discovery = HostDiscovery.fromConfig(config); const tokenManager = ServerTokenManager.fromConfig(config, { logger, }); diff --git a/plugins/devtools-common/CHANGELOG.md b/plugins/devtools-common/CHANGELOG.md index 4e1f15afcf..4a95434b3d 100644 --- a/plugins/devtools-common/CHANGELOG.md +++ b/plugins/devtools-common/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-devtools-common +## 0.1.5 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## 0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 0.1.4 ### Patch Changes diff --git a/plugins/devtools-common/package.json b/plugins/devtools-common/package.json index bde9934ffa..703ad2a5e3 100644 --- a/plugins/devtools-common/package.json +++ b/plugins/devtools-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-devtools-common", "description": "Common functionalities for the devtools plugin", - "version": "0.1.4", + "version": "0.1.5", "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 b858ff2c61..b200af4d82 100644 --- a/plugins/devtools/CHANGELOG.md +++ b/plugins/devtools/CHANGELOG.md @@ -1,5 +1,32 @@ # @backstage/plugin-devtools +## 0.1.5 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.5 + +## 0.1.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-devtools-common@0.1.5-next.0 + - @backstage/plugin-permission-react@0.4.16-next.1 + ## 0.1.5-next.1 ### Patch Changes diff --git a/plugins/devtools/package.json b/plugins/devtools/package.json index 62ba643765..41ea821dea 100644 --- a/plugins/devtools/package.json +++ b/plugins/devtools/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools", - "version": "0.1.5-next.1", + "version": "0.1.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -44,8 +44,8 @@ }, "peerDependencies": { "@types/react": "^16.13.1 || ^17.0.0", - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -53,8 +53,8 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/dynatrace/CHANGELOG.md b/plugins/dynatrace/CHANGELOG.md index dc1c8cd54d..2de9b4555b 100644 --- a/plugins/dynatrace/CHANGELOG.md +++ b/plugins/dynatrace/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-dynatrace +## 7.0.5 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 7.0.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + ## 7.0.5-next.1 ### Patch Changes diff --git a/plugins/dynatrace/README.md b/plugins/dynatrace/README.md index b03e65473f..9143b0ff9c 100644 --- a/plugins/dynatrace/README.md +++ b/plugins/dynatrace/README.md @@ -109,6 +109,10 @@ The annotation can also contain a comma or space separated list of Synthetic Ids The `SYNTHETIC_ID` can be found in Dynatrace by browsing to the Synthetic monitor. It will be located in the browser address bar in the resource path - `https://example.dynatrace.com/ui/http-monitor/HTTP_CHECK-1234` for an Http check, or `https://example.dynatrace.com/ui/browser-monitor/SYNTHETIC_TEST-1234` for a browser clickpath. +## Contribution + +This plugin was originally built by [TELUS](https://github.com/telus). + ## Disclaimer This plugin is not officially supported by Dynatrace. diff --git a/plugins/dynatrace/catalog-info.yaml b/plugins/dynatrace/catalog-info.yaml index 3dc14c96ff..64d6d5f845 100644 --- a/plugins/dynatrace/catalog-info.yaml +++ b/plugins/dynatrace/catalog-info.yaml @@ -4,6 +4,6 @@ metadata: name: backstage-plugin-dynatrace title: '@backstage/plugin-dynatrace' spec: - lifecycle: experimental + lifecycle: production type: backstage-frontend-plugin owner: maintainers diff --git a/plugins/dynatrace/package.json b/plugins/dynatrace/package.json index 83395cabb8..f8b35eafaa 100644 --- a/plugins/dynatrace/package.json +++ b/plugins/dynatrace/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-dynatrace", - "version": "7.0.5-next.1", + "version": "7.0.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -41,8 +41,8 @@ }, "peerDependencies": { "@backstage/plugin-catalog-react": "workspace:^", - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -50,9 +50,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "express": "^4.18.1", "msw": "^1.0.0" diff --git a/plugins/entity-feedback-backend/CHANGELOG.md b/plugins/entity-feedback-backend/CHANGELOG.md index 8c0b27d2aa..acfdaf360f 100644 --- a/plugins/entity-feedback-backend/CHANGELOG.md +++ b/plugins/entity-feedback-backend/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-entity-feedback-backend +## 0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## 0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-entity-feedback-common@0.1.3 + ## 0.2.2-next.1 ### Patch Changes diff --git a/plugins/entity-feedback-backend/package.json b/plugins/entity-feedback-backend/package.json index 320748501f..c493be7075 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.2-next.1", + "version": "0.2.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/entity-feedback-backend/src/service/standaloneServer.ts b/plugins/entity-feedback-backend/src/service/standaloneServer.ts index 9395c72141..27c48ebb1e 100644 --- a/plugins/entity-feedback-backend/src/service/standaloneServer.ts +++ b/plugins/entity-feedback-backend/src/service/standaloneServer.ts @@ -18,8 +18,7 @@ import { createServiceBuilder, DatabaseManager, loadBackendConfig, - SingleHostDiscovery, - useHotMemoize, + HostDiscovery, } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; @@ -38,18 +37,16 @@ export async function startStandaloneServer( ): Promise<Server> { const logger = options.logger.child({ service: 'entity-feedback-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); - const discovery = SingleHostDiscovery.fromConfig(config); + const discovery = HostDiscovery.fromConfig(config); - const database = useHotMemoize(module, () => { - const manager = DatabaseManager.fromConfig( - new ConfigReader({ - backend: { - database: { client: 'better-sqlite3', connection: ':memory:' }, - }, - }), - ); - return manager.forPlugin('entity-feedback'); - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('entity-feedback'); const identity = DefaultIdentityClient.create({ discovery, diff --git a/plugins/entity-feedback/CHANGELOG.md b/plugins/entity-feedback/CHANGELOG.md index c5ead7f611..469ff16ca2 100644 --- a/plugins/entity-feedback/CHANGELOG.md +++ b/plugins/entity-feedback/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-entity-feedback +## 0.2.8 + +### Patch Changes + +- 48c8b93e98: Added tooltip to like dislike buttons +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-entity-feedback-common@0.1.3 + +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-entity-feedback-common@0.1.3 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/entity-feedback/package.json b/plugins/entity-feedback/package.json index b04e438e34..f2a4697454 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.8-next.1", + "version": "0.2.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -52,10 +52,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.0.1", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/entity-feedback/src/components/LikeDislikeButtons/LikeDislikeButtons.tsx b/plugins/entity-feedback/src/components/LikeDislikeButtons/LikeDislikeButtons.tsx index 2d38e60ac2..6c634deefb 100644 --- a/plugins/entity-feedback/src/components/LikeDislikeButtons/LikeDislikeButtons.tsx +++ b/plugins/entity-feedback/src/components/LikeDislikeButtons/LikeDislikeButtons.tsx @@ -24,6 +24,7 @@ import { } from '@backstage/core-plugin-api'; import { useAsyncEntity } from '@backstage/plugin-catalog-react'; import { IconButton } from '@material-ui/core'; +import Tooltip from '@material-ui/core/Tooltip'; import ThumbDownIcon from '@material-ui/icons/ThumbDown'; import ThumbUpIcon from '@material-ui/icons/ThumbUp'; import ThumbDownOutlinedIcon from '@material-ui/icons/ThumbDownOutlined'; @@ -127,9 +128,13 @@ export const LikeDislikeButtons = (props: LikeDislikeButtonsProps) => { onClick={() => applyRating(FeedbackRatings.like)} > {rating === FeedbackRatings.like ? ( - <ThumbUpIcon fontSize="small" /> + <Tooltip title="Liked"> + <ThumbUpIcon fontSize="small" /> + </Tooltip> ) : ( - <ThumbUpOutlinedIcon fontSize="small" /> + <Tooltip title="Like"> + <ThumbUpOutlinedIcon fontSize="small" /> + </Tooltip> )} </IconButton> <IconButton @@ -137,9 +142,13 @@ export const LikeDislikeButtons = (props: LikeDislikeButtonsProps) => { onClick={() => applyRating(FeedbackRatings.dislike)} > {rating === FeedbackRatings.dislike ? ( - <ThumbDownIcon fontSize="small" /> + <Tooltip title="Disliked"> + <ThumbDownIcon fontSize="small" /> + </Tooltip> ) : ( - <ThumbDownOutlinedIcon fontSize="small" /> + <Tooltip title="Dislike"> + <ThumbDownOutlinedIcon fontSize="small" /> + </Tooltip> )} </IconButton> <FeedbackResponseDialog diff --git a/plugins/entity-validation/CHANGELOG.md b/plugins/entity-validation/CHANGELOG.md index 0cb48bd911..4aeb6cfd03 100644 --- a/plugins/entity-validation/CHANGELOG.md +++ b/plugins/entity-validation/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-entity-validation +## 0.1.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/plugin-catalog-common@1.0.17 + +## 0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + ## 0.1.10-next.1 ### Patch Changes diff --git a/plugins/entity-validation/package.json b/plugins/entity-validation/package.json index 5f8368aeb0..1fee0c7892 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.10-next.1", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -51,8 +51,8 @@ "yaml": "^2.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -60,9 +60,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/events-backend-module-aws-sqs/CHANGELOG.md b/plugins/events-backend-module-aws-sqs/CHANGELOG.md index c45de40839..304271a0a4 100644 --- a/plugins/events-backend-module-aws-sqs/CHANGELOG.md +++ b/plugins/events-backend-module-aws-sqs/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-events-backend-module-aws-sqs +## 0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.15 + +## 0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-events-node@0.2.15-next.2 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-aws-sqs/package.json b/plugins/events-backend-module-aws-sqs/package.json index c9825edbff..a114136c7e 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.8-next.1", + "version": "0.2.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-azure/CHANGELOG.md b/plugins/events-backend-module-azure/CHANGELOG.md index 4883d87b10..593b77bdf3 100644 --- a/plugins/events-backend-module-azure/CHANGELOG.md +++ b/plugins/events-backend-module-azure/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-events-backend-module-azure +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-events-node@0.2.15 + +## 0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/plugin-events-node@0.2.15-next.2 + ## 0.1.15-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-azure/package.json b/plugins/events-backend-module-azure/package.json index 18d712e5c4..175f952a4b 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.15-next.1", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md index 21b4e7e6ca..2bfd659892 100644 --- a/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/events-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-events-backend-module-bitbucket-cloud +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-events-node@0.2.15 + +## 0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/plugin-events-node@0.2.15-next.2 + ## 0.1.15-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-bitbucket-cloud/package.json b/plugins/events-backend-module-bitbucket-cloud/package.json index 5d6563e8b6..e81bea9415 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.15-next.1", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gerrit/CHANGELOG.md b/plugins/events-backend-module-gerrit/CHANGELOG.md index aa368e48e4..fd49c7df3b 100644 --- a/plugins/events-backend-module-gerrit/CHANGELOG.md +++ b/plugins/events-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-events-backend-module-gerrit +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-events-node@0.2.15 + +## 0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/plugin-events-node@0.2.15-next.2 + ## 0.1.15-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-gerrit/package.json b/plugins/events-backend-module-gerrit/package.json index 9b05753c42..d30063e14f 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.15-next.1", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-github/CHANGELOG.md b/plugins/events-backend-module-github/CHANGELOG.md index 16979ed40b..f87a77ea7e 100644 --- a/plugins/events-backend-module-github/CHANGELOG.md +++ b/plugins/events-backend-module-github/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-events-backend-module-github +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + +## 0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-events-node@0.2.15-next.2 + ## 0.1.15-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-github/package.json b/plugins/events-backend-module-github/package.json index c6cce93bda..bf9caa3bfd 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.15-next.1", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-module-gitlab/CHANGELOG.md b/plugins/events-backend-module-gitlab/CHANGELOG.md index 24f8a1c574..90f9ce8e5d 100644 --- a/plugins/events-backend-module-gitlab/CHANGELOG.md +++ b/plugins/events-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-events-backend-module-gitlab +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + +## 0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-events-node@0.2.15-next.2 + ## 0.1.15-next.1 ### Patch Changes diff --git a/plugins/events-backend-module-gitlab/package.json b/plugins/events-backend-module-gitlab/package.json index 7e7ca5eb31..9ce53681d0 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.15-next.1", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/events-backend-test-utils/CHANGELOG.md b/plugins/events-backend-test-utils/CHANGELOG.md index 6df0dc6a05..fd4afbc91c 100644 --- a/plugins/events-backend-test-utils/CHANGELOG.md +++ b/plugins/events-backend-test-utils/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-events-backend-test-utils +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.15 + +## 0.1.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.2.15-next.2 + ## 0.1.15-next.1 ### Patch Changes diff --git a/plugins/events-backend-test-utils/package.json b/plugins/events-backend-test-utils/package.json index 9d09d999f4..f7cfa76cef 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.15-next.1", + "version": "0.1.16", "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 9810584a6b..0ecbc4461e 100644 --- a/plugins/events-backend/CHANGELOG.md +++ b/plugins/events-backend/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-events-backend +## 0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-events-node@0.2.15 + +## 0.2.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-events-node@0.2.15-next.2 + ## 0.2.14-next.1 ### Patch Changes diff --git a/plugins/events-backend/package.json b/plugins/events-backend/package.json index 03028ae833..6c330ce996 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.14-next.1", + "version": "0.2.15", "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 607651ad73..cf2c846c93 100644 --- a/plugins/events-node/CHANGELOG.md +++ b/plugins/events-node/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-events-node +## 0.2.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6 + +## 0.2.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@0.6.6-next.2 + ## 0.2.14-next.1 ### Patch Changes diff --git a/plugins/events-node/package.json b/plugins/events-node/package.json index 762b5237b0..804eabe491 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.14-next.1", + "version": "0.2.15", "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 8c1c37256d..3ce8bb2103 100644 --- a/plugins/example-todo-list-backend/CHANGELOG.md +++ b/plugins/example-todo-list-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @internal/plugin-todo-list-backend +## 1.0.18 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## 1.0.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + ## 1.0.18-next.1 ### Patch Changes diff --git a/plugins/example-todo-list-backend/package.json b/plugins/example-todo-list-backend/package.json index 3a3a38a5c4..c13bb571e2 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.18-next.1", + "version": "1.0.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/example-todo-list-backend/src/service/standaloneServer.ts b/plugins/example-todo-list-backend/src/service/standaloneServer.ts index eedf1230ca..77c78365d6 100644 --- a/plugins/example-todo-list-backend/src/service/standaloneServer.ts +++ b/plugins/example-todo-list-backend/src/service/standaloneServer.ts @@ -17,7 +17,7 @@ import { createServiceBuilder, loadBackendConfig, - SingleHostDiscovery, + HostDiscovery, } from '@backstage/backend-common'; import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; import { Server } from 'http'; @@ -36,7 +36,7 @@ export async function startStandaloneServer( const logger = options.logger.child({ service: 'todo-list-backend' }); logger.debug('Starting application server...'); const config = await loadBackendConfig({ logger, argv: process.argv }); - const discovery = SingleHostDiscovery.fromConfig(config); + const discovery = HostDiscovery.fromConfig(config); const router = await createRouter({ logger, identity: DefaultIdentityClient.create({ diff --git a/plugins/example-todo-list-common/CHANGELOG.md b/plugins/example-todo-list-common/CHANGELOG.md index af2dba54e0..8deaa18374 100644 --- a/plugins/example-todo-list-common/CHANGELOG.md +++ b/plugins/example-todo-list-common/CHANGELOG.md @@ -1,5 +1,19 @@ # @internal/plugin-todo-list-common +## 1.0.14 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.9 + +## 1.0.14-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 1.0.13 ### Patch Changes diff --git a/plugins/example-todo-list-common/package.json b/plugins/example-todo-list-common/package.json index 257f19e1c7..57e6a9dbdf 100644 --- a/plugins/example-todo-list-common/package.json +++ b/plugins/example-todo-list-common/package.json @@ -1,6 +1,6 @@ { "name": "@internal/plugin-todo-list-common", - "version": "1.0.13", + "version": "1.0.14", "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 04243ee26a..1a4c10fb2b 100644 --- a/plugins/example-todo-list/CHANGELOG.md +++ b/plugins/example-todo-list/CHANGELOG.md @@ -1,5 +1,23 @@ # @internal/plugin-todo-list +## 1.0.18 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## 1.0.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + ## 1.0.18-next.1 ### Patch Changes diff --git a/plugins/example-todo-list/package.json b/plugins/example-todo-list/package.json index 589689a59c..7bfc3f898c 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.18-next.1", + "version": "1.0.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -39,8 +39,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -48,9 +48,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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" diff --git a/plugins/explore-backend/CHANGELOG.md b/plugins/explore-backend/CHANGELOG.md index 4e27d8f124..c02ad2da28 100644 --- a/plugins/explore-backend/CHANGELOG.md +++ b/plugins/explore-backend/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-explore-backend +## 0.0.16 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-search-backend-module-explore@0.1.10 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7 + +## 0.0.16-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-search-backend-module-explore@0.1.10-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 0.0.15-next.1 ### Patch Changes diff --git a/plugins/explore-backend/package.json b/plugins/explore-backend/package.json index 1e8a4a456b..8c1ae12922 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.15-next.1", + "version": "0.0.16", "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 6d45e9a689..ba70624ec9 100644 --- a/plugins/explore-react/CHANGELOG.md +++ b/plugins/explore-react/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-explore-react +## 0.0.32 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/plugin-explore-common@0.0.2 + +## 0.0.32-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/plugin-explore-common@0.0.2 + ## 0.0.32-next.0 ### Patch Changes diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index 9282573a38..7599da4ba8 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.32-next.0", + "version": "0.0.32", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -37,17 +37,17 @@ "@backstage/plugin-explore-common": "workspace:^" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "cross-fetch": "^3.1.5", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index 480d85437d..82e0a66d3c 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-explore +## 0.4.11 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0f10c53a05: Create an experimental `ExploreSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-explore-react@0.0.32 + - @backstage/theme@0.4.3 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7 + +## 0.4.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-explore-react@0.0.32-next.1 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 0.4.11-next.1 ### Patch Changes diff --git a/plugins/explore/alpha-api-report.md b/plugins/explore/alpha-api-report.md index 3d6e527629..8670338f3e 100644 --- a/plugins/explore/alpha-api-report.md +++ b/plugins/explore/alpha-api-report.md @@ -7,7 +7,7 @@ import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin<{}, {}>; export default _default; // @alpha (undocumented) diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 0462d60884..435c5df84d 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.11-next.1", + "version": "0.4.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -66,8 +66,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -76,9 +76,9 @@ "@backstage/dev-utils": "workspace:^", "@backstage/plugin-catalog": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index b1694c6717..ef28aa04c6 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-firehydrant +## 0.2.9 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + ## 0.2.9-next.1 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index 31848ee464..ed723f71cf 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.9-next.1", + "version": "0.2.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -52,9 +52,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index 68a526db00..099ab5f5a4 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-fossa +## 0.2.57 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.2.57-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.2.57-next.1 ### Patch Changes diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 7fbe7e5570..6c08f3d4fd 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.57-next.1", + "version": "0.2.57", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -50,8 +50,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -59,9 +59,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/gcalendar/CHANGELOG.md b/plugins/gcalendar/CHANGELOG.md index 3e479c9bc4..f9ac25d7f6 100644 --- a/plugins/gcalendar/CHANGELOG.md +++ b/plugins/gcalendar/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-gcalendar +## 0.3.19 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.3.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.3.19-next.1 ### Patch Changes diff --git a/plugins/gcalendar/package.json b/plugins/gcalendar/package.json index be9b02d4cc..d84850677b 100644 --- a/plugins/gcalendar/package.json +++ b/plugins/gcalendar/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-gcalendar", - "version": "0.3.19-next.1", + "version": "0.3.19", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -57,9 +57,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/dompurify": "^2.3.3", "@types/sanitize-html": "^2.6.2", diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index 69584e9c89..5a2c289a94 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-gcp-projects +## 0.3.42 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## 0.3.42-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + ## 0.3.42-next.1 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 888f2c7a16..24bb9a99fa 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.42-next.1", + "version": "0.3.42", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -44,8 +44,8 @@ "@types/react": "^16.13.1 || ^17.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -53,9 +53,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index 10c0d6770a..a91f49bbe1 100644 --- a/plugins/git-release-manager/CHANGELOG.md +++ b/plugins/git-release-manager/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-git-release-manager +## 0.3.38 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## 0.3.38-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/integration@1.7.1-next.1 + - @backstage/theme@0.4.3-next.0 + ## 0.3.38-next.1 ### Patch Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 869d39633d..2c0ce60f6a 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.38-next.1", + "version": "0.3.38", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,8 +45,8 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -54,10 +54,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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/recharts": "^1.8.15", "msw": "^1.0.0" diff --git a/plugins/git-release-manager/src/features/CreateReleaseCandidate/hooks/useCreateReleaseCandidate.test.tsx b/plugins/git-release-manager/src/features/CreateReleaseCandidate/hooks/useCreateReleaseCandidate.test.tsx index 25a987df2a..c5490103cb 100644 --- a/plugins/git-release-manager/src/features/CreateReleaseCandidate/hooks/useCreateReleaseCandidate.test.tsx +++ b/plugins/git-release-manager/src/features/CreateReleaseCandidate/hooks/useCreateReleaseCandidate.test.tsx @@ -13,8 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { renderHook, act } from '@testing-library/react-hooks'; -import { waitFor } from '@testing-library/react'; +import { renderHook, act } from '@testing-library/react'; import { mockCalverProject, @@ -48,10 +47,9 @@ describe('useCreateReleaseCandidate', () => { ); await act(async () => { - await waitFor(() => result.current.run()); + await result.current.run(); }); - expect(result.error).toEqual(undefined); expect(result.current.responseSteps).toHaveLength(6); }); @@ -67,7 +65,7 @@ describe('useCreateReleaseCandidate', () => { ); await act(async () => { - await waitFor(() => result.current.run()); + await result.current.run(); }); expect(result.current.responseSteps).toHaveLength(7); diff --git a/plugins/git-release-manager/src/features/Features.test.tsx b/plugins/git-release-manager/src/features/Features.test.tsx index f3a70c2bda..abde878648 100644 --- a/plugins/git-release-manager/src/features/Features.test.tsx +++ b/plugins/git-release-manager/src/features/Features.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { render, act, waitFor } from '@testing-library/react'; +import { render, waitFor } from '@testing-library/react'; import { Features } from './Features'; import { mockCalverProject } from '../test-helpers/test-helpers'; @@ -49,9 +49,7 @@ describe('Features', () => { />, ); - await act(async () => { - await waitFor(() => getByTestId(TEST_IDS.info.info)); - }); + await waitFor(() => getByTestId(TEST_IDS.info.info)); expect(getByTestId(TEST_IDS.info.info)).toMatchInlineSnapshot(` <div diff --git a/plugins/git-release-manager/src/features/Patch/hooks/usePatch.test.ts b/plugins/git-release-manager/src/features/Patch/hooks/usePatch.test.ts index 0bd7f27cdb..3eeda0531f 100644 --- a/plugins/git-release-manager/src/features/Patch/hooks/usePatch.test.ts +++ b/plugins/git-release-manager/src/features/Patch/hooks/usePatch.test.ts @@ -14,8 +14,7 @@ * limitations under the License. */ -import { renderHook, act } from '@testing-library/react-hooks'; -import { waitFor } from '@testing-library/react'; +import { renderHook, act } from '@testing-library/react'; import { mockBumpedTag, @@ -50,10 +49,9 @@ describe('patch', () => { ); await act(async () => { - await waitFor(() => result.current.run(mockSelectedPatchCommit)); + await result.current.run(mockSelectedPatchCommit); }); - expect(result.error).toEqual(undefined); expect(result.current.responseSteps).toHaveLength(18); }); @@ -69,10 +67,9 @@ describe('patch', () => { ); await act(async () => { - await waitFor(() => result.current.run(mockSelectedPatchCommit)); + await result.current.run(mockSelectedPatchCommit); }); - expect(result.error).toEqual(undefined); expect(result.current.responseSteps).toHaveLength(19); expect(result.current).toMatchInlineSnapshot(` { diff --git a/plugins/git-release-manager/src/features/PromoteRc/hooks/usePromoteRc.test.ts b/plugins/git-release-manager/src/features/PromoteRc/hooks/usePromoteRc.test.ts index f4e0fcb081..1b1bb54df0 100644 --- a/plugins/git-release-manager/src/features/PromoteRc/hooks/usePromoteRc.test.ts +++ b/plugins/git-release-manager/src/features/PromoteRc/hooks/usePromoteRc.test.ts @@ -14,9 +14,7 @@ * limitations under the License. */ -import { renderHook, act } from '@testing-library/react-hooks'; -import { waitFor } from '@testing-library/react'; - +import { renderHook, act } from '@testing-library/react'; import { mockCalverProject, mockReleaseCandidateCalver, @@ -50,10 +48,9 @@ describe('usePromoteRc', () => { ); await act(async () => { - await waitFor(() => result.current.run()); + await result.current.run(); }); - expect(result.error).toEqual(undefined); expect(result.current.responseSteps).toHaveLength(4); }); @@ -67,7 +64,7 @@ describe('usePromoteRc', () => { ); await act(async () => { - await waitFor(() => result.current.run()); + await result.current.run(); }); expect(result.current.responseSteps).toHaveLength(5); diff --git a/plugins/git-release-manager/src/hooks/useGetGitBatchInfo.test.ts b/plugins/git-release-manager/src/hooks/useGetGitBatchInfo.test.ts index 8e89add810..d1bf28bccb 100644 --- a/plugins/git-release-manager/src/hooks/useGetGitBatchInfo.test.ts +++ b/plugins/git-release-manager/src/hooks/useGetGitBatchInfo.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { waitFor } from '@testing-library/react'; import { mockApiClient } from '../test-helpers/mock-api-client'; diff --git a/plugins/git-release-manager/src/hooks/useResponseSteps.test.ts b/plugins/git-release-manager/src/hooks/useResponseSteps.test.ts index 513c51758d..c406a353b2 100644 --- a/plugins/git-release-manager/src/hooks/useResponseSteps.test.ts +++ b/plugins/git-release-manager/src/hooks/useResponseSteps.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; import { useResponseSteps } from './useResponseSteps'; diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index e4bea23a68..f5e9f1bc4c 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-github-actions +## 0.6.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 0.6.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/theme@0.4.3-next.0 + ## 0.6.6-next.1 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index fa273363c9..ec0d9a03db 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.6-next.1", + "version": "0.6.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -52,8 +52,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -61,9 +61,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx index 2d006b32c2..772a33c4fe 100644 --- a/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx +++ b/plugins/github-actions/src/components/Cards/RecentWorkflowRunsCard.test.tsx @@ -75,7 +75,7 @@ describe('<RecentWorkflowRunsCard />', () => { }); const renderSubject = async (props: any = {}) => { - renderInTestApp( + await renderInTestApp( <TestApiProvider apis={[ [errorApiRef, mockErrorApi], diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index 637bb2ca7f..e44c124264 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-github-deployments +## 0.1.56 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.1.56-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.1.56-next.1 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index edd3b6ff0e..4833a4df8a 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.56-next.1", + "version": "0.1.56", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -47,8 +47,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -56,9 +56,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/github-issues/CHANGELOG.md b/plugins/github-issues/CHANGELOG.md index e6a848c39d..11901150bb 100644 --- a/plugins/github-issues/CHANGELOG.md +++ b/plugins/github-issues/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-github-issues +## 0.2.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 7bd0a8ab3c: Filters out entities that belonged to a different github instance other than the one configured by the plugin +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.2.14-next.2 + +### Patch Changes + +- 7bd0a8ab3c: Filters out entities that belonged to a different github instance other than the one configured by the plugin +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.2.14-next.1 ### Patch Changes diff --git a/plugins/github-issues/package.json b/plugins/github-issues/package.json index 0a18bb22b9..f942ca50bc 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.14-next.1", + "version": "0.2.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,8 +45,8 @@ "react-use": "^17.4.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -54,9 +54,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/github-issues/src/api/githubIssuesApi.test.ts b/plugins/github-issues/src/api/githubIssuesApi.test.ts index e960d3123b..f3c1b29675 100644 --- a/plugins/github-issues/src/api/githubIssuesApi.test.ts +++ b/plugins/github-issues/src/api/githubIssuesApi.test.ts @@ -21,9 +21,22 @@ jest.mock('octokit', () => ({ import { ConfigApi, ErrorApi } from '@backstage/core-plugin-api'; import { ForwardedError } from '@backstage/errors'; -import { createFilterByClause, githubIssuesApi } from './githubIssuesApi'; -import type { GithubIssuesFilters } from './githubIssuesApi'; +import { + createFilterByClause, + githubIssuesApi, + Repository, + GithubIssuesFilters, +} from './githubIssuesApi'; +function entityRepository( + name: string, + locationHostname: string = 'github.com', +): Repository { + return { + locationHostname, + name, + }; +} function getFragment( filterBy = '', orderBy = 'field: UPDATED_AT, direction: DESC', @@ -110,7 +123,26 @@ describe('githubIssuesApi', () => { it('should call GitHub API with correct query with fragment for each repo', async () => { await api.fetchIssuesByRepoFromGithub( - ['mrwolny/yo-yo', 'mrwolny/yoyo', 'mrwolny/yo.yo'], + [ + entityRepository('mrwolny/yo-yo'), + entityRepository('mrwolny/yoyo'), + entityRepository('mrwolny/yo.yo'), + ], + 10, + ); + + expect(mockGraphQLQuery).toHaveBeenCalledTimes(1); + expect(mockGraphQLQuery).toHaveBeenCalledWith(getFragment()); + }); + + it("should only fetch data for entities hosted in the same GitHub instance as the plugin's config", async () => { + await api.fetchIssuesByRepoFromGithub( + [ + entityRepository('mrwolny/yo-yo'), + entityRepository('mrwolny/yoyo'), + entityRepository('mrwolny/yo.yo'), + entityRepository('mrwolny/another-repo', 'enterprise.github.com'), // This one should be filtered out + ], 10, ); @@ -120,7 +152,11 @@ describe('githubIssuesApi', () => { it('should call Github API with the correct filterBy and orderBy clauses', async () => { await api.fetchIssuesByRepoFromGithub( - ['mrwolny/yo-yo', 'mrwolny/yoyo', 'mrwolny/yo.yo'], + [ + entityRepository('mrwolny/yo-yo'), + entityRepository('mrwolny/yoyo'), + entityRepository('mrwolny/yo.yo'), + ], 10, { filterBy: { @@ -231,7 +267,7 @@ describe('githubIssuesApi', () => { ); const data = await api.fetchIssuesByRepoFromGithub( - ['mrwolny/yo-yo', 'mrwolny/notfound'], + [entityRepository('mrwolny/yo-yo'), entityRepository('mrwolny/notfound')], 10, ); @@ -301,7 +337,7 @@ describe('githubIssuesApi', () => { ); const data = await api.fetchIssuesByRepoFromGithub( - ['mrwolny/notfound'], + [entityRepository('mrwolny/notfound')], 10, ); @@ -341,7 +377,10 @@ describe('githubIssuesApi', () => { mockErrorApi as unknown as ErrorApi, ); - await api.fetchIssuesByRepoFromGithub(['mrwolny/notfound'], 10); + await api.fetchIssuesByRepoFromGithub( + [entityRepository('mrwolny/notfound')], + 10, + ); expect(mockErrorApi.post).toHaveBeenCalledTimes(1); expect(mockErrorApi.post).toHaveBeenCalledWith( diff --git a/plugins/github-issues/src/api/githubIssuesApi.ts b/plugins/github-issues/src/api/githubIssuesApi.ts index 32331ef6b1..d7b39989d8 100644 --- a/plugins/github-issues/src/api/githubIssuesApi.ts +++ b/plugins/github-issues/src/api/githubIssuesApi.ts @@ -24,6 +24,11 @@ import { import { readGithubIntegrationConfigs } from '@backstage/integration'; import { ForwardedError } from '@backstage/errors'; +/** @internal */ +export type Repository = { + name: string; + locationHostname: string; +}; /** @internal */ export type Assignee = { avatarUrl: string; @@ -116,9 +121,10 @@ export const githubIssuesApi = ( let octokit: Octokit; const getOctokit = async () => { - const baseUrl = readGithubIntegrationConfigs( + const githubConfig = readGithubIntegrationConfigs( configApi.getOptionalConfigArray('integrations.github') ?? [], - )[0].apiBaseUrl; + )[0]; + const baseUrl = githubConfig.apiBaseUrl; const token = await githubAuthApi.getAccessToken(['repo']); @@ -126,11 +132,11 @@ export const githubIssuesApi = ( octokit = new Octokit({ auth: token, ...(baseUrl && { baseUrl }) }); } - return octokit.graphql; + return { graphql: octokit.graphql, hostname: githubConfig.host }; }; const fetchIssuesByRepoFromGithub = async ( - repos: Array<string>, + repos: Array<Repository>, itemsPerRepo: number, { filterBy, @@ -140,30 +146,35 @@ export const githubIssuesApi = ( }, }: GithubIssuesByRepoOptions = {}, ): Promise<IssuesByRepo> => { - const graphql = await getOctokit(); + const { graphql, hostname } = await getOctokit(); const safeNames: Array<string> = []; + const repositories = repos + // only tries to fetch issues from repositories that are hosted on the same GitHub instance as the octokit + .filter(repo => repo.locationHostname === hostname) + .map(repo => { + const [owner, name] = repo.name.split('/'); - const repositories = repos.map(repo => { - const [owner, name] = repo.split('/'); + const safeNameRegex = /-|\./gi; + let safeName = name.replace(safeNameRegex, ''); - const safeNameRegex = /-|\./gi; - let safeName = name.replace(safeNameRegex, ''); + while (safeNames.includes(safeName)) { + safeName += 'x'; + } - while (safeNames.includes(safeName)) { - safeName += 'x'; - } + safeNames.push(safeName); - safeNames.push(safeName); - - return { - safeName, - name, - owner, - }; - }); + return { + safeName, + name, + owner, + }; + }); let issuesByRepo: IssuesByRepo = {}; try { + if (repositories.length === 0) { + throw new Error(`No repositories found for ${hostname}`); + } issuesByRepo = await graphql( createIssueByRepoQuery(repositories, itemsPerRepo, { filterBy, diff --git a/plugins/github-issues/src/components/GithubIssues/GithubIssues.test.tsx b/plugins/github-issues/src/components/GithubIssues/GithubIssues.test.tsx index 3f9e829de9..bf3cac7423 100644 --- a/plugins/github-issues/src/components/GithubIssues/GithubIssues.test.tsx +++ b/plugins/github-issues/src/components/GithubIssues/GithubIssues.test.tsx @@ -68,6 +68,8 @@ const entityComponent = { metadata: { annotations: { 'github.com/project-slug': 'backstage/backstage', + 'backstage.io/source-location': + 'url:https://github.com/backstage/backstage', }, name: 'backstage', }, diff --git a/plugins/github-issues/src/hooks/useEntityGithubRepositories.ts b/plugins/github-issues/src/hooks/useEntityGithubRepositories.ts index f3fab72090..b9763298e6 100644 --- a/plugins/github-issues/src/hooks/useEntityGithubRepositories.ts +++ b/plugins/github-issues/src/hooks/useEntityGithubRepositories.ts @@ -14,10 +14,15 @@ * limitations under the License. */ -import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; +import { + Entity, + stringifyEntityRef, + getEntitySourceLocation, +} from '@backstage/catalog-model'; import { useApi } from '@backstage/core-plugin-api'; import { catalogApiRef, useEntity } from '@backstage/plugin-catalog-react'; import { useCallback, useEffect, useState } from 'react'; +import { Repository } from '../api'; const GITHUB_PROJECT_SLUG_ANNOTATION = 'github.com/project-slug'; @@ -25,18 +30,28 @@ export const getProjectNameFromEntity = (entity: Entity): string => { return entity?.metadata.annotations?.[GITHUB_PROJECT_SLUG_ANNOTATION] ?? ''; }; +export const getHostnameFromEntity = (entity: Entity): string => { + const { target } = getEntitySourceLocation(entity); + return new URL(target).hostname; +}; + export function useEntityGithubRepositories() { const { entity } = useEntity(); const catalogApi = useApi(catalogApiRef); - const [repositories, setRepositories] = useState<string[]>([]); + const [repositories, setRepositories] = useState<Repository[]>([]); const getRepositoriesNames = useCallback(async () => { if (entity.kind === 'Component' || entity.kind === 'API') { const entityName = getProjectNameFromEntity(entity); - + const locationHostname = getHostnameFromEntity(entity); if (entityName) { - setRepositories([entityName]); + setRepositories([ + { + name: entityName, + locationHostname, + }, + ]); } return; @@ -49,11 +64,26 @@ export function useEntityGithubRepositories() { }, }); - const entitiesNames: string[] = entitiesList.items.map(componentEntity => - getProjectNameFromEntity(componentEntity), + const repositoryEntities: Repository[] = entitiesList.items.reduce( + (acc: Repository[], componentEntity: Entity) => { + const entityName = getProjectNameFromEntity(componentEntity); + const entityLocationHostname = getHostnameFromEntity(componentEntity); + if ( + entityName && + !acc.some((it: Repository) => it.name === entityName) && + entityName.length + ) { + acc.push({ + name: entityName, + locationHostname: entityLocationHostname, + }); + } + return acc; + }, + [], ); - setRepositories([...new Set(entitiesNames)].filter(name => name.length)); + setRepositories(repositoryEntities); }, [catalogApi, entity]); useEffect(() => { diff --git a/plugins/github-issues/src/hooks/useGetIssuesByRepoFromGithub.ts b/plugins/github-issues/src/hooks/useGetIssuesByRepoFromGithub.ts index 8ec5f3ec65..0b5bad7f57 100644 --- a/plugins/github-issues/src/hooks/useGetIssuesByRepoFromGithub.ts +++ b/plugins/github-issues/src/hooks/useGetIssuesByRepoFromGithub.ts @@ -16,10 +16,14 @@ import { useApi } from '@backstage/core-plugin-api'; import useAsyncRetry from 'react-use/lib/useAsyncRetry'; -import { githubIssuesApiRef, GithubIssuesByRepoOptions } from '../api'; +import { + Repository, + githubIssuesApiRef, + GithubIssuesByRepoOptions, +} from '../api'; export const useGetIssuesByRepoFromGithub = ( - repos: Array<string>, + repos: Array<Repository>, itemsPerRepo: number, options?: GithubIssuesByRepoOptions, ) => { diff --git a/plugins/github-pull-requests-board/CHANGELOG.md b/plugins/github-pull-requests-board/CHANGELOG.md index cf06af7c0c..8721accd79 100644 --- a/plugins/github-pull-requests-board/CHANGELOG.md +++ b/plugins/github-pull-requests-board/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-github-pull-requests-board +## 0.1.19 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 0.1.19-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/theme@0.4.3-next.0 + ## 0.1.19-next.1 ### Patch Changes diff --git a/plugins/github-pull-requests-board/package.json b/plugins/github-pull-requests-board/package.json index b7d320931b..2c985beda7 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.19-next.1", + "version": "0.1.19", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -51,17 +51,17 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/gitops-profiles/CHANGELOG.md b/plugins/gitops-profiles/CHANGELOG.md index 7783bf960b..f254fd8eac 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-gitops-profiles +## 0.3.41 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## 0.3.41-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + ## 0.3.41-next.1 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index d254a70390..5511f1f4fa 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.41-next.1", + "version": "0.3.41", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -54,9 +54,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/gocd/CHANGELOG.md b/plugins/gocd/CHANGELOG.md index 33c2d9bd14..be089e60a5 100644 --- a/plugins/gocd/CHANGELOG.md +++ b/plugins/gocd/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-gocd +## 0.1.31 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.1.31-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.1.31-next.1 ### Patch Changes diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json index 9da32e57b1..c2f60d7eb6 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.31-next.1", + "version": "0.1.31", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -54,9 +54,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/lodash": "^4.14.173", "@types/luxon": "^3.0.0", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index 0663cb0755..dea81e130c 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-graphiql +## 0.2.55 + +### Patch Changes + +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- 06432f900c: Updated `/alpha` exports to use new `attachTo` option. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## 0.2.55-next.2 + +### Patch Changes + +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- 06432f900c: Updated `/alpha` exports to use new `attachTo` option. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + ## 0.2.55-next.1 ### Patch Changes diff --git a/plugins/graphiql/alpha-api-report.md b/plugins/graphiql/alpha-api-report.md index 28537cfb15..3362cf0a59 100644 --- a/plugins/graphiql/alpha-api-report.md +++ b/plugins/graphiql/alpha-api-report.md @@ -7,6 +7,7 @@ import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } 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<TConfig extends {}>(options: { @@ -19,7 +20,12 @@ export function createEndpointExtension<TConfig extends {}>(options: { }): Extension<TConfig>; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin< + { + root: RouteRef<undefined>; + }, + {} +>; export default _default; // @alpha (undocumented) diff --git a/plugins/graphiql/api-report.md b/plugins/graphiql/api-report.md index 984b90ae88..4c760c33b7 100644 --- a/plugins/graphiql/api-report.md +++ b/plugins/graphiql/api-report.md @@ -79,6 +79,4 @@ export class GraphQLEndpoints implements GraphQLBrowseApi { // @public (undocumented) export const Router: () => React_2.JSX.Element; - -// (No @packageDocumentation comment for this package) ``` diff --git a/plugins/graphiql/dev/index.tsx b/plugins/graphiql/dev/index.tsx index 163b4d0512..5d7bff5f32 100644 --- a/plugins/graphiql/dev/index.tsx +++ b/plugins/graphiql/dev/index.tsx @@ -21,9 +21,9 @@ import { errorApiRef, IconComponent, } from '@backstage/core-plugin-api'; -import GraphiQLIcon from '../src/assets/graphiql.icon.svg'; import { graphiqlPlugin, + GraphiQLIcon, GraphQLEndpoints, graphQlBrowseApiRef, GraphiQLPage, diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index d0ce3982a6..52cff1fdb7 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.2.55-next.1", + "version": "0.2.55", "publishConfig": { "access": "public" }, @@ -60,8 +60,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -69,9 +69,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/codemirror": "^5.0.0", "cross-fetch": "^3.1.5", diff --git a/plugins/graphiql/src/GraphiQLIcon.tsx b/plugins/graphiql/src/GraphiQLIcon.tsx new file mode 100644 index 0000000000..c48c47bc09 --- /dev/null +++ b/plugins/graphiql/src/GraphiQLIcon.tsx @@ -0,0 +1,44 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import SvgIcon from '@material-ui/core/SvgIcon'; +import { IconComponent } from '@backstage/core-plugin-api'; + +/** + * @public + */ +export const GraphiQLIcon: IconComponent = () => ( + <SvgIcon> + <g> + <path d="M 3.449219 18.160156 L 2.585938 17.660156 L 12.195312 1.019531 L 13.058594 1.515625 Z M 3.449219 18.160156" /> + <path d="M 2.386719 16.332031 L 21.605469 16.332031 L 21.605469 17.328125 L 2.386719 17.328125 Z M 2.386719 16.332031" /> + <path d="M 12.382812 22.441406 L 2.769531 16.890625 L 3.265625 16.027344 L 12.878906 21.578125 Z M 12.382812 22.441406" /> + <path d="M 20.730469 7.976562 L 11.117188 2.425781 L 11.617188 1.5625 L 21.230469 7.113281 Z M 20.730469 7.976562" /> + <path d="M 3.269531 7.972656 L 2.769531 7.109375 L 12.382812 1.558594 L 12.882812 2.421875 Z M 3.269531 7.972656" /> + <path d="M 20.554688 18.160156 L 10.945312 1.515625 L 11.808594 1.019531 L 21.417969 17.660156 Z M 20.554688 18.160156" /> + <path d="M 3.148438 6.449219 L 4.144531 6.449219 L 4.144531 17.550781 L 3.148438 17.550781 Z M 3.148438 6.449219" /> + <path d="M 19.855469 6.449219 L 20.851562 6.449219 L 20.851562 17.550781 L 19.855469 17.550781 Z M 19.855469 6.449219" /> + <path d="M 12.210938 22.019531 L 11.777344 21.265625 L 20.136719 16.441406 L 20.570312 17.191406 Z M 12.210938 22.019531" /> + <path d="M 22.171875 17.875 C 21.59375 18.875 20.308594 19.21875 19.308594 18.640625 C 18.304688 18.066406 17.964844 16.78125 18.539062 15.78125 C 19.117188 14.777344 20.398438 14.4375 21.402344 15.011719 C 22.410156 15.59375 22.753906 16.871094 22.171875 17.875" /> + <path d="M 5.453125 8.21875 C 4.878906 9.222656 3.59375 9.5625 2.59375 8.988281 C 1.589844 8.410156 1.246094 7.128906 1.824219 6.125 C 2.398438 5.125 3.683594 4.78125 4.6875 5.359375 C 5.6875 5.941406 6.03125 7.21875 5.453125 8.21875" /> + <path d="M 1.828125 17.875 C 1.253906 16.871094 1.597656 15.59375 2.597656 15.011719 C 3.601562 14.4375 4.878906 14.777344 5.460938 15.78125 C 6.035156 16.78125 5.695312 18.058594 4.691406 18.640625 C 3.683594 19.21875 2.40625 18.875 1.828125 17.875" /> + <path d="M 18.546875 8.21875 C 17.96875 7.21875 18.3125 5.941406 19.3125 5.359375 C 20.316406 4.78125 21.59375 5.125 22.175781 6.125 C 22.753906 7.128906 22.410156 8.40625 21.40625 8.988281 C 20.40625 9.5625 19.121094 9.222656 18.546875 8.21875" /> + <path d="M 12 23.746094 C 10.84375 23.746094 9.90625 22.8125 9.90625 21.652344 C 9.90625 20.496094 10.84375 19.558594 12 19.558594 C 13.15625 19.558594 14.09375 20.496094 14.09375 21.652344 C 14.09375 22.804688 13.15625 23.746094 12 23.746094" /> + <path d="M 12 4.441406 C 10.84375 4.441406 9.90625 3.503906 9.90625 2.347656 C 9.90625 1.1875 10.84375 0.253906 12 0.253906 C 13.15625 0.253906 14.09375 1.1875 14.09375 2.347656 C 14.09375 3.503906 13.15625 4.441406 12 4.441406" /> + </g> + </SvgIcon> +); diff --git a/plugins/graphiql/src/alpha.tsx b/plugins/graphiql/src/alpha.tsx index 9cd956fc1a..58b6686daa 100644 --- a/plugins/graphiql/src/alpha.tsx +++ b/plugins/graphiql/src/alpha.tsx @@ -30,21 +30,17 @@ import { graphQlBrowseApiRef, GraphQLEndpoints, GraphQLEndpoint, + GraphiQLIcon, } from '@backstage/plugin-graphiql'; -import GraphiQLIcon from './assets/graphiql.icon.svg'; -import { - createApiFactory, - createRouteRef, - IconComponent, -} from '@backstage/core-plugin-api'; - -const graphiqlRouteRef = createRouteRef({ id: 'plugin.graphiql.page' }); +import { createApiFactory, IconComponent } from '@backstage/core-plugin-api'; +import { graphiQLRouteRef } from './route-refs'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; /** @alpha */ export const GraphiqlPage = createPageExtension({ id: 'plugin.graphiql.page', defaultPath: '/graphiql', - routeRef: graphiqlRouteRef, + routeRef: convertLegacyRouteRef(graphiQLRouteRef), loader: () => import('./components').then(m => <m.GraphiQLPage />), }); @@ -53,7 +49,7 @@ export const graphiqlPageSidebarItem = createNavItemExtension({ id: 'plugin.graphiql.nav.index', title: 'GraphiQL', icon: GraphiQLIcon as IconComponent, - routeRef: graphiqlRouteRef, + routeRef: convertLegacyRouteRef(graphiQLRouteRef), }); /** @internal */ @@ -86,7 +82,7 @@ export function createEndpointExtension<TConfig extends {}>(options: { }) { return createExtension({ id: `apis.plugin.graphiql.browse.${options.id}`, - at: 'apis.plugin.graphiql.browse/endpoints', + attachTo: { id: 'apis.plugin.graphiql.browse', input: 'endpoints' }, configSchema: options.configSchema, disabled: options.disabled ?? false, output: { @@ -125,4 +121,7 @@ export default createPlugin({ gitlabGraphiQLBrowseExtension, graphiqlPageSidebarItem, ], + routes: { + root: convertLegacyRouteRef(graphiQLRouteRef), + }, }); diff --git a/plugins/graphiql/src/assets/graphiql.icon.svg b/plugins/graphiql/src/assets/graphiql.icon.svg deleted file mode 100644 index e16f0e307c..0000000000 --- a/plugins/graphiql/src/assets/graphiql.icon.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><path d="M 3.449219 18.160156 L 2.585938 17.660156 L 12.195312 1.019531 L 13.058594 1.515625 Z M 3.449219 18.160156"/><path d="M 2.386719 16.332031 L 21.605469 16.332031 L 21.605469 17.328125 L 2.386719 17.328125 Z M 2.386719 16.332031"/><path d="M 12.382812 22.441406 L 2.769531 16.890625 L 3.265625 16.027344 L 12.878906 21.578125 Z M 12.382812 22.441406"/><path d="M 20.730469 7.976562 L 11.117188 2.425781 L 11.617188 1.5625 L 21.230469 7.113281 Z M 20.730469 7.976562"/><path d="M 3.269531 7.972656 L 2.769531 7.109375 L 12.382812 1.558594 L 12.882812 2.421875 Z M 3.269531 7.972656"/><path d="M 20.554688 18.160156 L 10.945312 1.515625 L 11.808594 1.019531 L 21.417969 17.660156 Z M 20.554688 18.160156"/><path d="M 3.148438 6.449219 L 4.144531 6.449219 L 4.144531 17.550781 L 3.148438 17.550781 Z M 3.148438 6.449219"/><path d="M 19.855469 6.449219 L 20.851562 6.449219 L 20.851562 17.550781 L 19.855469 17.550781 Z M 19.855469 6.449219"/><path d="M 12.210938 22.019531 L 11.777344 21.265625 L 20.136719 16.441406 L 20.570312 17.191406 Z M 12.210938 22.019531"/><path d="M 22.171875 17.875 C 21.59375 18.875 20.308594 19.21875 19.308594 18.640625 C 18.304688 18.066406 17.964844 16.78125 18.539062 15.78125 C 19.117188 14.777344 20.398438 14.4375 21.402344 15.011719 C 22.410156 15.59375 22.753906 16.871094 22.171875 17.875"/><path d="M 5.453125 8.21875 C 4.878906 9.222656 3.59375 9.5625 2.59375 8.988281 C 1.589844 8.410156 1.246094 7.128906 1.824219 6.125 C 2.398438 5.125 3.683594 4.78125 4.6875 5.359375 C 5.6875 5.941406 6.03125 7.21875 5.453125 8.21875"/><path d="M 1.828125 17.875 C 1.253906 16.871094 1.597656 15.59375 2.597656 15.011719 C 3.601562 14.4375 4.878906 14.777344 5.460938 15.78125 C 6.035156 16.78125 5.695312 18.058594 4.691406 18.640625 C 3.683594 19.21875 2.40625 18.875 1.828125 17.875"/><path d="M 18.546875 8.21875 C 17.96875 7.21875 18.3125 5.941406 19.3125 5.359375 C 20.316406 4.78125 21.59375 5.125 22.175781 6.125 C 22.753906 7.128906 22.410156 8.40625 21.40625 8.988281 C 20.40625 9.5625 19.121094 9.222656 18.546875 8.21875"/><path d="M 12 23.746094 C 10.84375 23.746094 9.90625 22.8125 9.90625 21.652344 C 9.90625 20.496094 10.84375 19.558594 12 19.558594 C 13.15625 19.558594 14.09375 20.496094 14.09375 21.652344 C 14.09375 22.804688 13.15625 23.746094 12 23.746094"/><path d="M 12 4.441406 C 10.84375 4.441406 9.90625 3.503906 9.90625 2.347656 C 9.90625 1.1875 10.84375 0.253906 12 0.253906 C 13.15625 0.253906 14.09375 1.1875 14.09375 2.347656 C 14.09375 3.503906 13.15625 4.441406 12 4.441406"/></g></svg> \ No newline at end of file diff --git a/plugins/graphiql/src/index.ts b/plugins/graphiql/src/index.ts index 284b78fa35..d7326134ff 100644 --- a/plugins/graphiql/src/index.ts +++ b/plugins/graphiql/src/index.ts @@ -20,18 +20,12 @@ * @packageDocumentation */ -import GraphiQLIconComponent from './assets/graphiql.icon.svg'; -import { IconComponent } from '@backstage/core-plugin-api'; - export { graphiqlPlugin, graphiqlPlugin as plugin, GraphiQLPage, } from './plugin'; +export { GraphiQLIcon } from './GraphiQLIcon'; export { GraphiQLPage as Router } from './components'; export * from './lib/api'; export * from './route-refs'; - -/** @public */ -export const GraphiQLIcon: IconComponent = - GraphiQLIconComponent as IconComponent; diff --git a/plugins/graphql-backend/CHANGELOG.md b/plugins/graphql-backend/CHANGELOG.md index c3991bd3a2..dcf6b8f243 100644 --- a/plugins/graphql-backend/CHANGELOG.md +++ b/plugins/graphql-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-graphql-backend +## 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 diff --git a/plugins/graphql-backend/README.md b/plugins/graphql-backend/README.md index 970222fb1f..7e9f6c772e 100644 --- a/plugins/graphql-backend/README.md +++ b/plugins/graphql-backend/README.md @@ -1,28 +1,3 @@ # GraphQL Backend -## Getting Started - -This is the GraphQL Backend plugin. - -It is responsible for merging different `graphql-plugins` together to provide the end schema. - -To run it within the backend do: - -1. Register the router in `packages/backend/src/index.ts`: - -```ts -const graphqlEnv = useHotMemoize(module, () => createEnv('graphql')); - -const service = createServiceBuilder(module) - .loadConfig(configReader) - /** several different routers */ - .addRouter('/graphql', await graphql(graphqlEnv)); -``` - -2. Start the backend - -```bash -yarn workspace example-backend start -``` - -This will launch the full example 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/package.json b/plugins/graphql-backend/package.json index 7ba1b47881..c0b89ef0ce 100644 --- a/plugins/graphql-backend/package.json +++ b/plugins/graphql-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphql-backend", - "description": "An experimental Backstage backend plugin for GraphQL", - "version": "0.1.43-next.1", + "description": "Deprecated, consider using @frontside/backstage-plugin-graphql-backend instead", + "version": "0.2.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/graphql-voyager/CHANGELOG.md b/plugins/graphql-voyager/CHANGELOG.md index 5331c0a7fc..20130f64dd 100644 --- a/plugins/graphql-voyager/CHANGELOG.md +++ b/plugins/graphql-voyager/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-graphql-voyager +## 0.1.8 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## 0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + ## 0.1.8-next.1 ### Patch Changes diff --git a/plugins/graphql-voyager/package.json b/plugins/graphql-voyager/package.json index bc62c158ac..51b7020154 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.8-next.1", + "version": "0.1.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -41,8 +41,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -50,9 +50,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/home-react/CHANGELOG.md b/plugins/home-react/CHANGELOG.md index 2c2fce8504..8124f70308 100644 --- a/plugins/home-react/CHANGELOG.md +++ b/plugins/home-react/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-home-react +## 0.1.4 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + +## 0.1.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + ## 0.1.4-next.1 ### Patch Changes diff --git a/plugins/home-react/package.json b/plugins/home-react/package.json index f6e9655849..5c56caf71b 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.4-next.1", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -42,8 +42,8 @@ "@types/react": "^16.13.1 || ^17.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -51,9 +51,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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-grid-layout": "^1.3.2", "cross-fetch": "^3.1.5", diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index 2d826ed5d0..cd27145f6c 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-home +## 0.5.9 + +### Patch Changes + +- f997f771da: Adds Top/Recently Visited components to homepage +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-home-react@0.1.4 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.5.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-home-react@0.1.4-next.2 + ## 0.5.9-next.1 ### Patch Changes diff --git a/plugins/home/alpha-api-report.md b/plugins/home/alpha-api-report.md new file mode 100644 index 0000000000..35ce0bb86c --- /dev/null +++ b/plugins/home/alpha-api-report.md @@ -0,0 +1,17 @@ +## API Report File for "@backstage/plugin-home" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; +import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api'; + +// @alpha (undocumented) +const _default: BackstagePlugin<{}, {}>; +export default _default; + +// @alpha (undocumented) +export const titleExtensionDataRef: ConfigurableExtensionDataRef<string, {}>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/home/package.json b/plugins/home/package.json index 17c17cffe3..edb7e6542d 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,14 +1,12 @@ { "name": "@backstage/plugin-home", "description": "A Backstage plugin that helps you build a home page", - "version": "0.5.9-next.1", + "version": "0.5.9", "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" + "access": "public" }, "backstage": { "role": "frontend-plugin" @@ -23,6 +21,21 @@ "backstage", "homepage" ], + "exports": { + ".": "./src/index.ts", + "./alpha": "./src/alpha.tsx", + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + "alpha": [ + "src/alpha.tsx" + ], + "package.json": [ + "package.json" + ] + } + }, "sideEffects": false, "scripts": { "build": "backstage-cli package build", @@ -39,6 +52,7 @@ "@backstage/core-app-api": "workspace:^", "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@backstage/plugin-home-react": "workspace:^", "@backstage/theme": "workspace:^", @@ -46,8 +60,8 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", - "@rjsf/core-v5": "npm:@rjsf/core@5.13.0", - "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@5.13.0", + "@rjsf/core": "5.13.0", + "@rjsf/material-ui": "5.13.0", "@rjsf/utils": "5.13.0", "@rjsf/validator-ajv8": "5.13.0", "@types/react": "^16.13.1 || ^17.0.0", @@ -59,18 +73,17 @@ "zod": "^3.21.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.0.1", + "@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-grid-layout": "^1.3.2", "msw": "^1.0.0" diff --git a/plugins/home/src/alpha.tsx b/plugins/home/src/alpha.tsx new file mode 100644 index 0000000000..c8308f7c0a --- /dev/null +++ b/plugins/home/src/alpha.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, + createExtensionDataRef, + createExtensionInput, + createPageExtension, + createPlugin, + createRouteRef, +} from '@backstage/frontend-plugin-api'; + +const rootRouteRef = createRouteRef(); + +/** + * @alpha + */ +export const titleExtensionDataRef = createExtensionDataRef<string>('title'); + +const HomepageCompositionRootExtension = createPageExtension({ + id: 'home', + defaultPath: '/home', + routeRef: rootRouteRef, + inputs: { + props: createExtensionInput( + { + children: coreExtensionData.reactElement.optional(), + title: titleExtensionDataRef.optional(), + }, + + { + singleton: true, + optional: true, + }, + ), + }, + loader: ({ inputs }) => + import('./components/').then(m => ( + <m.HomepageCompositionRoot + children={inputs.props?.children} + title={inputs.props?.title} + /> + )), +}); + +/** + * @alpha + */ +export default createPlugin({ + id: 'home', + extensions: [HomepageCompositionRootExtension], +}); diff --git a/plugins/home/src/components/CustomHomepage/WidgetSettingsOverlay.tsx b/plugins/home/src/components/CustomHomepage/WidgetSettingsOverlay.tsx index 2c3a1d9ab9..aec4b3dcf2 100644 --- a/plugins/home/src/components/CustomHomepage/WidgetSettingsOverlay.tsx +++ b/plugins/home/src/components/CustomHomepage/WidgetSettingsOverlay.tsx @@ -27,10 +27,11 @@ import SettingsIcon from '@material-ui/icons/Settings'; import DeleteIcon from '@material-ui/icons/Delete'; import React from 'react'; import { Widget } from './types'; -import { withTheme } from '@rjsf/core-v5'; +import { withTheme } from '@rjsf/core'; +import { Theme as MuiTheme } from '@rjsf/material-ui'; import validator from '@rjsf/validator-ajv8'; -const Form = withTheme(require('@rjsf/material-ui-v5').Theme); +const Form = withTheme(MuiTheme); const useStyles = makeStyles((theme: Theme) => createStyles({ diff --git a/plugins/ilert/CHANGELOG.md b/plugins/ilert/CHANGELOG.md index 31cace8de8..8e07fa787f 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-ilert +## 0.2.14 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.2.14-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- 9c9a9100b0: Internal refactor to avoid using the deprecated `.icon.svg` extension. +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.2.14-next.1 ### Patch Changes diff --git a/plugins/ilert/api-report.md b/plugins/ilert/api-report.md index 821a3a6bd0..da752d4c16 100644 --- a/plugins/ilert/api-report.md +++ b/plugins/ilert/api-report.md @@ -810,6 +810,4 @@ export type UserRole = | 'STAKEHOLDER' | 'ACCOUNT_OWNER' | 'RESPONDER'; - -// (No @packageDocumentation comment for this package) ``` diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index f84a79375d..42d6a33ab1 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.14-next.1", + "version": "0.2.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -44,12 +44,11 @@ "@types/react": "^16.13.1 || ^17.0.0", "humanize-duration": "^3.26.0", "luxon": "^3.0.0", - "prop-types": "^15.7.2", "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -57,9 +56,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/ilert/src/ILertIcon.tsx b/plugins/ilert/src/ILertIcon.tsx new file mode 100644 index 0000000000..ffe1ae0877 --- /dev/null +++ b/plugins/ilert/src/ILertIcon.tsx @@ -0,0 +1,71 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import SvgIcon from '@material-ui/core/SvgIcon'; +import { IconComponent } from '@backstage/core-plugin-api'; + +/** + * @public + */ +export const ILertIcon: IconComponent = () => ( + <SvgIcon> + <g> + <path + stroke="none" + fillRule="nonzero" + fill="#fff" + fillOpacity="1" + d="M 0 9.277344 L 0 18.574219 C 0 20.832031 1.847656 22.679688 4.105469 22.679688 L 12.582031 22.679688 C 6.21875 21.007812 1.277344 15.792969 0 9.277344 Z M 0 9.277344" + /> + <path + stroke="none" + fillRule="nonzero" + fill="#fff" + fillOpacity="1" + d="M 19.527344 22.5625 C 21.328125 22.128906 22.679688 20.503906 22.679688 18.574219 L 22.679688 16.273438 C 21.691406 16.820312 20.632812 17.222656 19.527344 17.46875 Z M 19.527344 22.5625" + /> + <path + stroke="none" + fillRule="nonzero" + fill="#fff" + fillOpacity="1" + d="M 14.417969 17.46875 C 9.136719 16.296875 5.171875 11.578125 5.171875 5.945312 C 5.167969 3.855469 5.726562 1.804688 6.785156 0 L 4.105469 0 C 1.847656 0 0 1.847656 0 4.105469 L 0 6.882812 C 0.433594 14.816406 6.335938 21.316406 13.992188 22.679688 L 14.421875 22.679688 Z M 14.417969 17.46875" + /> + <path + stroke="none" + fillRule="nonzero" + fill="#fff" + fillOpacity="1" + d="M 19.527344 12.375 L 19.527344 17.160156 C 20.632812 16.910156 21.695312 16.496094 22.679688 15.929688 L 22.679688 9.855469 C 21.902344 10.988281 20.804688 11.863281 19.527344 12.375 Z M 19.527344 12.375" + /> + <path + stroke="none" + fillRule="nonzero" + fill="#fff" + fillOpacity="1" + d="M 14.417969 17.160156 L 14.417969 12.375 C 11.863281 11.355469 10.054688 8.859375 10.054688 5.945312 C 10.054688 3.503906 11.34375 1.246094 13.441406 0 L 7.128906 0 C 6.039062 1.792969 5.464844 3.847656 5.46875 5.945312 C 5.46875 11.410156 9.300781 15.996094 14.417969 17.160156 Z M 14.417969 17.160156" + /> + <path + stroke="none" + fillRule="nonzero" + fill="#fff" + fillOpacity="1" + d="M 10.355469 5.945312 C 10.355469 8.613281 11.957031 11.019531 14.417969 12.050781 L 14.417969 9.917969 C 15.972656 10.925781 17.972656 10.925781 19.527344 9.917969 L 19.527344 12.050781 C 20.847656 11.496094 21.953125 10.53125 22.679688 9.300781 L 22.679688 4.105469 C 22.679688 1.847656 20.832031 0 18.574219 0 L 14.066406 0 C 11.796875 1.113281 10.355469 3.417969 10.355469 5.945312 Z M 16.972656 2.5625 C 18.84375 2.5625 20.355469 4.078125 20.355469 5.945312 C 20.355469 7.8125 18.84375 9.328125 16.972656 9.328125 C 15.105469 9.328125 13.589844 7.8125 13.589844 5.945312 C 13.59375 4.078125 15.105469 2.566406 16.972656 2.5625 Z M 16.972656 2.5625" + /> + </g> + </SvgIcon> +); diff --git a/plugins/ilert/src/assets/ilert.icon.svg b/plugins/ilert/src/assets/ilert.icon.svg deleted file mode 100644 index 5109286355..0000000000 --- a/plugins/ilert/src/assets/ilert.icon.svg +++ /dev/null @@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" version="1.1" viewBox="0 0 24 24"><g id="Logo"><path style="stroke:none;fill-rule:nonzero;fill:#fff;fill-opacity:1" d="M 0 9.277344 L 0 18.574219 C 0 20.832031 1.847656 22.679688 4.105469 22.679688 L 12.582031 22.679688 C 6.21875 21.007812 1.277344 15.792969 0 9.277344 Z M 0 9.277344"/><path style="stroke:none;fill-rule:nonzero;fill:#fff;fill-opacity:1" d="M 19.527344 22.5625 C 21.328125 22.128906 22.679688 20.503906 22.679688 18.574219 L 22.679688 16.273438 C 21.691406 16.820312 20.632812 17.222656 19.527344 17.46875 Z M 19.527344 22.5625"/><path style="stroke:none;fill-rule:nonzero;fill:#fff;fill-opacity:1" d="M 14.417969 17.46875 C 9.136719 16.296875 5.171875 11.578125 5.171875 5.945312 C 5.167969 3.855469 5.726562 1.804688 6.785156 0 L 4.105469 0 C 1.847656 0 0 1.847656 0 4.105469 L 0 6.882812 C 0.433594 14.816406 6.335938 21.316406 13.992188 22.679688 L 14.421875 22.679688 Z M 14.417969 17.46875"/><path style="stroke:none;fill-rule:nonzero;fill:#fff;fill-opacity:1" d="M 19.527344 12.375 L 19.527344 17.160156 C 20.632812 16.910156 21.695312 16.496094 22.679688 15.929688 L 22.679688 9.855469 C 21.902344 10.988281 20.804688 11.863281 19.527344 12.375 Z M 19.527344 12.375"/><path style="stroke:none;fill-rule:nonzero;fill:#fff;fill-opacity:1" d="M 14.417969 17.160156 L 14.417969 12.375 C 11.863281 11.355469 10.054688 8.859375 10.054688 5.945312 C 10.054688 3.503906 11.34375 1.246094 13.441406 0 L 7.128906 0 C 6.039062 1.792969 5.464844 3.847656 5.46875 5.945312 C 5.46875 11.410156 9.300781 15.996094 14.417969 17.160156 Z M 14.417969 17.160156"/><path style="stroke:none;fill-rule:nonzero;fill:#fff;fill-opacity:1" d="M 10.355469 5.945312 C 10.355469 8.613281 11.957031 11.019531 14.417969 12.050781 L 14.417969 9.917969 C 15.972656 10.925781 17.972656 10.925781 19.527344 9.917969 L 19.527344 12.050781 C 20.847656 11.496094 21.953125 10.53125 22.679688 9.300781 L 22.679688 4.105469 C 22.679688 1.847656 20.832031 0 18.574219 0 L 14.066406 0 C 11.796875 1.113281 10.355469 3.417969 10.355469 5.945312 Z M 16.972656 2.5625 C 18.84375 2.5625 20.355469 4.078125 20.355469 5.945312 C 20.355469 7.8125 18.84375 9.328125 16.972656 9.328125 C 15.105469 9.328125 13.589844 7.8125 13.589844 5.945312 C 13.59375 4.078125 15.105469 2.566406 16.972656 2.5625 Z M 16.972656 2.5625"/></g></svg> \ No newline at end of file diff --git a/plugins/ilert/src/index.ts b/plugins/ilert/src/index.ts index 5fcf42011b..39e3dac9ec 100644 --- a/plugins/ilert/src/index.ts +++ b/plugins/ilert/src/index.ts @@ -20,9 +20,6 @@ * @packageDocumentation */ -import ILertIconComponent from './assets/ilert.icon.svg'; -import { IconComponent } from '@backstage/core-plugin-api'; - export { ilertPlugin, ilertPlugin as plugin, @@ -35,9 +32,7 @@ export { isPluginApplicableToEntity as isILertAvailable, ILertCard, } from './components'; +export { ILertIcon } from './ILertIcon'; export * from './api'; export * from './route-refs'; export * from './types'; - -/** @public */ -export const ILertIcon: IconComponent = ILertIconComponent as IconComponent; diff --git a/plugins/jenkins-backend/CHANGELOG.md b/plugins/jenkins-backend/CHANGELOG.md index b0aeddb339..27af4041da 100644 --- a/plugins/jenkins-backend/CHANGELOG.md +++ b/plugins/jenkins-backend/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-jenkins-backend +## 0.3.0 + +### Minor Changes + +- 411896faf9: Added JobRunTable Component. + Added new Route and extended Api to get buildJobs. + Actions column has a new icon button, clicking on which takes us to page where we + can see all the job runs. + +### Patch Changes + +- 930ac236d8: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-jenkins-common@0.1.20 + - @backstage/plugin-permission-common@0.7.9 + +## 0.2.9-next.2 + +### Patch Changes + +- 930ac236d8: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-jenkins-common@0.1.20-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/jenkins-backend/README.md b/plugins/jenkins-backend/README.md index 133b9f42e2..d6f8fa5472 100644 --- a/plugins/jenkins-backend/README.md +++ b/plugins/jenkins-backend/README.md @@ -8,6 +8,20 @@ This is the backend half of the 2 Jenkins plugins and is responsible for: - finding the appropriate job(s) on that instance for an entity - connecting to Jenkins and gathering data to present to the frontend +## New Backend System + +The jenkins backend plugin has support for the [new backend system](https://backstage.io/docs/backend-system/), here's how you can set that up: + +In your `packages/backend/src/index.ts` make the following changes: + +```diff + import { createBackend } from '@backstage/backend-defaults'; + const backend = createBackend(); + // ... other feature additions + backend.add(import('@backstage/plugin-jenkins-backend')); + backend.start(); +``` + ## Integrating into a backstage instance This plugin needs to be added to an existing backstage instance. diff --git a/plugins/jenkins-backend/api-report.md b/plugins/jenkins-backend/api-report.md index fd1365547d..28dafa70bf 100644 --- a/plugins/jenkins-backend/api-report.md +++ b/plugins/jenkins-backend/api-report.md @@ -3,6 +3,7 @@ > 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 { CatalogApi } from '@backstage/catalog-client'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; @@ -79,6 +80,10 @@ export interface JenkinsInstanceConfig { username: string; } +// @public +const jenkinsPlugin: () => BackendFeature; +export default jenkinsPlugin; + // @public (undocumented) export interface RouterOptions { // (undocumented) diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index 12fe2debe1..740ef8710a 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.2.8-next.1", + "version": "0.3.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,11 +31,13 @@ }, "dependencies": { "@backstage/backend-common": "workspace:^", + "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", + "@backstage/plugin-catalog-node": "workspace:^", "@backstage/plugin-jenkins-common": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-permission-node": "workspace:^", diff --git a/plugins/jenkins-backend/src/index.ts b/plugins/jenkins-backend/src/index.ts index c55335c52d..4d01566a60 100644 --- a/plugins/jenkins-backend/src/index.ts +++ b/plugins/jenkins-backend/src/index.ts @@ -21,3 +21,4 @@ */ export * from './service'; +export { jenkinsPlugin as default } from './plugin'; diff --git a/plugins/jenkins-backend/src/plugin.test.tsx b/plugins/jenkins-backend/src/plugin.test.tsx new file mode 100644 index 0000000000..22ef6de078 --- /dev/null +++ b/plugins/jenkins-backend/src/plugin.test.tsx @@ -0,0 +1,22 @@ +/* + * 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 { jenkinsPlugin } from './plugin'; + +describe('jenkins', () => { + it('should export the jenkins plugin', () => { + expect(jenkinsPlugin).toBeDefined(); + }); +}); diff --git a/plugins/jenkins-backend/src/plugin.ts b/plugins/jenkins-backend/src/plugin.ts new file mode 100644 index 0000000000..8da26d62aa --- /dev/null +++ b/plugins/jenkins-backend/src/plugin.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 { loggerToWinstonLogger } from '@backstage/backend-common'; +import { + createBackendPlugin, + coreServices, +} from '@backstage/backend-plugin-api'; +import { DefaultJenkinsInfoProvider } from './service/jenkinsInfoProvider'; +import { createRouter } from './service/router'; +import { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha'; + +/** + * Jenkins backend plugin + * + * @public + */ +export const jenkinsPlugin = createBackendPlugin({ + pluginId: 'jenkins', + register(env) { + env.registerInit({ + deps: { + logger: coreServices.logger, + permissions: coreServices.permissions, + httpRouter: coreServices.httpRouter, + config: coreServices.rootConfig, + catalogClient: catalogServiceRef, + }, + async init({ logger, permissions, httpRouter, config, catalogClient }) { + const winstonLogger = loggerToWinstonLogger(logger); + const jenkinsInfoProvider = DefaultJenkinsInfoProvider.fromConfig({ + config, + catalog: catalogClient, + }); + httpRouter.use( + await createRouter({ + permissions, + /** + * Logger for logging purposes + */ + logger: winstonLogger, + /** + * Info provider to be able to get all necessary information for the APIs + */ + jenkinsInfoProvider, + }), + ); + }, + }); + }, +}); diff --git a/plugins/jenkins-backend/src/service/jenkinsApi.ts b/plugins/jenkins-backend/src/service/jenkinsApi.ts index 85271462eb..2cf432343f 100644 --- a/plugins/jenkins-backend/src/service/jenkinsApi.ts +++ b/plugins/jenkins-backend/src/service/jenkinsApi.ts @@ -54,6 +54,7 @@ export class JenkinsApiImpl { private static readonly jobTreeSpec = `actions[*], ${JenkinsApiImpl.lastBuildTreeSpec} jobs{0,1}, + url, name, fullName, displayName, @@ -64,6 +65,16 @@ export class JenkinsApiImpl { ${JenkinsApiImpl.jobTreeSpec} ]{0,50}`; + private static readonly jobBuildsTreeSpec = ` + name, + description, + url, + fullName, + displayName, + fullDisplayName, + inQueue, + builds[*]`; + constructor(private readonly permissionApi?: PermissionEvaluator) {} /** @@ -329,4 +340,35 @@ export class JenkinsApiImpl { const jobs = jobFullName.split('/'); return `${jenkinsInfo.baseUrl}/job/${jobs.join('/job/')}/${buildId}`; } + + async getJobBuilds(jenkinsInfo: JenkinsInfo, jobFullName: string) { + let jobName = jobFullName; + + if (jobFullName.includes('/')) { + const arr = jobFullName.split('/'); + const multibranchJobName = arr.shift(); + jobName = [ + multibranchJobName, + 'job', + encodeURIComponent(arr.join('/')), + ].join('/'); + } + + const response = await fetch( + `${ + jenkinsInfo.baseUrl + }/job/${jobName}/api/json?tree=${JenkinsApiImpl.jobBuildsTreeSpec.replace( + /\s/g, + '', + )}`, + { + method: 'get', + headers: jenkinsInfo.headers as HeaderInit, + }, + ); + + const jobBuilds = await response.json(); + + return jobBuilds; + } } diff --git a/plugins/jenkins-backend/src/service/router.ts b/plugins/jenkins-backend/src/service/router.ts index eea067fab6..06a04d8266 100644 --- a/plugins/jenkins-backend/src/service/router.ts +++ b/plugins/jenkins-backend/src/service/router.ts @@ -151,6 +151,32 @@ export async function createRouter( }, ); + router.get( + '/v1/entity/:namespace/:kind/:name/job/:jobFullName', + async (request, response) => { + const token = getBearerTokenFromAuthorizationHeader( + request.header('authorization'), + ); + const { namespace, kind, name, jobFullName } = request.params; + + const jenkinsInfo = await jenkinsInfoProvider.getInstance({ + entityRef: { + kind, + namespace, + name, + }, + jobFullName, + backstageToken: token, + }); + + const build = await jenkinsApi.getJobBuilds(jenkinsInfo, jobFullName); + + response.json({ + build: build, + }); + }, + ); + router.post( '/v1/entity/:namespace/:kind/:name/job/:jobFullName/:buildNumber', async (request, response) => { diff --git a/plugins/jenkins-common/CHANGELOG.md b/plugins/jenkins-common/CHANGELOG.md index 4fa915f473..f91ea5074c 100644 --- a/plugins/jenkins-common/CHANGELOG.md +++ b/plugins/jenkins-common/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-jenkins-common +## 0.1.20 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + +## 0.1.20-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 0.1.19 ### Patch Changes diff --git a/plugins/jenkins-common/package.json b/plugins/jenkins-common/package.json index 4bf522dadd..0856d27ad0 100644 --- a/plugins/jenkins-common/package.json +++ b/plugins/jenkins-common/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-jenkins-common", - "version": "0.1.19", + "version": "0.1.20", "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 c7b92cbcdd..5878d16f47 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,42 @@ # @backstage/plugin-jenkins +## 0.9.0 + +### Minor Changes + +- 411896faf9: Added JobRunTable Component. + Added new Route and extended Api to get buildJobs. + Actions column has a new icon button, clicking on which takes us to page where we + can see all the job runs. + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 1a05cf34f6: Extend EntityJenkinsContent to receive columns as prop +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-jenkins-common@0.1.20 + +## 0.8.7-next.2 + +### Patch Changes + +- 1a05cf34f6: Extend EntityJenkinsContent to receive columns as prop +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-jenkins-common@0.1.20-next.0 + ## 0.8.7-next.1 ### Patch Changes diff --git a/plugins/jenkins/README.md b/plugins/jenkins/README.md index 2a0ec451c8..b62eaab514 100644 --- a/plugins/jenkins/README.md +++ b/plugins/jenkins/README.md @@ -5,6 +5,8 @@ Website: [https://jenkins.io/](https://jenkins.io/) <img src="./src/assets/last-master-build.png" alt="Last master build"/> <img src="./src/assets/folder-results.png" alt="Folder results"/> <img src="./src/assets/build-details.png" alt="Build details"/> +<img src="./src/assets/jobrun-table.png" alt="Job builds records"/> +<img src="./src/assets/dynamic-columns.png" alt="Modify Table Columns"/> ## Setup @@ -74,7 +76,9 @@ metadata: name: 'your-component' description: 'a description' annotations: - jenkins.io/github-folder: 'folder-name/project-name' + jenkins.io/github-folder: 'folder-name/project-name' # deprecated + jenkins.io/job-full-name: 'folder-name/project-name' # use this instead + spec: type: service lifecycle: experimental @@ -97,3 +101,35 @@ spec: - Only works with organization folder projects backed by GitHub - No pagination support currently, limited to 50 projects - don't run this on a Jenkins instance with lots of builds + +## EntityJobRunsTable + +- View all builds of a particular job +- shows average build time for successful builds + +## Modify Columns of EntityJenkinsContent + +- now you can pass down column props to show the columns/metadata as per your use case. + +```tsx +export const generatedColumns: TableColumn[] = [ + { + title: 'Timestamp', + field: 'lastBuild.timestamp', + render: (row: Partial<Project>) => ( + <> + <Typography paragraph> + {` + ${new Date(row.lastBuild?.timestamp).toLocaleDateString()} + ${new Date(row.lastBuild?.timestamp).toLocaleTimeString()} + `} + </Typography> + </> + ), + }, +] + +// ... +<EntityJenkinsContent columns={generatedColumns}/> +// ... +``` diff --git a/plugins/jenkins/api-report.md b/plugins/jenkins/api-report.md index 611a56cd5f..c1b8ad2b81 100644 --- a/plugins/jenkins/api-report.md +++ b/plugins/jenkins/api-report.md @@ -15,9 +15,15 @@ import { InfoCardVariants } from '@backstage/core-components'; import { JSX as JSX_2 } from 'react'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; +import { TableColumn } from '@backstage/core-components'; // @public (undocumented) -export const EntityJenkinsContent: () => JSX_2.Element; +export const EntityJenkinsContent: (props: { + columns?: TableColumn<Project>[] | undefined; +}) => JSX_2.Element; + +// @public (undocumented) +export const EntityJobRunsTable: () => JSX_2.Element; // @public (undocumented) export const EntityLatestJenkinsRunCard: (props: { @@ -45,7 +51,13 @@ export interface JenkinsApi { jobFullName: string; buildNumber: string; }): Promise<Build>; - // Warning: (ae-forgotten-export) The symbol "Project" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "Job" needs to be exported by the entry point index.d.ts + // + // (undocumented) + getJobBuilds(options: { + entity: CompoundEntityRef; + jobFullName: string; + }): Promise<Job>; getProjects(options: { entity: CompoundEntityRef; filter: { @@ -80,6 +92,11 @@ export class JenkinsClient implements JenkinsApi { buildNumber: string; }): Promise<Build>; // (undocumented) + getJobBuilds(options: { + entity: CompoundEntityRef; + jobFullName: string; + }): Promise<Job>; + // (undocumented) getProjects(options: { entity: CompoundEntityRef; filter: { @@ -117,8 +134,28 @@ export const LatestRunCard: (props: { // @public (undocumented) export const LEGACY_JENKINS_ANNOTATION = 'jenkins.io/github-folder'; +// @public (undocumented) +export interface Project { + // (undocumented) + displayName: string; + // (undocumented) + fullDisplayName: string; + // (undocumented) + fullName: string; + // (undocumented) + inQueue: string; + // (undocumented) + lastBuild: Build; + // (undocumented) + onRestartClick: () => Promise<void>; + // (undocumented) + status: string; +} + // Warning: (ae-missing-release-tag) "Router" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const Router: () => React_2.JSX.Element; +export const Router: (props: { + columns?: TableColumn<Project>[]; +}) => React_2.JSX.Element; ``` diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index cfbac50ae5..8be847f002 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.8.7-next.1", + "version": "0.9.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -49,8 +49,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -58,9 +58,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/testing-library__jest-dom": "^5.9.1", "cross-fetch": "^3.1.5", diff --git a/plugins/jenkins/src/api/JenkinsApi.ts b/plugins/jenkins/src/api/JenkinsApi.ts index 04bd313227..1f6e7ec294 100644 --- a/plugins/jenkins/src/api/JenkinsApi.ts +++ b/plugins/jenkins/src/api/JenkinsApi.ts @@ -56,7 +56,32 @@ export interface Build { }; status: string; // == building ? 'running' : result, } +export interface JobBuild { + timestamp: number; + building: boolean; + duration: number; + result?: string; + fullDisplayName: string; + displayName: string; + url: string; + number: number; + inProgress: boolean; + queueId: number; + id: number; +} +export interface Job { + name: string; + displayName: string; + description: string; + fullDisplayName: string; + inQueue: boolean; + fullName: string; + url: string; + builds: JobBuild[]; +} + +/** @public */ export interface Project { // standard Jenkins lastBuild: Build; @@ -98,6 +123,11 @@ export interface JenkinsApi { buildNumber: string; }): Promise<Build>; + getJobBuilds(options: { + entity: CompoundEntityRef; + jobFullName: string; + }): Promise<Job>; + retry(options: { entity: CompoundEntityRef; jobFullName: string; @@ -212,4 +242,28 @@ export class JenkinsClient implements JenkinsApi { const { token } = await this.identityApi.getCredentials(); return token; } + + async getJobBuilds(options: { + entity: CompoundEntityRef; + jobFullName: string; + }): Promise<Job> { + const { entity, jobFullName } = options; + const url = `${await this.discoveryApi.getBaseUrl( + 'jenkins', + )}/v1/entity/${encodeURIComponent(entity.namespace)}/${encodeURIComponent( + entity.kind, + )}/${encodeURIComponent(entity.name)}/job/${encodeURIComponent( + jobFullName, + )}`; + + const idToken = await this.getToken(); + const response = await fetch(url, { + method: 'GET', + headers: { + ...(idToken && { Authorization: `Bearer ${idToken}` }), + }, + }); + + return (await response.json()).build; + } } diff --git a/plugins/jenkins/src/api/index.ts b/plugins/jenkins/src/api/index.ts index af1829c0b4..32c98ae5a6 100644 --- a/plugins/jenkins/src/api/index.ts +++ b/plugins/jenkins/src/api/index.ts @@ -16,4 +16,4 @@ export { JenkinsClient, jenkinsApiRef } from './JenkinsApi'; -export type { JenkinsApi } from './JenkinsApi'; +export type { JenkinsApi, Project } from './JenkinsApi'; diff --git a/plugins/jenkins/src/assets/dynamic-columns.png b/plugins/jenkins/src/assets/dynamic-columns.png new file mode 100644 index 0000000000..1a85257403 Binary files /dev/null and b/plugins/jenkins/src/assets/dynamic-columns.png differ diff --git a/plugins/jenkins/src/assets/jobrun-table.png b/plugins/jenkins/src/assets/jobrun-table.png new file mode 100644 index 0000000000..9fff841c3b Binary files /dev/null and b/plugins/jenkins/src/assets/jobrun-table.png differ diff --git a/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx b/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx index f82ce2e7ec..1f5d272c61 100644 --- a/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx +++ b/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx @@ -13,222 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Link, Progress, Table, TableColumn } from '@backstage/core-components'; -import { alertApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; -import { useEntityPermission } from '@backstage/plugin-catalog-react/alpha'; -import { Box, IconButton, Tooltip, Typography } from '@material-ui/core'; +import { Table, TableColumn } from '@backstage/core-components'; +import { Box, Typography } from '@material-ui/core'; import RetryIcon from '@material-ui/icons/Replay'; -import VisibilityIcon from '@material-ui/icons/Visibility'; -import { default as React, useState } from 'react'; +import { default as React } from 'react'; import { Project } from '../../../../api/JenkinsApi'; import JenkinsLogo from '../../../../assets/JenkinsLogo.svg'; -import { buildRouteRef } from '../../../../plugin'; import { useBuilds } from '../../../useBuilds'; -import { JenkinsRunStatus } from '../Status'; -import { jenkinsExecutePermission } from '@backstage/plugin-jenkins-common'; - -const FailCount = ({ count }: { count: number }): JSX.Element | null => { - if (count !== 0) { - return <>{count} failed</>; - } - return null; -}; - -const SkippedCount = ({ count }: { count: number }): JSX.Element | null => { - if (count !== 0) { - return <>{count} skipped</>; - } - return null; -}; - -const FailSkippedWidget = ({ - skipped, - failed, -}: { - skipped: number; - failed: number; -}): JSX.Element | null => { - if (skipped === 0 && failed === 0) { - return null; - } - - if (skipped !== 0 && failed !== 0) { - return ( - <> - {' '} - (<FailCount count={failed} />, <SkippedCount count={skipped} />) - </> - ); - } - - if (failed !== 0) { - return ( - <> - {' '} - (<FailCount count={failed} />) - </> - ); - } - - if (skipped !== 0) { - return ( - <> - {' '} - (<SkippedCount count={skipped} />) - </> - ); - } - - return null; -}; - -const generatedColumns: TableColumn[] = [ - { - title: 'Timestamp', - defaultSort: 'desc', - hidden: true, - field: 'lastBuild.timestamp', - }, - { - title: 'Build', - field: 'fullName', - highlight: true, - render: (row: Partial<Project>) => { - const LinkWrapper = () => { - const routeLink = useRouteRef(buildRouteRef); - if (!row.fullName || !row.lastBuild?.number) { - return ( - <> - {row.fullName || - row.fullDisplayName || - row.displayName || - 'Unknown'} - </> - ); - } - - return ( - <Link - to={routeLink({ - jobFullName: encodeURIComponent(row.fullName), - buildNumber: String(row.lastBuild?.number), - })} - > - {row.fullDisplayName} - </Link> - ); - }; - - return <LinkWrapper />; - }, - }, - { - title: 'Source', - field: 'lastBuild.source.branchName', - render: (row: Partial<Project>) => ( - <> - <Typography paragraph> - <Link to={row.lastBuild?.source?.url ?? ''}> - {row.lastBuild?.source?.branchName} - </Link> - </Typography> - <Typography paragraph>{row.lastBuild?.source?.commit?.hash}</Typography> - </> - ), - }, - { - title: 'Status', - field: 'status', - render: (row: Partial<Project>) => { - return ( - <Box display="flex" alignItems="center"> - <JenkinsRunStatus status={row.status} /> - </Box> - ); - }, - }, - { - title: 'Tests', - sorting: false, - render: (row: Partial<Project>) => { - return ( - <> - <Typography paragraph> - {row.lastBuild?.tests && ( - <Link to={row.lastBuild?.tests.testUrl ?? ''}> - {row.lastBuild?.tests.passed} / {row.lastBuild?.tests.total}{' '} - passed - <FailSkippedWidget - skipped={row.lastBuild?.tests.skipped} - failed={row.lastBuild?.tests.failed} - /> - </Link> - )} - - {!row.lastBuild?.tests && 'n/a'} - </Typography> - </> - ); - }, - }, - { - title: 'Actions', - sorting: false, - render: (row: Partial<Project>) => { - const ActionWrapper = () => { - const [isLoadingRebuild, setIsLoadingRebuild] = useState(false); - const { allowed, loading } = useEntityPermission( - jenkinsExecutePermission, - ); - - const alertApi = useApi(alertApiRef); - - const onRebuild = async () => { - if (row.onRestartClick) { - setIsLoadingRebuild(true); - try { - await row.onRestartClick(); - alertApi.post({ - message: 'Jenkins re-build has successfully executed', - severity: 'success', - display: 'transient', - }); - } catch (e) { - alertApi.post({ - message: `Jenkins re-build has failed. Error: ${e.message}`, - severity: 'error', - }); - } finally { - setIsLoadingRebuild(false); - } - } - }; - - return ( - <div style={{ width: '98px' }}> - {row.lastBuild?.url && ( - <Tooltip title="View build"> - <IconButton href={row.lastBuild.url} target="_blank"> - <VisibilityIcon /> - </IconButton> - </Tooltip> - )} - {isLoadingRebuild && <Progress />} - {!isLoadingRebuild && ( - <Tooltip title="Rerun build"> - <IconButton onClick={onRebuild} disabled={loading || !allowed}> - <RetryIcon /> - </IconButton> - </Tooltip> - )} - </div> - ); - }; - return <ActionWrapper />; - }, - width: '10%', - }, -]; +import { columnFactories } from './columns'; +import { defaultCITableColumns } from './presets'; type Props = { loading: boolean; @@ -239,6 +32,7 @@ type Props = { total: number; pageSize: number; onChangePageSize: (pageSize: number) => void; + columns: TableColumn<Project>[]; }; export const CITableView = ({ @@ -249,6 +43,7 @@ export const CITableView = ({ projects, onChangePage, onChangePageSize, + columns, total, }: Props) => { const projectsInPage = projects?.slice( @@ -279,20 +74,31 @@ export const CITableView = ({ <Typography variant="h6">Projects</Typography> </Box> } - columns={generatedColumns} + columns={ + columns && columns.length !== 0 ? columns : defaultCITableColumns + } /> ); }; -export const CITable = () => { +type CITableProps = { + columns?: TableColumn<Project>[]; +}; + +export const CITable = ({ columns }: CITableProps) => { const [tableProps, { setPage, retry, setPageSize }] = useBuilds(); return ( <CITableView {...tableProps} + columns={columns || ([] as TableColumn<Project>[])} retry={retry} onChangePageSize={setPageSize} onChangePage={setPage} /> ); }; + +CITable.columns = columnFactories; + +CITable.defaultCITableColumns = defaultCITableColumns; diff --git a/plugins/jenkins/src/components/BuildsPage/lib/CITable/columns.tsx b/plugins/jenkins/src/components/BuildsPage/lib/CITable/columns.tsx new file mode 100644 index 0000000000..f18d3e5b21 --- /dev/null +++ b/plugins/jenkins/src/components/BuildsPage/lib/CITable/columns.tsx @@ -0,0 +1,283 @@ +/* + * 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 { Link, Progress, TableColumn } from '@backstage/core-components'; +import { alertApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; +import { useEntityPermission } from '@backstage/plugin-catalog-react/alpha'; +import { Box, IconButton, Tooltip, Typography } from '@material-ui/core'; +import RetryIcon from '@material-ui/icons/Replay'; +import VisibilityIcon from '@material-ui/icons/Visibility'; +import HistoryIcon from '@material-ui/icons/History'; +import { default as React, useState } from 'react'; +import { Project } from '../../../../api/JenkinsApi'; +import { buildRouteRef, jobRunsRouteRef } from '../../../../plugin'; +import { JenkinsRunStatus } from '../Status'; +import { jenkinsExecutePermission } from '@backstage/plugin-jenkins-common'; + +const FailCount = ({ count }: { count: number }): JSX.Element | null => { + if (count !== 0) { + return <>{count} failed</>; + } + return null; +}; + +const SkippedCount = ({ count }: { count: number }): JSX.Element | null => { + if (count !== 0) { + return <>{count} skipped</>; + } + return null; +}; + +const FailSkippedWidget = ({ + skipped, + failed, +}: { + skipped: number; + failed: number; +}): JSX.Element | null => { + if (skipped === 0 && failed === 0) { + return null; + } + + if (skipped !== 0 && failed !== 0) { + return ( + <> + {' '} + (<FailCount count={failed} />, <SkippedCount count={skipped} />) + </> + ); + } + + if (failed !== 0) { + return ( + <> + {' '} + (<FailCount count={failed} />) + </> + ); + } + + if (skipped !== 0) { + return ( + <> + {' '} + (<SkippedCount count={skipped} />) + </> + ); + } + + return null; +}; + +export const columnFactories = Object.freeze({ + createTimestampColumn(): TableColumn<Project> { + return { + title: 'Timestamp', + defaultSort: 'desc', + hidden: true, + field: 'lastBuild.timestamp', + }; + }, + + createBuildColumn(): TableColumn<Project> { + return { + title: 'Build', + field: 'fullName', + highlight: true, + render: (row: Partial<Project>) => { + const LinkWrapper = () => { + const routeLink = useRouteRef(buildRouteRef); + if (!row.fullName || !row.lastBuild?.number) { + return ( + <> + {row.fullName || + row.fullDisplayName || + row.displayName || + 'Unknown'} + </> + ); + } + + return ( + <Link + to={routeLink({ + jobFullName: encodeURIComponent(row.fullName), + buildNumber: String(row.lastBuild?.number), + })} + > + {row.fullDisplayName} + </Link> + ); + }; + + return <LinkWrapper />; + }, + }; + }, + + createSourceColumn(): TableColumn<Project> { + return { + title: 'Source', + field: 'lastBuild.source.branchName', + render: (row: Partial<Project>) => ( + <> + <Typography paragraph> + <Link to={row.lastBuild?.source?.url ?? ''}> + {row.lastBuild?.source?.branchName} + </Link> + </Typography> + <Typography paragraph> + {row.lastBuild?.source?.commit?.hash} + </Typography> + </> + ), + }; + }, + + createStatusColumn(): TableColumn<Project> { + return { + title: 'Status', + field: 'status', + render: (row: Partial<Project>) => { + return ( + <Box display="flex" alignItems="center"> + <JenkinsRunStatus status={row.status} /> + </Box> + ); + }, + }; + }, + + createTestColumn(): TableColumn<Project> { + return { + title: 'Tests', + sorting: false, + render: (row: Partial<Project>) => { + return ( + <> + <Typography paragraph> + {row.lastBuild?.tests && ( + <Link to={row.lastBuild?.tests.testUrl ?? ''}> + {row.lastBuild?.tests.passed} / {row.lastBuild?.tests.total}{' '} + passed + <FailSkippedWidget + skipped={row.lastBuild?.tests.skipped} + failed={row.lastBuild?.tests.failed} + /> + </Link> + )} + + {!row.lastBuild?.tests && 'n/a'} + </Typography> + </> + ); + }, + }; + }, + + createLastRunDuration(): TableColumn<Project> { + return { + title: 'Last Run Duration', + align: 'left', + render: (row: Partial<Project>) => ( + <> + <Typography> + {row?.lastBuild?.duration + ? (row?.lastBuild?.duration / 1000) + .toFixed(1) + .toString() + .concat(' s') + : ''}{' '} + </Typography> + </> + ), + }; + }, + + createActionsColumn(): TableColumn<Project> { + return { + title: 'Actions', + sorting: false, + render: (row: Partial<Project>) => { + const ActionWrapper = () => { + const [isLoadingRebuild, setIsLoadingRebuild] = useState(false); + const { allowed, loading } = useEntityPermission( + jenkinsExecutePermission, + ); + + const alertApi = useApi(alertApiRef); + const jobRunsLink = useRouteRef(jobRunsRouteRef); + + const onRebuild = async () => { + if (row.onRestartClick) { + setIsLoadingRebuild(true); + try { + await row.onRestartClick(); + alertApi.post({ + message: 'Jenkins re-build has successfully executed', + severity: 'success', + display: 'transient', + }); + } catch (e) { + alertApi.post({ + message: `Jenkins re-build has failed. Error: ${e.message}`, + severity: 'error', + }); + } finally { + setIsLoadingRebuild(false); + } + } + }; + + return ( + <div style={{ width: '148px' }}> + {row.lastBuild?.url && ( + <Tooltip title="View build"> + <IconButton href={row.lastBuild.url} target="_blank"> + <VisibilityIcon /> + </IconButton> + </Tooltip> + )} + {isLoadingRebuild && <Progress />} + {!isLoadingRebuild && ( + <Tooltip title="Rerun build"> + <IconButton + onClick={onRebuild} + disabled={loading || !allowed} + > + <RetryIcon /> + </IconButton> + </Tooltip> + )} + <Link + to={jobRunsLink({ + jobFullName: encodeURIComponent(row.fullName || ''), + })} + > + <Tooltip title="View Runs"> + <IconButton> + <HistoryIcon /> + </IconButton> + </Tooltip> + </Link> + </div> + ); + }; + return <ActionWrapper />; + }, + width: '10%', + }; + }, +}); diff --git a/plugins/jenkins/src/components/BuildsPage/lib/CITable/presets.ts b/plugins/jenkins/src/components/BuildsPage/lib/CITable/presets.ts new file mode 100644 index 0000000000..828e035c8e --- /dev/null +++ b/plugins/jenkins/src/components/BuildsPage/lib/CITable/presets.ts @@ -0,0 +1,29 @@ +/* + * 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 { Project } from '../../../../api'; +import { columnFactories } from './columns'; +import { TableColumn } from '@backstage/core-components'; + +export const defaultCITableColumns: TableColumn<Project>[] = [ + columnFactories.createTimestampColumn(), + columnFactories.createSourceColumn(), + columnFactories.createBuildColumn(), + columnFactories.createTestColumn(), + columnFactories.createStatusColumn(), + columnFactories.createLastRunDuration(), + columnFactories.createActionsColumn(), +]; diff --git a/plugins/jenkins/src/components/JobRunsTable/JobRunsTable.tsx b/plugins/jenkins/src/components/JobRunsTable/JobRunsTable.tsx new file mode 100644 index 0000000000..78b66b98eb --- /dev/null +++ b/plugins/jenkins/src/components/JobRunsTable/JobRunsTable.tsx @@ -0,0 +1,187 @@ +/* + * 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 { Link, Table, TableColumn } from '@backstage/core-components'; +import { Box, IconButton, Tooltip, Typography } from '@material-ui/core'; +import { default as React } from 'react'; +import JenkinsLogo from './../../assets/JenkinsLogo.svg'; +import { useJobRuns } from './../useJobRuns'; +import { Job, JobBuild } from './../../api/JenkinsApi'; +import { JenkinsRunStatus } from './../BuildsPage/lib/Status'; +import VisibilityIcon from '@material-ui/icons/Visibility'; +import { jobRunsRouteRef } from '../../plugin'; +import { useRouteRefParams } from '@backstage/core-plugin-api'; + +const generatedColumns: TableColumn[] = [ + { + title: 'Number', + field: 'number', + render: (row: Partial<JobBuild>) => { + return ( + <Box display="flex" alignItems="center"> + <Typography paragraph> + <Link to={row.url ?? ''}>{row.number}</Link> + </Typography> + </Box> + ); + }, + }, + { + title: 'Timestamp', + field: 'timestamp', + render: (row: Partial<JobBuild>) => { + return ( + <Box display="flex" alignItems="center"> + <Typography> + {row?.timestamp ? new Date(row?.timestamp).toLocaleString() : ' '} + </Typography> + </Box> + ); + }, + }, + { + title: 'Result', + field: 'result', + render: (row: Partial<JobBuild>) => { + return ( + <Box display="flex" alignItems="center"> + {row.inProgress ? ( + <Typography>In Progress</Typography> + ) : ( + <JenkinsRunStatus status={row?.result} /> + )} + </Box> + ); + }, + }, + { + title: 'Duration', + field: 'duration', + render: (row: Partial<JobBuild>) => { + return ( + <Box display="flex" alignItems="center"> + <Typography> + {row?.duration + ? (row.duration / 1000).toFixed(1).toString().concat(' s') + : ''} + </Typography> + </Box> + ); + }, + }, + + { + title: 'Actions', + render: (row: Partial<JobBuild>) => { + const ActionWrapper = () => { + return ( + <div style={{ width: '98px' }}> + {row?.url && ( + <Tooltip title="View build"> + <Link component={IconButton} to={row.url}> + <VisibilityIcon /> + </Link> + </Tooltip> + )} + </div> + ); + }; + return <ActionWrapper />; + }, + width: '10%', + }, +]; + +type Props = { + loading: boolean; + jobRuns?: Job; + page: number; + onChangePage: (page: number) => void; + pageSize: number; + onChangePageSize: (pageSize: number) => void; +}; + +export const JobRunsTableView = ({ + loading, + pageSize, + page, + jobRuns, + onChangePage, + onChangePageSize, +}: Props) => { + const builds = jobRuns?.builds.slice( + page * pageSize, + page * pageSize + pageSize, + ); + let sumOfAllSuccessfulJobDuration = 0; + + const successfulJobCount = + builds?.reduce((count, build) => { + if (!build.inProgress && build.result === 'SUCCESS') { + sumOfAllSuccessfulJobDuration += build.duration; + return count + 1; + } + return count; + }, 0) || 0; + + let avgTime; + + if (successfulJobCount > 0) { + avgTime = (sumOfAllSuccessfulJobDuration / successfulJobCount / 1000) + .toFixed(1) + .toString(); + } + + return ( + <Table + isLoading={loading} + options={{ paging: true, pageSize, padding: 'dense' }} + totalCount={jobRuns?.builds.length || 0} + page={page} + data={builds ?? []} + onPageChange={onChangePage} + onRowsPerPageChange={onChangePageSize} + title={ + <Box> + <Box display="flex" alignItems="center"> + <img src={JenkinsLogo} alt="Jenkins logo" height="50px" /> + <Box mr={2} /> + <Typography variant="h6">{`${jobRuns?.displayName} Runs`}</Typography> + </Box> + <Box display="flex" alignItems="center" mt={2}> + <Typography variant="h6"> + Average Build Time For Last {successfulJobCount} Successful jobs :{' '} + {avgTime || 0} + </Typography> + </Box> + </Box> + } + columns={generatedColumns} + /> + ); +}; + +export const JobRunsTable = () => { + const { jobFullName } = useRouteRefParams(jobRunsRouteRef); + const [tableProps, { setPage, setPageSize }] = useJobRuns(jobFullName); + + return ( + <JobRunsTableView + {...tableProps} + onChangePageSize={setPageSize} + onChangePage={setPage} + /> + ); +}; diff --git a/plugins/jenkins/src/components/JobRunsTable/index.ts b/plugins/jenkins/src/components/JobRunsTable/index.ts new file mode 100644 index 0000000000..b74beeb315 --- /dev/null +++ b/plugins/jenkins/src/components/JobRunsTable/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { JobRunsTable } from './JobRunsTable'; diff --git a/plugins/jenkins/src/components/Router.tsx b/plugins/jenkins/src/components/Router.tsx index af13575c62..30ce999f31 100644 --- a/plugins/jenkins/src/components/Router.tsx +++ b/plugins/jenkins/src/components/Router.tsx @@ -15,31 +15,39 @@ */ import { Entity } from '@backstage/catalog-model'; -import { MissingAnnotationEmptyState } from '@backstage/core-components'; +import { + MissingAnnotationEmptyState, + TableColumn, +} from '@backstage/core-components'; import { useEntity } from '@backstage/plugin-catalog-react'; import React from 'react'; import { Route, Routes } from 'react-router-dom'; import { JENKINS_ANNOTATION, LEGACY_JENKINS_ANNOTATION } from '../constants'; -import { buildRouteRef } from '../plugin'; +import { buildRouteRef, jobRunsRouteRef } from '../plugin'; import { CITable } from './BuildsPage/lib/CITable'; import { DetailedViewPage } from './BuildWithStepsPage/'; +import { JobRunsTable } from './JobRunsTable'; +import { Project } from '../api'; /** @public */ export const isJenkinsAvailable = (entity: Entity) => Boolean(entity.metadata.annotations?.[JENKINS_ANNOTATION]) || Boolean(entity.metadata.annotations?.[LEGACY_JENKINS_ANNOTATION]); -export const Router = () => { +export const Router = (props: { columns?: TableColumn<Project>[] }) => { const { entity } = useEntity(); if (!isJenkinsAvailable(entity)) { return <MissingAnnotationEmptyState annotation={JENKINS_ANNOTATION} />; } + const columns = props.columns; + return ( <Routes> - <Route path="/" element={<CITable />} /> + <Route path="/" element={<CITable columns={columns} />} /> <Route path={`/${buildRouteRef.path}`} element={<DetailedViewPage />} /> + <Route path={`/${jobRunsRouteRef.path}`} element={<JobRunsTable />} /> </Routes> ); }; diff --git a/plugins/jenkins/src/components/useJobRuns.ts b/plugins/jenkins/src/components/useJobRuns.ts new file mode 100644 index 0000000000..d80e09b18b --- /dev/null +++ b/plugins/jenkins/src/components/useJobRuns.ts @@ -0,0 +1,70 @@ +/* + * 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 { useState } from 'react'; +import useAsyncRetry from 'react-use/lib/useAsyncRetry'; +import { jenkinsApiRef } from '../api'; +import { errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { useEntity } from '@backstage/plugin-catalog-react'; +import { getCompoundEntityRef } from '@backstage/catalog-model'; + +export enum ErrorType { + CONNECTION_ERROR, + NOT_FOUND, +} + +export function useJobRuns(jobFullName: string) { + const { entity } = useEntity(); + const api = useApi(jenkinsApiRef); + const errorApi = useApi(errorApiRef); + + const [page, setPage] = useState(0); + const [pageSize, setPageSize] = useState(5); + + const [error, setError] = useState<{ + message: string; + errorType: ErrorType; + }>(); + + const { loading, value: jobRuns } = useAsyncRetry(async () => { + try { + const jobBuilds = await api.getJobBuilds({ + entity: getCompoundEntityRef(entity), + jobFullName, + }); + return jobBuilds; + } catch (e) { + const errorType = e.notFound + ? ErrorType.NOT_FOUND + : ErrorType.CONNECTION_ERROR; + setError({ message: e.message, errorType }); + throw e; + } + }, [api, errorApi, entity]); + + return [ + { + page, + pageSize, + loading, + jobRuns, + error, + }, + { + setPage, + setPageSize, + }, + ] as const; +} diff --git a/plugins/jenkins/src/index.ts b/plugins/jenkins/src/index.ts index 7562026bdc..9d092014a0 100644 --- a/plugins/jenkins/src/index.ts +++ b/plugins/jenkins/src/index.ts @@ -25,6 +25,7 @@ export { jenkinsPlugin as plugin, EntityJenkinsContent, EntityLatestJenkinsRunCard, + EntityJobRunsTable, } from './plugin'; export { LatestRunCard } from './components/Cards'; export { diff --git a/plugins/jenkins/src/plugin.ts b/plugins/jenkins/src/plugin.ts index 7dbb6bfde1..1b666da9a9 100644 --- a/plugins/jenkins/src/plugin.ts +++ b/plugins/jenkins/src/plugin.ts @@ -38,6 +38,13 @@ export const buildRouteRef = createSubRouteRef({ parent: rootRouteRef, }); +/** @public */ +export const jobRunsRouteRef = createSubRouteRef({ + id: 'jenkins/job/runs', + path: '/builds/:jobFullName/runs', + parent: rootRouteRef, +}); + /** @public */ export const jenkinsPlugin = createPlugin({ id: 'jenkins', @@ -72,3 +79,13 @@ export const EntityLatestJenkinsRunCard = jenkinsPlugin.provide( }, }), ); + +/** @public */ +export const EntityJobRunsTable = jenkinsPlugin.provide( + createComponentExtension({ + name: 'EntityJobRunsTable', + component: { + lazy: () => import('./components/JobRunsTable').then(m => m.JobRunsTable), + }, + }), +); diff --git a/plugins/kafka-backend/CHANGELOG.md b/plugins/kafka-backend/CHANGELOG.md index bccda7319f..573be0062f 100644 --- a/plugins/kafka-backend/CHANGELOG.md +++ b/plugins/kafka-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-kafka-backend +## 0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## 0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.3.2-next.1 ### Patch Changes diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index d965258859..68060f254c 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.2-next.1", + "version": "0.3.3", "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 adb941bc3f..d24a6db0e2 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-kafka +## 0.3.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## 0.3.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + ## 0.3.25-next.1 ### Patch Changes diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index 5e699b3bcc..1580caa124 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.25-next.1", + "version": "0.3.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -44,8 +44,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -53,10 +53,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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", "jest-when": "^3.1.0", "msw": "^1.0.0" diff --git a/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsForEntity.test.tsx b/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsForEntity.test.tsx index e2393d0598..026331c7d9 100644 --- a/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsForEntity.test.tsx +++ b/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsForEntity.test.tsx @@ -15,7 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import React, { PropsWithChildren } from 'react'; import { useConsumerGroupsForEntity } from './useConsumerGroupsForEntity'; import { TestApiProvider } from '@backstage/test-utils'; @@ -165,12 +165,8 @@ describe('useConsumerGroupOffsets', () => { lifecycle: 'development', }, }; - const { result } = subject(); - expect(() => result.current).toThrow(); - expect(result.error).toStrictEqual( - new Error( - `Failed to parse kafka consumer group annotation: got "dev/another,consumer"`, - ), + expect(() => subject()).toThrow( + `Failed to parse kafka consumer group annotation: got "dev/another,consumer"`, ); }); }); diff --git a/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsOffsetsForEntity.test.tsx b/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsOffsetsForEntity.test.tsx index 8a7f28d69b..2f3fc21f93 100644 --- a/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsOffsetsForEntity.test.tsx +++ b/plugins/kafka/src/components/ConsumerGroupOffsets/useConsumerGroupsOffsetsForEntity.test.tsx @@ -15,7 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import { when } from 'jest-when'; import React, { PropsWithChildren } from 'react'; import { @@ -96,27 +96,28 @@ describe('useConsumerGroupOffsets', () => { .mockResolvedValue(consumerGroupOffsets); when(mockKafkaDashboardApi.getDashboardUrl).mockReturnValue({}); - const { result, waitForNextUpdate } = subject(); - await waitForNextUpdate(); - const [tableProps] = result.current; + const { result } = subject(); - expect(tableProps.consumerGroupsTopics).toStrictEqual([ - { - clusterId: 'prod', - consumerGroup: consumerGroupOffsets.consumerId, - dashboardUrl: undefined, - topics: consumerGroupOffsets.offsets, - }, - ]); + await waitFor(() => { + expect(result.current[0].consumerGroupsTopics).toStrictEqual([ + { + clusterId: 'prod', + consumerGroup: consumerGroupOffsets.consumerId, + dashboardUrl: undefined, + topics: consumerGroupOffsets.offsets, + }, + ]); + }); }); it('posts an error to the error api', async () => { const error = new Error('error!'); mockKafkaApi.getConsumerGroupOffsets.mockRejectedValueOnce(error); - const { waitForNextUpdate } = subject(); - await waitForNextUpdate(); + subject(); - expect(mockErrorApi.post).toHaveBeenCalledWith(error); + await waitFor(() => { + expect(mockErrorApi.post).toHaveBeenCalledWith(error); + }); }); }); diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index cef2f97198..138b47b345 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,59 @@ # @backstage/plugin-kubernetes-backend +## 0.13.0 + +### Minor Changes + +- ae943c3bb1: **BREAKING** Allow passing undefined `labelSelector` to `KubernetesFetcher` + + `KubernetesFetch` no longer auto-adds `labelSelector` when empty string was passed. + This is only applicable if you have custom ObjectProvider implementation, as build-in `KubernetesFanOutHandler` already does this + +### Patch Changes + +- cbb0e3c3f4: A new plugin has been introduced to house the extension points for Kubernetes backend plugin; at the moment only the `KubernetesObjectsProviderExtensionPoint` is present. The `kubernetes-backend` plugin was modified to use this new extension point. +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-node@0.1.0 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## 0.12.3-next.2 + +### Patch Changes + +- cbb0e3c3f4: A new plugin has been introduced to house the extension points for Kubernetes backend plugin; at the moment only the `KubernetesObjectsProviderExtensionPoint` is present. The `kubernetes-backend` plugin was modified to use this new extension point. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-kubernetes-node@0.1.0-next.0 + - @backstage/plugin-kubernetes-common@0.7.0-next.1 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/integration-aws-node@0.1.7-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 0.12.2-next.1 ### Patch Changes diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index 158b917a48..a6fa50848d 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -6,16 +6,18 @@ import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import type { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common'; +import { CustomResourcesByEntity } from '@backstage/plugin-kubernetes-node'; import { Duration } from 'luxon'; import { Entity } from '@backstage/catalog-model'; import express from 'express'; import type { FetchResponse } from '@backstage/plugin-kubernetes-common'; import type { JsonObject } from '@backstage/types'; import type { KubernetesFetchError } from '@backstage/plugin-kubernetes-common'; +import { KubernetesObjectsByEntity } from '@backstage/plugin-kubernetes-node'; +import { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node'; import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; import type { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; import { Logger } from 'winston'; -import type { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { RequestHandler } from 'http-proxy-middleware'; @@ -101,11 +103,7 @@ export interface CustomResource extends ObjectToFetch { objectType: 'customresources'; } -// @public (undocumented) -export interface CustomResourcesByEntity extends KubernetesObjectsByEntity { - // (undocumented) - customResources: CustomResourceMatcher[]; -} +export { CustomResourcesByEntity }; // @public (undocumented) export const DEFAULT_OBJECTS: ObjectToFetch[]; @@ -316,25 +314,9 @@ export interface KubernetesFetcher { ): Promise<FetchResponseWrapper>; } -// @public (undocumented) -export interface KubernetesObjectsByEntity { - // (undocumented) - auth: KubernetesRequestAuth; - // (undocumented) - entity: Entity; -} +export { KubernetesObjectsByEntity }; -// @public (undocumented) -export interface KubernetesObjectsProvider { - // (undocumented) - getCustomResourcesByEntity( - customResourcesByEntity: CustomResourcesByEntity, - ): Promise<ObjectsByEntityResponse>; - // (undocumented) - getKubernetesObjectsByEntity( - kubernetesObjectsByEntity: KubernetesObjectsByEntity, - ): Promise<ObjectsByEntityResponse>; -} +export { KubernetesObjectsProvider }; // @public (undocumented) export interface KubernetesObjectsProviderOptions { @@ -409,7 +391,7 @@ export interface ObjectFetchParams { // (undocumented) customResources: CustomResource[]; // (undocumented) - labelSelector: string; + labelSelector?: string; // (undocumented) namespace?: string; // (undocumented) diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index bb39a01c6c..cc0b5016e4 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.12.2-next.1", + "version": "0.13.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -61,12 +61,13 @@ "@backstage/plugin-auth-node": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", "@backstage/plugin-kubernetes-common": "workspace:^", + "@backstage/plugin-kubernetes-node": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/plugin-permission-node": "workspace:^", "@backstage/types": "workspace:^", "@google-cloud/container": "^4.0.0", "@jest-mock/express": "^2.0.1", - "@kubernetes/client-node": "0.18.1", + "@kubernetes/client-node": "0.19.0", "@types/express": "^4.17.6", "@types/http-proxy-middleware": "^0.19.3", "@types/luxon": "^3.0.0", @@ -86,6 +87,7 @@ "yn": "^4.0.0" }, "devDependencies": { + "@backstage/backend-app-api": "workspace:^", "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/aws4": "^1.5.1", diff --git a/plugins/kubernetes-backend/src/plugin.ts b/plugins/kubernetes-backend/src/plugin.ts index e2523b4ecd..83dbae15a0 100644 --- a/plugins/kubernetes-backend/src/plugin.ts +++ b/plugins/kubernetes-backend/src/plugin.ts @@ -22,14 +22,43 @@ import { import { catalogServiceRef } from '@backstage/plugin-catalog-node/alpha'; import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend'; +import { + KubernetesObjectsProviderExtensionPoint, + kubernetesObjectsProviderExtensionPoint, + KubernetesObjectsProvider, +} from '@backstage/plugin-kubernetes-node'; + +class ObjectsProvider implements KubernetesObjectsProviderExtensionPoint { + private objectsProvider: KubernetesObjectsProvider | undefined; + + getObjectsProvider() { + return this.objectsProvider; + } + + addObjectsProvider(provider: KubernetesObjectsProvider) { + if (this.objectsProvider) { + throw new Error( + 'Multiple Kubernetes objects provider is not supported at this time', + ); + } + this.objectsProvider = provider; + } +} /** * This is the backend plugin that provides the Kubernetes integration. * @alpha */ + export const kubernetesPlugin = createBackendPlugin({ pluginId: 'kubernetes', register(env) { + const extensionPoint = new ObjectsProvider(); + env.registerExtensionPoint( + kubernetesObjectsProviderExtensionPoint, + extensionPoint, + ); + env.registerInit({ deps: { http: coreServices.httpRouter, @@ -46,7 +75,9 @@ export const kubernetesPlugin = createBackendPlugin({ config, catalogApi, permissions, - }).build(); + }) + .setObjectsProvider(extensionPoint.getObjectsProvider()) + .build(); http.use(router); }, }); diff --git a/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts b/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts index 753be36fb0..b8254d781c 100644 --- a/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts +++ b/plugins/kubernetes-backend/src/routes/resourceRoutes.test.ts @@ -14,23 +14,64 @@ * limitations under the License. */ -import { errorHandler } from '@backstage/backend-common'; -import express from 'express'; import request from 'supertest'; -import Router from 'express-promise-router'; -import { addResourceRoutesToRouter } from './resourcesRoutes'; +import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; +import { ExtendedHttpServer } from '@backstage/backend-app-api'; +import { kubernetesObjectsProviderExtensionPoint } from '@backstage/plugin-kubernetes-node'; +import { createBackendModule } from '@backstage/backend-plugin-api'; import { Entity } from '@backstage/catalog-model'; describe('resourcesRoutes', () => { - let app: express.Express; + let app: ExtendedHttpServer; - beforeAll(() => { - app = express(); - app.use(express.json()); - const router = Router(); - addResourceRoutesToRouter( - router, - { + beforeAll(async () => { + const objectsProviderMock = { + getKubernetesObjectsByEntity: jest.fn().mockImplementation(args => { + if (args.entity.metadata.name === 'inject500') { + return Promise.reject(new Error('some internal error')); + } + + return Promise.resolve({ + items: [ + { + clusterOne: { + pods: [ + { + metadata: { + name: 'pod1', + }, + }, + ], + }, + }, + ], + }); + }), + getCustomResourcesByEntity: jest.fn().mockImplementation(args => { + if (args.entity.metadata.name === 'inject500') { + return Promise.reject(new Error('some internal error')); + } + + return Promise.resolve({ + items: [ + { + clusterOne: { + pods: [ + { + metadata: { + name: 'pod1', + }, + }, + ], + }, + }, + ], + }); + }), + }; + + jest.mock('@backstage/catalog-client', () => ({ + CatalogClient: jest.fn().mockImplementation(() => ({ getEntityByRef: jest.fn().mockImplementation(entityRef => { if (entityRef.name === 'noentity') { return Promise.resolve(undefined); @@ -43,61 +84,50 @@ describe('resourcesRoutes', () => { }, } as Entity); }), - } as any, - { - getKubernetesObjectsByEntity: jest.fn().mockImplementation(args => { - if (args.entity.metadata.name === 'inject500') { - return Promise.reject(new Error('some internal error')); - } + })), + })); - return Promise.resolve({ - items: [ - { - clusterOne: { - pods: [ - { - metadata: { - name: 'pod1', - }, - }, - ], - }, + const { server } = await startTestBackend({ + features: [ + mockServices.rootConfig.factory({ + data: { + kubernetes: { + serviceLocatorMethod: { + type: 'multiTenant', }, - ], - }); + clusterLocatorMethods: [ + { + type: 'config', + clusters: [], + }, + ], + }, + }, }), - getCustomResourcesByEntity: jest.fn().mockImplementation(args => { - if (args.entity.metadata.name === 'inject500') { - return Promise.reject(new Error('some internal error')); - } + import('@backstage/plugin-kubernetes-backend/alpha'), + createBackendModule({ + pluginId: 'kubernetes', + moduleId: 'testObjectsProvider', + register(env) { + env.registerInit({ + deps: { extension: kubernetesObjectsProviderExtensionPoint }, + async init({ extension }) { + extension.addObjectsProvider(objectsProviderMock); + }, + }); + }, + }), + ], + }); - return Promise.resolve({ - items: [ - { - clusterOne: { - pods: [ - { - metadata: { - name: 'pod1', - }, - }, - ], - }, - }, - ], - }); - }), - } as any, - ); - app.use('/', router); - app.use(errorHandler()); + app = server; }); describe('POST /resources/workloads/query', () => { // eslint-disable-next-line jest/expect-expect it('200 happy path', async () => { await request(app) - .post('/resources/workloads/query') + .post('/api/kubernetes/resources/workloads/query') .send({ entityRef: 'kind:namespacec/someComponent', auth: { @@ -125,7 +155,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('400 when missing entity ref', async () => { await request(app) - .post('/resources/workloads/query') + .post('/api/kubernetes/resources/workloads/query') .send({ auth: { google: 'something', @@ -137,7 +167,7 @@ describe('resourcesRoutes', () => { error: { name: 'InputError', message: 'entity is a required field' }, request: { method: 'POST', - url: '/resources/workloads/query', + url: '/api/kubernetes/resources/workloads/query', }, response: { statusCode: 400 }, }); @@ -145,7 +175,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('400 when bad entity ref', async () => { await request(app) - .post('/resources/workloads/query') + .post('/api/kubernetes/resources/workloads/query') .send({ entityRef: 'ffff', auth: { @@ -162,7 +192,7 @@ describe('resourcesRoutes', () => { }, request: { method: 'POST', - url: '/resources/workloads/query', + url: '/api/kubernetes/resources/workloads/query', }, response: { statusCode: 400 }, }); @@ -170,7 +200,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('400 when no entity in catalog', async () => { await request(app) - .post('/resources/workloads/query') + .post('/api/kubernetes/resources/workloads/query') .send({ entityRef: 'noentity:noentity', auth: { @@ -186,7 +216,7 @@ describe('resourcesRoutes', () => { }, request: { method: 'POST', - url: '/resources/workloads/query', + url: '/api/kubernetes/resources/workloads/query', }, response: { statusCode: 400 }, }); @@ -194,7 +224,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('401 when no Auth header', async () => { await request(app) - .post('/resources/workloads/query') + .post('/api/kubernetes/resources/workloads/query') .send({ entityRef: 'component:someComponent', auth: { @@ -206,7 +236,7 @@ describe('resourcesRoutes', () => { error: { name: 'AuthenticationError', message: 'No Backstage token' }, request: { method: 'POST', - url: '/resources/workloads/query', + url: '/api/kubernetes/resources/workloads/query', }, response: { statusCode: 401 }, }); @@ -214,7 +244,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('401 when invalid Auth header', async () => { await request(app) - .post('/resources/workloads/query') + .post('/api/kubernetes/resources/workloads/query') .send({ entityRef: 'component:someComponent', auth: { @@ -227,7 +257,7 @@ describe('resourcesRoutes', () => { error: { name: 'AuthenticationError', message: 'No Backstage token' }, request: { method: 'POST', - url: '/resources/workloads/query', + url: '/api/kubernetes/resources/workloads/query', }, response: { statusCode: 401 }, }); @@ -235,7 +265,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('500 handle gracefully', async () => { await request(app) - .post('/resources/workloads/query') + .post('/api/kubernetes/resources/workloads/query') .send({ entityRef: 'inject500:inject500/inject500', auth: { @@ -249,7 +279,10 @@ describe('resourcesRoutes', () => { name: 'Error', message: 'some internal error', }, - request: { method: 'POST', url: '/resources/workloads/query' }, + request: { + method: 'POST', + url: '/api/kubernetes/resources/workloads/query', + }, response: { statusCode: 500 }, }); }); @@ -258,7 +291,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('200 happy path', async () => { await request(app) - .post('/resources/custom/query') + .post('/api/kubernetes/resources/custom/query') .send({ entityRef: 'component:someComponent', auth: { @@ -293,7 +326,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('400 when missing custom resources', async () => { await request(app) - .post('/resources/custom/query') + .post('/api/kubernetes/resources/custom/query') .send({ entityRef: 'component:someComponent', auth: { @@ -309,7 +342,7 @@ describe('resourcesRoutes', () => { }, request: { method: 'POST', - url: '/resources/custom/query', + url: '/api/kubernetes/resources/custom/query', }, response: { statusCode: 400 }, }); @@ -317,7 +350,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('400 when custom resources not array', async () => { await request(app) - .post('/resources/custom/query') + .post('/api/kubernetes/resources/custom/query') .send({ entityRef: 'component:someComponent', auth: { @@ -334,7 +367,7 @@ describe('resourcesRoutes', () => { }, request: { method: 'POST', - url: '/resources/custom/query', + url: '/api/kubernetes/resources/custom/query', }, response: { statusCode: 400 }, }); @@ -342,7 +375,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('400 when custom resources empty', async () => { await request(app) - .post('/resources/custom/query') + .post('/api/kubernetes/resources/custom/query') .send({ entityRef: 'component:someComponent', auth: { @@ -359,7 +392,7 @@ describe('resourcesRoutes', () => { }, request: { method: 'POST', - url: '/resources/custom/query', + url: '/api/kubernetes/resources/custom/query', }, response: { statusCode: 400 }, }); @@ -367,7 +400,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('400 when missing entity ref', async () => { await request(app) - .post('/resources/custom/query') + .post('/api/kubernetes/resources/custom/query') .send({ auth: { google: 'something', @@ -386,7 +419,7 @@ describe('resourcesRoutes', () => { error: { name: 'InputError', message: 'entity is a required field' }, request: { method: 'POST', - url: '/resources/custom/query', + url: '/api/kubernetes/resources/custom/query', }, response: { statusCode: 400 }, }); @@ -394,7 +427,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('400 when bad entity ref', async () => { await request(app) - .post('/resources/custom/query') + .post('/api/kubernetes/resources/custom/query') .send({ entityRef: 'ffff', auth: { @@ -418,7 +451,7 @@ describe('resourcesRoutes', () => { }, request: { method: 'POST', - url: '/resources/custom/query', + url: '/api/kubernetes/resources/custom/query', }, response: { statusCode: 400 }, }); @@ -426,7 +459,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('400 when no entity in catalog', async () => { await request(app) - .post('/resources/custom/query') + .post('/api/kubernetes/resources/custom/query') .send({ entityRef: 'noentity:noentity', auth: { @@ -449,7 +482,7 @@ describe('resourcesRoutes', () => { }, request: { method: 'POST', - url: '/resources/custom/query', + url: '/api/kubernetes/resources/custom/query', }, response: { statusCode: 400 }, }); @@ -457,7 +490,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('401 when no Auth header', async () => { await request(app) - .post('/resources/custom/query') + .post('/api/kubernetes/resources/custom/query') .send({ entityRef: 'component:someComponent', auth: { @@ -476,7 +509,7 @@ describe('resourcesRoutes', () => { error: { name: 'AuthenticationError', message: 'No Backstage token' }, request: { method: 'POST', - url: '/resources/custom/query', + url: '/api/kubernetes/resources/custom/query', }, response: { statusCode: 401 }, }); @@ -484,7 +517,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('401 when invalid Auth header', async () => { await request(app) - .post('/resources/custom/query') + .post('/api/kubernetes/resources/custom/query') .send({ entityRef: 'component:someComponent', auth: { @@ -504,7 +537,7 @@ describe('resourcesRoutes', () => { error: { name: 'AuthenticationError', message: 'No Backstage token' }, request: { method: 'POST', - url: '/resources/custom/query', + url: '/api/kubernetes/resources/custom/query', }, response: { statusCode: 401 }, }); @@ -512,7 +545,7 @@ describe('resourcesRoutes', () => { // eslint-disable-next-line jest/expect-expect it('500 handle gracefully', async () => { await request(app) - .post('/resources/custom/query') + .post('/api/kubernetes/resources/custom/query') .send({ entityRef: 'inject500:inject500/inject500', auth: { @@ -533,7 +566,10 @@ describe('resourcesRoutes', () => { name: 'Error', message: 'some internal error', }, - request: { method: 'POST', url: '/resources/custom/query' }, + request: { + method: 'POST', + url: '/api/kubernetes/resources/custom/query', + }, response: { statusCode: 500 }, }); }); diff --git a/plugins/kubernetes-backend/src/routes/resourcesRoutes.ts b/plugins/kubernetes-backend/src/routes/resourcesRoutes.ts index 2b2a48f707..0468799908 100644 --- a/plugins/kubernetes-backend/src/routes/resourcesRoutes.ts +++ b/plugins/kubernetes-backend/src/routes/resourcesRoutes.ts @@ -21,7 +21,7 @@ import { import { CatalogApi } from '@backstage/catalog-client'; import { InputError, AuthenticationError } from '@backstage/errors'; import express, { Request } from 'express'; -import { KubernetesObjectsProvider } from '../types/types'; +import { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node'; import { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node'; export const addResourceRoutesToRouter = ( diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts index 9ac1bf6e5d..b05db36398 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts @@ -47,13 +47,13 @@ import { CustomResource, KubernetesClustersSupplier, KubernetesFetcher, - KubernetesObjectsProvider, KubernetesObjectsProviderOptions, KubernetesObjectTypes, KubernetesServiceLocator, ObjectsByEntityRequest, ServiceLocatorMethod, } from '../types/types'; +import { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node'; import { DEFAULT_OBJECTS, KubernetesFanOutHandler, diff --git a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts index f2f1c6d38f..02f7ab86df 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts @@ -25,8 +25,6 @@ import { FetchResponseWrapper, ObjectToFetch, CustomResource, - CustomResourcesByEntity, - KubernetesObjectsByEntity, } from '../types/types'; import { AuthenticationStrategy, KubernetesCredential } from '../auth/types'; import { @@ -46,6 +44,10 @@ import { CurrentResourceUsage, PodStatus, } from '@kubernetes/client-node'; +import { + CustomResourcesByEntity, + KubernetesObjectsByEntity, +} from '@backstage/plugin-kubernetes-node'; /** * diff --git a/plugins/kubernetes-backend/src/service/KubernetesFetcher.test.ts b/plugins/kubernetes-backend/src/service/KubernetesFetcher.test.ts index 574a1475fd..e388589e74 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFetcher.test.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFetcher.test.ts @@ -165,7 +165,7 @@ describe('KubernetesFetcher', () => { { metadata: { name: 'pod-name', - labels: { 'backstage.io/kubernetes-id': 'some-service' }, + labels: {}, }, }, ], @@ -226,7 +226,7 @@ describe('KubernetesFetcher', () => { { metadata: { name: 'pod-name', - labels: { 'backstage.io/kubernetes-id': 'some-service' }, + labels: {}, }, }, ], @@ -237,7 +237,7 @@ describe('KubernetesFetcher', () => { { metadata: { name: 'service-name', - labels: { 'backstage.io/kubernetes-id': 'some-service' }, + labels: {}, }, }, ], @@ -289,7 +289,7 @@ describe('KubernetesFetcher', () => { { metadata: { name: 'service-name', - labels: { 'backstage.io/kubernetes-id': 'some-service' }, + labels: {}, }, }, ], @@ -339,7 +339,7 @@ describe('KubernetesFetcher', () => { { metadata: { name: 'pod-name', - labels: { 'backstage.io/kubernetes-id': 'some-service' }, + labels: {}, }, }, ], @@ -350,7 +350,7 @@ describe('KubernetesFetcher', () => { { metadata: { name: 'service-name', - labels: { 'backstage.io/kubernetes-id': 'some-service' }, + labels: {}, }, }, ], @@ -420,7 +420,7 @@ describe('KubernetesFetcher', () => { { metadata: { name: 'pod-name', - labels: { 'backstage.io/kubernetes-id': 'some-service' }, + labels: {}, }, }, ], @@ -431,7 +431,7 @@ describe('KubernetesFetcher', () => { { metadata: { name: 'service-name', - labels: { 'backstage.io/kubernetes-id': 'some-service' }, + labels: {}, }, }, ], @@ -443,7 +443,7 @@ describe('KubernetesFetcher', () => { kind: 'Thing', metadata: { name: 'something-else', - labels: { 'backstage.io/kubernetes-id': 'some-service' }, + labels: {}, }, }, ], @@ -511,7 +511,7 @@ describe('KubernetesFetcher', () => { { metadata: { name: 'pod-name', - labels: { 'backstage.io/kubernetes-id': 'some-service' }, + labels: {}, }, }, ], @@ -861,7 +861,7 @@ describe('KubernetesFetcher', () => { { metadata: { name: 'pod-name', - labels: { 'backstage.io/kubernetes-id': 'some-service' }, + labels: {}, }, }, ], @@ -872,7 +872,7 @@ describe('KubernetesFetcher', () => { { metadata: { name: 'service-name', - labels: { 'backstage.io/kubernetes-id': 'some-service' }, + labels: {}, }, }, ], @@ -956,7 +956,7 @@ describe('KubernetesFetcher', () => { { metadata: { name: 'pod-name', - labels: { 'backstage.io/kubernetes-id': 'some-service' }, + labels: {}, }, }, ], diff --git a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts index e514f5fe0b..d5c945a864 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts @@ -101,8 +101,7 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher { apiVersion, plural, params.namespace, - params.labelSelector || - `backstage.io/kubernetes-id=${params.serviceId}`, + params.labelSelector, ).then( (r: Response): Promise<FetchResult> => r.ok diff --git a/plugins/kubernetes-backend/src/types/index.ts b/plugins/kubernetes-backend/src/types/index.ts index db229eae34..c8413c1aa9 100644 --- a/plugins/kubernetes-backend/src/types/index.ts +++ b/plugins/kubernetes-backend/src/types/index.ts @@ -15,3 +15,9 @@ */ export * from './types'; + +export type { + CustomResourcesByEntity, + KubernetesObjectsByEntity, + KubernetesObjectsProvider, +} from '@backstage/plugin-kubernetes-node'; diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index 3767791589..fa7d4f9e60 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -21,9 +21,7 @@ import type { CustomResourceMatcher, FetchResponse, KubernetesFetchError, - KubernetesRequestAuth, KubernetesRequestBody, - ObjectsByEntityResponse, } from '@backstage/plugin-kubernetes-common'; import { Config } from '@backstage/config'; import { KubernetesCredential } from '../auth/types'; @@ -37,7 +35,7 @@ export interface ObjectFetchParams { clusterDetails: ClusterDetails; credential: KubernetesCredential; objectTypesToFetch: Set<ObjectToFetch>; - labelSelector: string; + labelSelector?: string; customResources: CustomResource[]; namespace?: string; } @@ -229,33 +227,3 @@ export interface KubernetesObjectsProviderOptions { * @public */ export type ObjectsByEntityRequest = KubernetesRequestBody; - -/** - * - * @public - */ -export interface KubernetesObjectsByEntity { - entity: Entity; - auth: KubernetesRequestAuth; -} - -/** - * - * @public - */ -export interface CustomResourcesByEntity extends KubernetesObjectsByEntity { - customResources: CustomResourceMatcher[]; -} - -/** - * - * @public - */ -export interface KubernetesObjectsProvider { - getKubernetesObjectsByEntity( - kubernetesObjectsByEntity: KubernetesObjectsByEntity, - ): Promise<ObjectsByEntityResponse>; - getCustomResourcesByEntity( - customResourcesByEntity: CustomResourcesByEntity, - ): Promise<ObjectsByEntityResponse>; -} diff --git a/plugins/kubernetes-cluster/CHANGELOG.md b/plugins/kubernetes-cluster/CHANGELOG.md new file mode 100644 index 0000000000..fbb762282e --- /dev/null +++ b/plugins/kubernetes-cluster/CHANGELOG.md @@ -0,0 +1,35 @@ +# @backstage/plugin-kubernetes-cluster + +## 0.0.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-react@0.1.0 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## 0.0.1-next.0 + +### Patch Changes + +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-kubernetes-react@0.1.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-kubernetes-common@0.7.0-next.1 + - @backstage/config@1.1.1-next.0 diff --git a/plugins/kubernetes-cluster/package.json b/plugins/kubernetes-cluster/package.json index 2e1c8d8309..1949941d47 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.0", + "version": "0.0.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -57,8 +57,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -66,10 +66,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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/node": "^16.11.26", "msw": "^1.0.0" diff --git a/plugins/kubernetes-common/CHANGELOG.md b/plugins/kubernetes-common/CHANGELOG.md index 4bd84d3ca7..4db1264d6b 100644 --- a/plugins/kubernetes-common/CHANGELOG.md +++ b/plugins/kubernetes-common/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-kubernetes-common +## 0.7.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## 0.7.0-next.1 + +### Patch Changes + +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 0.7.0-next.0 ### Minor Changes diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index baf24cea5d..9fe232e68f 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.0-next.0", + "version": "0.7.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -44,7 +44,7 @@ "@backstage/errors": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", "@backstage/types": "workspace:^", - "@kubernetes/client-node": "0.18.1", + "@kubernetes/client-node": "0.19.0", "kubernetes-models": "^4.3.1", "lodash": "^4.17.21", "luxon": "^3.0.0" diff --git a/plugins/kubernetes-node/.eslintrc.js b/plugins/kubernetes-node/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/kubernetes-node/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/kubernetes-node/CHANGELOG.md b/plugins/kubernetes-node/CHANGELOG.md new file mode 100644 index 0000000000..cc128fcd7f --- /dev/null +++ b/plugins/kubernetes-node/CHANGELOG.md @@ -0,0 +1,27 @@ +# @backstage/plugin-kubernetes-node + +## 0.1.0 + +### Minor Changes + +- cbb0e3c3f4: A new plugin has been introduced to house the extension points for Kubernetes backend plugin; at the moment only the `KubernetesObjectsProviderExtensionPoint` is present. The `kubernetes-backend` plugin was modified to use this new extension point. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/backend-plugin-api@0.6.6 + +## 0.1.0-next.0 + +### Minor Changes + +- cbb0e3c3f4: A new plugin has been introduced to house the extension points for Kubernetes backend plugin; at the moment only the `KubernetesObjectsProviderExtensionPoint` is present. The `kubernetes-backend` plugin was modified to use this new extension point. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-kubernetes-common@0.7.0-next.1 + - @backstage/backend-plugin-api@0.6.6-next.2 diff --git a/plugins/kubernetes-node/README.md b/plugins/kubernetes-node/README.md new file mode 100644 index 0000000000..afdc299bce --- /dev/null +++ b/plugins/kubernetes-node/README.md @@ -0,0 +1,5 @@ +# @backstage/plugin-kubernetes-node + +Welcome to the Node.js library package for the kubernetes plugin! + +_This plugin was created through the Backstage CLI_ diff --git a/plugins/kubernetes-node/api-report.md b/plugins/kubernetes-node/api-report.md new file mode 100644 index 0000000000..d2981b32d1 --- /dev/null +++ b/plugins/kubernetes-node/api-report.md @@ -0,0 +1,47 @@ +## API Report File for "@backstage/plugin-kubernetes-node" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common'; +import { Entity } from '@backstage/catalog-model'; +import { ExtensionPoint } from '@backstage/backend-plugin-api'; +import { KubernetesObjectsProvider as KubernetesObjectsProvider_2 } from '@backstage/plugin-kubernetes-node'; +import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; +import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common'; + +// @public (undocumented) +export interface CustomResourcesByEntity extends KubernetesObjectsByEntity { + // (undocumented) + customResources: CustomResourceMatcher[]; +} + +// @public (undocumented) +export interface KubernetesObjectsByEntity { + // (undocumented) + auth: KubernetesRequestAuth; + // (undocumented) + entity: Entity; +} + +// @public (undocumented) +export interface KubernetesObjectsProvider { + // (undocumented) + getCustomResourcesByEntity( + customResourcesByEntity: CustomResourcesByEntity, + ): Promise<ObjectsByEntityResponse>; + // (undocumented) + getKubernetesObjectsByEntity( + kubernetesObjectsByEntity: KubernetesObjectsByEntity, + ): Promise<ObjectsByEntityResponse>; +} + +// @public +export interface KubernetesObjectsProviderExtensionPoint { + // (undocumented) + addObjectsProvider(provider: KubernetesObjectsProvider_2): void; +} + +// @public +export const kubernetesObjectsProviderExtensionPoint: ExtensionPoint<KubernetesObjectsProviderExtensionPoint>; +``` diff --git a/plugins/kubernetes-node/catalog-info.yaml b/plugins/kubernetes-node/catalog-info.yaml new file mode 100644 index 0000000000..ad04818e49 --- /dev/null +++ b/plugins/kubernetes-node/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-kubernetes-node + title: '@backstage/plugin-kubernetes-node' + description: Node.js library for the kubernetes plugin +spec: + lifecycle: experimental + type: backstage-node-library + owner: kubernetes-maintainers diff --git a/plugins/kubernetes-node/package.json b/plugins/kubernetes-node/package.json new file mode 100644 index 0000000000..6f63ba1364 --- /dev/null +++ b/plugins/kubernetes-node/package.json @@ -0,0 +1,35 @@ +{ + "name": "@backstage/plugin-kubernetes-node", + "description": "Node.js library for the kubernetes plugin", + "version": "0.1.0", + "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": "node-library" + }, + "scripts": { + "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:^" + }, + "files": [ + "dist" + ], + "dependencies": { + "@backstage/backend-plugin-api": "workspace:^", + "@backstage/catalog-model": "workspace:^", + "@backstage/plugin-kubernetes-common": "workspace:^" + } +} diff --git a/plugins/kubernetes-node/src/extensions.ts b/plugins/kubernetes-node/src/extensions.ts new file mode 100644 index 0000000000..152622cf96 --- /dev/null +++ b/plugins/kubernetes-node/src/extensions.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. + */ +import { createExtensionPoint } from '@backstage/backend-plugin-api'; +import { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node'; + +/** + * The interface for {@link kubernetesObjectsProviderExtensionPoint}. + * + * @public + */ +export interface KubernetesObjectsProviderExtensionPoint { + addObjectsProvider(provider: KubernetesObjectsProvider): void; +} + +/** + * An extension point the exposes the ability to configure a objects provider. + * + * @public + */ +export const kubernetesObjectsProviderExtensionPoint = + createExtensionPoint<KubernetesObjectsProviderExtensionPoint>({ + id: 'kubernetes.objects-provider', + }); diff --git a/plugins/kubernetes-node/src/index.ts b/plugins/kubernetes-node/src/index.ts new file mode 100644 index 0000000000..09ea4123ce --- /dev/null +++ b/plugins/kubernetes-node/src/index.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. + */ + +/** + * Node.js library for the kubernetes plugin. + * + * @packageDocumentation + */ + +// In this package you might for example export functions that +// help other plugins or modules interact with your plugin. + +/** + * Node.js library for the kubernetes plugin. + * + * @packageDocumentation + */ + +export { + kubernetesObjectsProviderExtensionPoint, + type KubernetesObjectsProviderExtensionPoint, +} from './extensions'; + +export * from './types'; diff --git a/plugins/user-settings/src/alpha.ts b/plugins/kubernetes-node/src/setupTests.ts similarity index 95% rename from plugins/user-settings/src/alpha.ts rename to plugins/kubernetes-node/src/setupTests.ts index e1f7678bae..4b9026cde5 100644 --- a/plugins/user-settings/src/alpha.ts +++ b/plugins/kubernetes-node/src/setupTests.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * from './translation'; +export {}; diff --git a/plugins/kubernetes-node/src/types/index.ts b/plugins/kubernetes-node/src/types/index.ts new file mode 100644 index 0000000000..34ed8a9604 --- /dev/null +++ b/plugins/kubernetes-node/src/types/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 './types'; diff --git a/plugins/kubernetes-node/src/types/types.ts b/plugins/kubernetes-node/src/types/types.ts new file mode 100644 index 0000000000..182f3ecfeb --- /dev/null +++ b/plugins/kubernetes-node/src/types/types.ts @@ -0,0 +1,53 @@ +/* + * 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 { + CustomResourceMatcher, + KubernetesRequestAuth, + ObjectsByEntityResponse, +} from '@backstage/plugin-kubernetes-common'; + +/** + * + * @public + */ + +export interface KubernetesObjectsProvider { + getKubernetesObjectsByEntity( + kubernetesObjectsByEntity: KubernetesObjectsByEntity, + ): Promise<ObjectsByEntityResponse>; + getCustomResourcesByEntity( + customResourcesByEntity: CustomResourcesByEntity, + ): Promise<ObjectsByEntityResponse>; +} + +/** + * + * @public + */ + +export interface KubernetesObjectsByEntity { + entity: Entity; + auth: KubernetesRequestAuth; +} +/** + * + * @public + */ + +export interface CustomResourcesByEntity extends KubernetesObjectsByEntity { + customResources: CustomResourceMatcher[]; +} diff --git a/plugins/kubernetes-react/CHANGELOG.md b/plugins/kubernetes-react/CHANGELOG.md index f7ed7bb39d..13c23a75bf 100644 --- a/plugins/kubernetes-react/CHANGELOG.md +++ b/plugins/kubernetes-react/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-kubernetes-react +## 0.1.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- 4262e12921: Handle mixed decimals and bigint when calculating k8s resource usage +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/types@1.1.1 + +## 0.1.0-next.1 + +### Patch Changes + +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- 5dac12e435: The kubernetes APIs invokes Authentication Strategies when Backstage-Kubernetes-Authorization-X-X headers are provided, this enable the possibility to invoke strategies that executes additional steps to get a kubernetes token like on pinniped or custom strategies +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-kubernetes-common@0.7.0-next.1 + - @backstage/types@1.1.1 + ## 0.1.0-next.0 ### Minor Changes diff --git a/plugins/kubernetes-react/package.json b/plugins/kubernetes-react/package.json index e708e9e455..03f647cfb2 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.0-next.0", + "version": "0.1.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -48,15 +48,14 @@ "xterm-addon-fit": "^0.8.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0" + "react": "^16.13.1 || ^17.0.0 || ^18.0.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.0.1", + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0", "jest-websocket-mock": "^2.5.0", "msw": "^1.3.1" }, diff --git a/plugins/kubernetes-react/src/components/Pods/Events/useEvents.test.tsx b/plugins/kubernetes-react/src/components/Pods/Events/useEvents.test.tsx index 15da221f64..f98e4f5e6e 100644 --- a/plugins/kubernetes-react/src/components/Pods/Events/useEvents.test.tsx +++ b/plugins/kubernetes-react/src/components/Pods/Events/useEvents.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import { useApi } from '@backstage/core-plugin-api'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import { useEvents } from './useEvents'; import { DateTime } from 'luxon'; @@ -49,7 +49,7 @@ describe('Events', () => { mockGetEventsByInvolvedObjectName.mockResolvedValue(response), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useEvents({ involvedObjectName: 'some-objecgt', namespace: 'some-namespace', @@ -59,7 +59,9 @@ describe('Events', () => { expect(result.current.loading).toEqual(true); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.loading).toEqual(false); + }); expect(result.current.error).toBeUndefined(); expect(result.current.loading).toEqual(false); diff --git a/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts b/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts index abd8fc392c..40ab619180 100644 --- a/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts +++ b/plugins/kubernetes-react/src/hooks/useCustomResources.test.ts @@ -16,7 +16,7 @@ import { useCustomResources } from './useCustomResources'; import { Entity } from '@backstage/catalog-model'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import { useApi } from '@backstage/core-plugin-api'; import { CustomResourceMatcher } from '@backstage/plugin-kubernetes-common'; import { generateAuth } from './auth'; @@ -97,17 +97,17 @@ describe('useCustomResources', () => { getCustomObjectsByEntity: mockGetCustomObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useCustomResources(entity, customResourceMatchers), ); expect(result.current.loading).toEqual(true); - await waitForNextUpdate(); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); + }); expectMocksCalledCorrectly(); }); @@ -117,20 +117,17 @@ describe('useCustomResources', () => { getCustomObjectsByEntity: mockGetCustomObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useCustomResources(entity, customResourceMatchers, 100), ); - await waitForNextUpdate(); - expect(result.current.error).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); - await waitForNextUpdate(); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); - - expectMocksCalledCorrectly(2); + expectMocksCalledCorrectly(2); + }); }); it('should return error when getObjectsByEntity throws', async () => { mockGenerateAuth.mockResolvedValue(entityWithAuthToken.auth); @@ -139,17 +136,17 @@ describe('useCustomResources', () => { message: 'some error', }), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useCustomResources(entity, customResourceMatchers), ); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBe('some error'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); - expect(result.current.error).toBe('some error'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); - - expectMocksCalledCorrectly(); + expectMocksCalledCorrectly(); + }); }); describe('when retrying', () => { @@ -162,21 +159,21 @@ describe('useCustomResources', () => { mockGetCustomObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useCustomResources(entity, customResourceMatchers, 100), ); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBe('generateAuth failed'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); - expect(result.current.error).toBe('generateAuth failed'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); - - await waitForNextUpdate(); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); + }); }); it('should reset error after getCustomObjectsByEntity has failed and then succeeded', async () => { @@ -186,21 +183,21 @@ describe('useCustomResources', () => { .mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useCustomResources(entity, customResourceMatchers, 100), ); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBe('failed to fetch'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); - expect(result.current.error).toBe('failed to fetch'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); - - await waitForNextUpdate(); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); + }); }); it('should reset data after generateAuth succeeded then failed', async () => { @@ -212,21 +209,21 @@ describe('useCustomResources', () => { mockGetCustomObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useCustomResources(entity, customResourceMatchers, 100), ); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); + }); - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); - - await waitForNextUpdate(); - - expect(result.current.error).toBe('generateAuth failed'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('generateAuth failed'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); }); it('should reset data after getCustomObjectsByEntity succeeded then failed', async () => { @@ -236,21 +233,21 @@ describe('useCustomResources', () => { .mockRejectedValue({ message: 'failed to fetch' }), }); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useCustomResources(entity, customResourceMatchers, 100), ); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); + }); - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); - - await waitForNextUpdate(); - - expect(result.current.error).toBe('failed to fetch'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('failed to fetch'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); }); }); }); diff --git a/plugins/kubernetes-react/src/hooks/useIsPodExecTerminalSupported.test.ts b/plugins/kubernetes-react/src/hooks/useIsPodExecTerminalSupported.test.ts index 1772e0d4f2..93bfb6dd4d 100644 --- a/plugins/kubernetes-react/src/hooks/useIsPodExecTerminalSupported.test.ts +++ b/plugins/kubernetes-react/src/hooks/useIsPodExecTerminalSupported.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { useApi } from '@backstage/core-plugin-api'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import { useIsPodExecTerminalSupported } from './useIsPodExecTerminalSupported'; @@ -68,15 +68,14 @@ describe('useIsClusterShellEnabled', () => { async ({ testClusters, returnValue }) => { clusters = testClusters; - const { result, waitForNextUpdate } = renderHook(() => - useIsPodExecTerminalSupported(), - ); + const { result } = renderHook(() => useIsPodExecTerminalSupported()); expect(result.current.loading).toEqual(true); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.loading).toEqual(false); + }); - expect(result.current.loading).toEqual(false); expect(result.current.value).toBe(returnValue); }, ); diff --git a/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts b/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts index 5c4db4db14..e88432f980 100644 --- a/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts +++ b/plugins/kubernetes-react/src/hooks/useKubernetesObjects.test.ts @@ -16,7 +16,7 @@ import { useKubernetesObjects } from './useKubernetesObjects'; import { Entity } from '@backstage/catalog-model'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import { useApi } from '@backstage/core-plugin-api'; import { generateAuth } from './auth'; @@ -87,19 +87,17 @@ describe('useKubernetesObjects', () => { getObjectsByEntity: mockGetObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesObjects(entity), - ); + const { result } = renderHook(() => useKubernetesObjects(entity)); expect(result.current.loading).toEqual(true); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); - - expectMocksCalledCorrectly(); + expectMocksCalledCorrectly(); + }); }); it('should update on an interval', async () => { mockGenerateAuth.mockResolvedValue(entityWithAuthToken.auth); @@ -107,20 +105,17 @@ describe('useKubernetesObjects', () => { getObjectsByEntity: mockGetObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesObjects(entity, 100), - ); - - await waitForNextUpdate(); - expect(result.current.error).toBeUndefined(); - - await waitForNextUpdate(); + const { result } = renderHook(() => useKubernetesObjects(entity, 100)); expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); - expectMocksCalledCorrectly(2); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toStrictEqual(mockResponse); + + expectMocksCalledCorrectly(2); + }); }); it('should return error when getObjectsByEntity throws', async () => { mockGenerateAuth.mockResolvedValue(entityWithAuthToken.auth); @@ -129,17 +124,15 @@ describe('useKubernetesObjects', () => { message: 'some error', }), }); - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesObjects(entity), - ); + const { result } = renderHook(() => useKubernetesObjects(entity)); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBe('some error'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); - expect(result.current.error).toBe('some error'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); - - expectMocksCalledCorrectly(); + expectMocksCalledCorrectly(); + }); }); describe('when retrying', () => { @@ -152,21 +145,19 @@ describe('useKubernetesObjects', () => { mockGetObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesObjects(entity, 100), - ); + const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBe('generateAuth failed'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); - expect(result.current.error).toBe('generateAuth failed'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); - - await waitForNextUpdate(); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); + }); }); it('should reset error after getObjectsByEntity has failed and then succeeded', async () => { @@ -176,21 +167,19 @@ describe('useKubernetesObjects', () => { .mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesObjects(entity, 100), - ); + const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBe('failed to fetch'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); - expect(result.current.error).toBe('failed to fetch'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); - - await waitForNextUpdate(); - - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); + }); }); it('should reset data after generateAuth succeeded then failed', async () => { @@ -202,21 +191,19 @@ describe('useKubernetesObjects', () => { mockGetObjectsByEntity.mockResolvedValue(mockResponse), }); - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesObjects(entity, 100), - ); + const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); + }); - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); - - await waitForNextUpdate(); - - expect(result.current.error).toBe('generateAuth failed'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('generateAuth failed'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); }); it('should reset data after getObjectsByEntity succeeded then failed', async () => { @@ -226,21 +213,19 @@ describe('useKubernetesObjects', () => { .mockRejectedValue({ message: 'failed to fetch' }), }); - const { result, waitForNextUpdate } = renderHook(() => - useKubernetesObjects(entity, 100), - ); + const { result } = renderHook(() => useKubernetesObjects(entity, 100)); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.error).toBeUndefined(); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).not.toBeUndefined(); + }); - expect(result.current.error).toBeUndefined(); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).not.toBeUndefined(); - - await waitForNextUpdate(); - - expect(result.current.error).toBe('failed to fetch'); - expect(result.current.loading).toEqual(false); - expect(result.current.kubernetesObjects).toBeUndefined(); + await waitFor(() => { + expect(result.current.error).toBe('failed to fetch'); + expect(result.current.loading).toEqual(false); + expect(result.current.kubernetesObjects).toBeUndefined(); + }); }); }); }); diff --git a/plugins/kubernetes-react/src/hooks/useMatchingErrors.test.tsx b/plugins/kubernetes-react/src/hooks/useMatchingErrors.test.tsx index 4d817e838d..f8312eac4e 100644 --- a/plugins/kubernetes-react/src/hooks/useMatchingErrors.test.tsx +++ b/plugins/kubernetes-react/src/hooks/useMatchingErrors.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { DetectedErrorsContext, useMatchingErrors } from './useMatchingErrors'; import { DetectedError, diff --git a/plugins/kubernetes-react/src/hooks/usePodMetrics.test.tsx b/plugins/kubernetes-react/src/hooks/usePodMetrics.test.tsx index be74448abd..45c53e822d 100644 --- a/plugins/kubernetes-react/src/hooks/usePodMetrics.test.tsx +++ b/plugins/kubernetes-react/src/hooks/usePodMetrics.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { PodMetricsContext, usePodMetrics } from './usePodMetrics'; import { ClientPodStatus } from '@backstage/plugin-kubernetes-common'; diff --git a/plugins/kubernetes-react/src/utils/pod.test.tsx b/plugins/kubernetes-react/src/utils/pod.test.tsx index 06d4e22371..c48e40cd42 100644 --- a/plugins/kubernetes-react/src/utils/pod.test.tsx +++ b/plugins/kubernetes-react/src/utils/pod.test.tsx @@ -24,18 +24,18 @@ import { SubvalueCell } from '@backstage/core-components'; describe('pod', () => { describe('currentToDeclaredResourceToPerc', () => { - it('10%', () => { - const tests: (number | string)[][] = [ - [10, 100], - [10, '100'], - ['10', 100], - ['10', '100'], - ]; - tests.forEach(([a, b]) => { - const result = currentToDeclaredResourceToPerc(a, b); - expect(result).toBe('10%'); - }); - }); + it.each([ + [10, 100], + [10, '100'], + ['10', 100], + ['10', '100'], + ['10', 100.0], + [10.0, '100'], + [10.1, '100'], + ['10', 100.1], + ])('%p out of %p gives 10%%', (current, resource) => + expect(currentToDeclaredResourceToPerc(current, resource)).toBe('10%'), + ); }); describe('podStatusToCpuUtil', () => { it('does use correct units', () => { diff --git a/plugins/kubernetes-react/src/utils/pod.tsx b/plugins/kubernetes-react/src/utils/pod.tsx index 9c0ce898a3..1123f11427 100644 --- a/plugins/kubernetes-react/src/utils/pod.tsx +++ b/plugins/kubernetes-react/src/utils/pod.tsx @@ -126,8 +126,12 @@ export const currentToDeclaredResourceToPerc = ( return `${Math.round((current / resource) * 100)}%`; } - const numerator: bigint = BigInt(current); - const denominator: bigint = BigInt(resource); + const numerator: bigint = BigInt( + typeof current === 'number' ? Math.round(current) : current, + ); + const denominator: bigint = BigInt( + typeof resource === 'number' ? Math.round(resource) : resource, + ); return `${(numerator * BigInt(100)) / denominator}%`; }; diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 55fda1b465..e208c83b06 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/plugin-kubernetes +## 0.11.0 + +### Minor Changes + +- 2d8151061c: Refactor Kubernetes plugins in line with ADR 11, no breaking changes yet + +### Patch Changes + +- 9101c0d1b6: Updated dependency `@kubernetes/client-node` to `0.19.0`. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- b0aca1a798: Updated dependency `xterm-addon-attach` to `^0.9.0`. + Updated dependency `xterm-addon-fit` to `^0.8.0`. +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-kubernetes-react@0.1.0 + - @backstage/plugin-kubernetes-common@0.7.0 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.11.0-next.2 + +### Patch Changes + +- 95518765ee: Add Kubernetes cluster plugin. Viewing Kubernetes clusters as an Admin from Backstage +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-kubernetes-react@0.1.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-kubernetes-common@0.7.0-next.1 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + ## 0.11.0-next.1 ### Minor Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 8ed59595c2..ed2dfd35ec 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.0-next.1", + "version": "0.11.0", "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.18.1", + "@kubernetes/client-node": "0.19.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", @@ -58,12 +58,12 @@ "luxon": "^3.0.0", "react-use": "^17.2.4", "xterm": "^5.2.1", - "xterm-addon-attach": "^0.8.0", - "xterm-addon-fit": "^0.7.0" + "xterm-addon-attach": "^0.9.0", + "xterm-addon-fit": "^0.8.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -71,10 +71,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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", "jest-websocket-mock": "^2.4.1", "msw": "^1.0.0" diff --git a/plugins/lighthouse-backend/CHANGELOG.md b/plugins/lighthouse-backend/CHANGELOG.md index 32c2b599dd..76b12fb1f4 100644 --- a/plugins/lighthouse-backend/CHANGELOG.md +++ b/plugins/lighthouse-backend/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-lighthouse-backend +## 0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4 + +## 0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4-next.0 + ## 0.3.2-next.1 ### Patch Changes diff --git a/plugins/lighthouse-backend/package.json b/plugins/lighthouse-backend/package.json index bd337e185a..e5306695cc 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.2-next.1", + "version": "0.3.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse-common/CHANGELOG.md b/plugins/lighthouse-common/CHANGELOG.md index ddeffb94b3..ded0273147 100644 --- a/plugins/lighthouse-common/CHANGELOG.md +++ b/plugins/lighthouse-common/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-lighthouse-common +## 0.1.4 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1 + +## 0.1.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.1.1-next.0 + ## 0.1.3 ### Patch Changes diff --git a/plugins/lighthouse-common/package.json b/plugins/lighthouse-common/package.json index 086ee6cccd..e03436fd88 100644 --- a/plugins/lighthouse-common/package.json +++ b/plugins/lighthouse-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse-common", "description": "Common functionalities for lighthouse, to be shared between lighthouse and lighthouse-backend plugin", - "version": "0.1.3", + "version": "0.1.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index 4ae227281a..0b9130363f 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-lighthouse +## 0.4.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-lighthouse-common@0.1.4 + +## 0.4.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-lighthouse-common@0.1.4-next.0 + ## 0.4.10-next.1 ### Patch Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 1b81e64511..c039ae6b30 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.10-next.1", + "version": "0.4.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -57,10 +57,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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", "msw": "^1.0.0" }, diff --git a/plugins/lighthouse/src/components/AuditList/index.tsx b/plugins/lighthouse/src/components/AuditList/index.tsx index c433bb1900..f030ec4708 100644 --- a/plugins/lighthouse/src/components/AuditList/index.tsx +++ b/plugins/lighthouse/src/components/AuditList/index.tsx @@ -44,7 +44,9 @@ import { useApi } from '@backstage/core-plugin-api'; export const LIMIT = 10; const AuditList = () => { - const [dismissedStored] = useLocalStorage(LIGHTHOUSE_INTRO_LOCAL_STORAGE); + const [dismissedStored] = useLocalStorage<boolean>( + LIGHTHOUSE_INTRO_LOCAL_STORAGE, + ); const [dismissed, setDismissed] = useState(dismissedStored); const query = useQuery(); diff --git a/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx b/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx index 199ede3049..69acd34dc3 100644 --- a/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx +++ b/plugins/lighthouse/src/hooks/useWebsiteForEntity.test.tsx @@ -15,7 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; import { EntityProvider } from '@backstage/plugin-catalog-react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import React, { PropsWithChildren } from 'react'; import { WebsiteListResponse } from '@backstage/plugin-lighthouse-common'; import { lighthouseApiRef } from '../api'; @@ -77,9 +77,10 @@ describe('useWebsiteForEntity', () => { }); it('returns the lighthouse information for the website url in annotations', async () => { - const { result, waitForNextUpdate } = subject(); - await waitForNextUpdate(); - expect(result.current?.value).toBe(website); + const { result } = subject(); + await waitFor(() => { + expect(result.current?.value).toBe(website); + }); }); describe('where there is an error', () => { @@ -92,10 +93,11 @@ describe('useWebsiteForEntity', () => { }); it('posts the error to the error api and returns the error to the caller', async () => { - const { result, waitForNextUpdate } = subject(); - await waitForNextUpdate(); - expect(result.current?.error).toBe(error); - expect(mockErrorApi.post).toHaveBeenCalledWith(error); + const { result } = subject(); + await waitFor(() => { + expect(result.current?.error).toBe(error); + expect(mockErrorApi.post).toHaveBeenCalledWith(error); + }); }); }); @@ -109,10 +111,11 @@ describe('useWebsiteForEntity', () => { }); it('does not post the error to the error api and returns the error to the caller', async () => { - const { result, waitForNextUpdate } = subject(); - await waitForNextUpdate(); - expect(result.current?.error).toBe(error); - expect(mockErrorApi.post).not.toHaveBeenCalledWith(error); + const { result } = subject(); + await waitFor(() => { + expect(result.current?.error).toBe(error); + expect(mockErrorApi.post).not.toHaveBeenCalledWith(error); + }); }); }); }); diff --git a/plugins/linguist-backend/CHANGELOG.md b/plugins/linguist-backend/CHANGELOG.md index 5bc5640704..74a4eb35a6 100644 --- a/plugins/linguist-backend/CHANGELOG.md +++ b/plugins/linguist-backend/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-linguist-backend +## 0.5.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-linguist-common@0.1.2 + +## 0.5.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-linguist-common@0.1.2 + ## 0.5.2-next.1 ### Patch Changes diff --git a/plugins/linguist-backend/package.json b/plugins/linguist-backend/package.json index 99ce86abd8..78aa0868d4 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.2-next.1", + "version": "0.5.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/linguist-backend/src/service/standaloneServer.ts b/plugins/linguist-backend/src/service/standaloneServer.ts index 11604cddfb..518efed6a0 100644 --- a/plugins/linguist-backend/src/service/standaloneServer.ts +++ b/plugins/linguist-backend/src/service/standaloneServer.ts @@ -17,16 +17,16 @@ import { createServiceBuilder, loadBackendConfig, - SingleHostDiscovery, + HostDiscovery, UrlReaders, - useHotMemoize, ServerTokenManager, + DatabaseManager, } from '@backstage/backend-common'; import { Server } from 'http'; import { Logger } from 'winston'; import { createRouter } from './router'; -import knexFactory from 'knex'; import { TaskScheduleDefinition } from '@backstage/backend-tasks'; +import { ConfigReader } from '@backstage/config'; export interface ServerOptions { port: number; @@ -39,19 +39,14 @@ export async function startStandaloneServer( ): Promise<Server> { const logger = options.logger.child({ service: 'linguist-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); - const db = useHotMemoize(module, () => { - const knex = knexFactory({ - client: 'sqlite3', - connection: ':memory:', - useNullAsDefault: true, - }); - - knex.client.pool.on('createSuccess', (_eventId: any, resource: any) => { - resource.run('PRAGMA foreign_keys = ON', () => {}); - }); - - return knex; - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('linguist'); const schedule: TaskScheduleDefinition = { frequency: { minutes: 2 }, @@ -63,8 +58,8 @@ export async function startStandaloneServer( const router = await createRouter( { schedule: schedule, age: { days: 30 }, useSourceLocation: false }, { - database: { getClient: async () => db }, - discovery: SingleHostDiscovery.fromConfig(config), + database, + discovery: HostDiscovery.fromConfig(config), reader: UrlReaders.default({ logger, config }), logger, tokenManager: ServerTokenManager.noop(), diff --git a/plugins/linguist/CHANGELOG.md b/plugins/linguist/CHANGELOG.md index b5f72d53ba..85db830a62 100644 --- a/plugins/linguist/CHANGELOG.md +++ b/plugins/linguist/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-linguist +## 0.1.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-linguist-common@0.1.2 + +## 0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-linguist-common@0.1.2 + ## 0.1.10-next.1 ### Patch Changes diff --git a/plugins/linguist/package.json b/plugins/linguist/package.json index 4bdc89ce29..3d101548a2 100644 --- a/plugins/linguist/package.json +++ b/plugins/linguist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-linguist", - "version": "0.1.10-next.1", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,8 +45,8 @@ "slugify": "^1.6.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -54,9 +54,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/microsoft-calendar/CHANGELOG.md b/plugins/microsoft-calendar/CHANGELOG.md index 1b1942ce6f..9e8f04b435 100644 --- a/plugins/microsoft-calendar/CHANGELOG.md +++ b/plugins/microsoft-calendar/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-microsoft-calendar +## 0.1.8 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.1.8-next.1 ### Patch Changes diff --git a/plugins/microsoft-calendar/package.json b/plugins/microsoft-calendar/package.json index 63ce1d7dfa..57c4a75c39 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.8-next.1", + "version": "0.1.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -65,8 +65,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -74,9 +74,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/newrelic-dashboard/CHANGELOG.md b/plugins/newrelic-dashboard/CHANGELOG.md index c667e3594c..1c1a8bc5bf 100644 --- a/plugins/newrelic-dashboard/CHANGELOG.md +++ b/plugins/newrelic-dashboard/CHANGELOG.md @@ -1,5 +1,49 @@ # @backstage/plugin-newrelic-dashboard +## 0.3.0 + +### Minor Changes + +- d7eba6cab4: Changes in `newrelic-dashboard` plugin: + + - Make DashboardSnapshotList component public + - Settle discrepancies in the exported API + - Deprecate DashboardSnapshotComponent + +- e605ea4906: Add storybook for newrelic-dashboard plugin. + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 61d55942ae: Fix the styles for NewRelicDashboard, add more responsiveness +- 5194a51a1c: Fixed React Warning: "Each child in a list should have a unique 'key' prop" during the rendering of `EntityNewRelicDashboardCard` +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + +## 0.3.0-next.2 + +### Minor Changes + +- d7eba6cab4: Changes in `newrelic-dashboard` plugin: + + - Make DashboardSnapshotList component public + - Settle discrepancies in the exported API + - Deprecate DashboardSnapshotComponent + +### Patch Changes + +- 5194a51a1c: Fixed React Warning: "Each child in a list should have a unique 'key' prop" during the rendering of `EntityNewRelicDashboardCard` +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + ## 0.2.18-next.1 ### Patch Changes diff --git a/plugins/newrelic-dashboard/package.json b/plugins/newrelic-dashboard/package.json index af5003dc1a..15f25d6cc7 100644 --- a/plugins/newrelic-dashboard/package.json +++ b/plugins/newrelic-dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-newrelic-dashboard", - "version": "0.2.18-next.1", + "version": "0.3.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -41,14 +41,15 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/dev-utils": "workspace:^", - "@testing-library/jest-dom": "^5.10.1" + "@backstage/test-utils": "workspace:^", + "@testing-library/jest-dom": "^6.0.0" }, "files": [ "dist" diff --git a/plugins/newrelic-dashboard/src/components/NewRelicDashboard/DashboardEntityList.tsx b/plugins/newrelic-dashboard/src/components/NewRelicDashboard/DashboardEntityList.tsx index 6c89f3eb80..8d87a54ca0 100644 --- a/plugins/newrelic-dashboard/src/components/NewRelicDashboard/DashboardEntityList.tsx +++ b/plugins/newrelic-dashboard/src/components/NewRelicDashboard/DashboardEntityList.tsx @@ -69,9 +69,9 @@ export const DashboardEntityList = () => { <>No Dashboard Pages found with the specified Dashboard GUID</> )} {value?.getDashboardEntity?.data.actor.entitySearch.results.entities?.map( - (entityResult: ResultEntity) => { + (entityResult: ResultEntity, index: number) => { return ( - <Box style={{ margin: '10px' }} display="flex"> + <Box style={{ margin: '10px' }} display="flex" key={index}> <Box mr={1} className={classes.svgIcon}> <Typography component="div"> <DesktopMac /> diff --git a/plugins/newrelic-dashboard/src/components/NewRelicDashboard/DashboardSnapshotList/DashboardSnapshot.tsx b/plugins/newrelic-dashboard/src/components/NewRelicDashboard/DashboardSnapshotList/DashboardSnapshot.tsx index cdac4196d4..c19697a4f0 100644 --- a/plugins/newrelic-dashboard/src/components/NewRelicDashboard/DashboardSnapshotList/DashboardSnapshot.tsx +++ b/plugins/newrelic-dashboard/src/components/NewRelicDashboard/DashboardSnapshotList/DashboardSnapshot.tsx @@ -15,8 +15,7 @@ */ import React from 'react'; -import { Box, Grid, MenuItem, Select } from '@material-ui/core'; -import { useTheme } from '@material-ui/core/styles'; +import { Box, makeStyles, MenuItem, Select } from '@material-ui/core'; import { useApi, storageApiRef } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; import { @@ -29,6 +28,20 @@ import { newRelicDashboardApiRef } from '../../../api'; import { DashboardSnapshotSummary } from '../../../api/NewRelicDashboardApi'; import useObservable from 'react-use/lib/useObservable'; +const useStyles = makeStyles( + theme => ({ + cardSelect: { + margin: theme.spacing(2, 1, 0, 0), + }, + img: { + width: '100%', + height: 'auto', + border: `solid 1px ${theme.palette.common.black}`, + }, + }), + { name: 'BackstageNewRelicDashboardSnapshot' }, +); + /** * @public */ @@ -37,11 +50,7 @@ export const DashboardSnapshot = (props: { name: string; permalink: string; }) => { - const { - palette: { - common: { black }, - }, - } = useTheme(); + const classes = useStyles(); const { guid, name, permalink } = props; const newRelicDashboardAPI = useApi(newRelicDashboardApiRef); const storageApi = useApi(storageApiRef).forBucket('newrelic-dashboard'); @@ -76,14 +85,15 @@ export const DashboardSnapshot = (props: { /\pdf$/i, 'png', ); + return ( - <Grid container> - <InfoCard - variant="gridItem" - title={name} - action={ + <InfoCard + variant="gridItem" + title={name} + action={ + <div> <Select - style={{ margin: '15px 10px 0 0' }} + className={classes.cardSelect} defaultValue={2592000000} value={storageSnapshot.value} onChange={event => { @@ -97,24 +107,24 @@ export const DashboardSnapshot = (props: { <MenuItem value={604800000}>1 Week</MenuItem> <MenuItem value={2592000000}>1 Month</MenuItem> </Select> - } - > - <Box display="flex"> - <Box flexGrow="1"> - <Link to={permalink}> - {url ? ( - <img - alt={`${name} Dashbord`} - style={{ border: `solid 1px ${black}` }} - src={url} - /> - ) : ( - 'Dashboard loading... , click here to open if it did not render correctly' - )} - </Link> - </Box> + </div> + } + > + <Box display="flex"> + <Box flexGrow="1"> + <Link to={permalink}> + {url ? ( + <img + alt={`${name} Dashboard`} + className={classes.img} + src={url} + /> + ) : ( + 'Dashboard loading... , click here to open if it did not render correctly' + )} + </Link> </Box> - </InfoCard> - </Grid> + </Box> + </InfoCard> ); }; diff --git a/plugins/newrelic-dashboard/src/components/NewRelicDashboard/DashboardSnapshotList/DashboardSnapshotList.tsx b/plugins/newrelic-dashboard/src/components/NewRelicDashboard/DashboardSnapshotList/DashboardSnapshotList.tsx index 594a5fd53d..81686d10c9 100644 --- a/plugins/newrelic-dashboard/src/components/NewRelicDashboard/DashboardSnapshotList/DashboardSnapshotList.tsx +++ b/plugins/newrelic-dashboard/src/components/NewRelicDashboard/DashboardSnapshotList/DashboardSnapshotList.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React, { useState } from 'react'; -import { Grid, Tab, Tabs, makeStyles } from '@material-ui/core'; +import { Tab, Tabs, makeStyles, Box } from '@material-ui/core'; import { newRelicDashboardApiRef } from '../../../api'; import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; @@ -29,11 +29,22 @@ interface TabPanelProps { value1: number; } +const tabPanelStyles = makeStyles( + theme => ({ + tabPanel: { + marginTop: theme.spacing(0.5), + }, + }), + { name: 'BackstageNewRelicDashboardTabPanel' }, +); + function TabPanel(props: TabPanelProps) { const { children, value1, index, ...other } = props; + const classes = tabPanelStyles(tabPanelStyles); return ( <div + className={classes.tabPanel} role="tabpanel" hidden={value1 !== index} id={`simple-tabpanel-${index}`} @@ -102,7 +113,7 @@ export const DashboardSnapshotList = (props: { guid: string }) => { return <ErrorPanel title={error.name} defaultExpanded error={error} />; } return ( - <Grid container direction="column"> + <Box> <Tabs selectionFollowsFocus indicatorColor="primary" @@ -112,7 +123,6 @@ export const DashboardSnapshotList = (props: { guid: string }) => { aria-label="scrollable auto tabs example" onChange={handleChange} value={value1} - style={{ width: '100%' }} > {value?.getDashboardEntity?.data?.actor.entitySearch.results.entities?.map( (Entity: ResultEntity, index: number) => { @@ -143,6 +153,6 @@ export const DashboardSnapshotList = (props: { guid: string }) => { ); }, )} - </Grid> + </Box> ); }; diff --git a/plugins/newrelic-dashboard/src/components/NewRelicDashboard/NewRelicDashboard.stories.tsx b/plugins/newrelic-dashboard/src/components/NewRelicDashboard/NewRelicDashboard.stories.tsx new file mode 100644 index 0000000000..a15a4c573c --- /dev/null +++ b/plugins/newrelic-dashboard/src/components/NewRelicDashboard/NewRelicDashboard.stories.tsx @@ -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 React from 'react'; +import { NewRelicDashboard } from './NewRelicDashboard'; +import { MockStorageApi, TestApiProvider } from '@backstage/test-utils'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { newRelicDashboardApiRef } from '../../api'; +import { NEWRELIC_GUID_ANNOTATION } from '../../constants'; +import { storageApiRef } from '@backstage/core-plugin-api'; +import { Entity } from '@backstage/catalog-model'; + +function createImage( + width: number, + height: number, + bgColor: string, + text: string, +): HTMLCanvasElement { + const canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + const ctx = canvas.getContext('2d'); + if (ctx !== null) { + ctx.fillStyle = bgColor; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.fillStyle = '#000'; // text color + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.font = '20px sans-serif'; + ctx.fillText(text, canvas.width / 2, canvas.height / 2); + } + return canvas; +} + +const entity: Entity = { + apiVersion: '1', + kind: 'Component', + metadata: { + name: 'mocked entity with newrelic service', + title: 'app with newrelic', + annotations: { + [NEWRELIC_GUID_ANNOTATION]: 'some-cool-guid', + }, + }, +}; + +const newRelicApiMockEmpty = { + getDashboardEntity: () => Promise.resolve(undefined), +}; + +export const EmptyNewRelicDashboard = () => ( + <TestApiProvider apis={[[newRelicDashboardApiRef, newRelicApiMockEmpty]]}> + <EntityProvider entity={entity}> + <NewRelicDashboard /> + </EntityProvider> + </TestApiProvider> +); + +const resultEntities = [ + { + dashboardParentGuid: 'parent guid', + guid: 'guid', + permalink: 'http://example.com', + name: 'Production metrics', + }, +]; + +const dashboardEntity = { + data: { + actor: { + entitySearch: { + results: { + entities: resultEntities, + }, + }, + }, + }, +}; + +const entitySummary = { + getDashboardEntity: dashboardEntity, +}; + +const dashboardSnapshot = { + getDashboardSnapshot: { + data: { + dashboardCreateSnapshotUrl: createImage( + 1000, + 600, + '#ddd', + 'Example snapshot, imagine NewRelic panels here', + ).toDataURL(), + }, + }, +}; + +const newRelicApiMockFull = { + getDashboardEntity: () => Promise.resolve(entitySummary), + getDashboardSnapshot: () => Promise.resolve(dashboardSnapshot), +}; + +export const NewRelicDashboardWithSnapshots = () => ( + <TestApiProvider + apis={[ + [newRelicDashboardApiRef, newRelicApiMockFull], + [storageApiRef, MockStorageApi.create()], + ]} + > + <EntityProvider entity={entity}> + <NewRelicDashboard /> + </EntityProvider> + </TestApiProvider> +); + +export default { + title: 'NewRelic Dashboard', + component: EmptyNewRelicDashboard, +}; diff --git a/plugins/newrelic/CHANGELOG.md b/plugins/newrelic/CHANGELOG.md index a0d122a18c..65d2aad766 100644 --- a/plugins/newrelic/CHANGELOG.md +++ b/plugins/newrelic/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-newrelic +## 0.3.41 + +### Patch Changes + +- ce50a15506: Fixed sorting and searching in the NewRelic table. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## 0.3.41-next.2 + +### Patch Changes + +- ce50a15506: Fixed sorting and searching in the NewRelic table. +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + ## 0.3.41-next.1 ### Patch Changes diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index da63717dda..c4da950dee 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.41-next.1", + "version": "0.3.41", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -55,9 +55,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/parse-link-header": "^2.0.1", "cross-fetch": "^3.1.5", diff --git a/plugins/nomad-backend/CHANGELOG.md b/plugins/nomad-backend/CHANGELOG.md index a5186f75f8..b5661c4b40 100644 --- a/plugins/nomad-backend/CHANGELOG.md +++ b/plugins/nomad-backend/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-nomad-backend +## 0.1.8 + +### Patch Changes + +- 6822918c50: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## 0.1.8-next.2 + +### Patch Changes + +- 6822918c50: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/nomad-backend/package.json b/plugins/nomad-backend/package.json index 7873f846ba..60ba974467 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.7-next.1", + "version": "0.1.8", "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 15f8fca004..b6dff83c44 100644 --- a/plugins/nomad/CHANGELOG.md +++ b/plugins/nomad/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-nomad +## 0.1.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + +## 0.1.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + ## 0.1.6-next.1 ### Patch Changes diff --git a/plugins/nomad/package.json b/plugins/nomad/package.json index 5a3964cdc1..617c8e2c5a 100644 --- a/plugins/nomad/package.json +++ b/plugins/nomad/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-nomad", - "version": "0.1.6-next.1", + "version": "0.1.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -52,8 +52,8 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/octopus-deploy/CHANGELOG.md b/plugins/octopus-deploy/CHANGELOG.md index b9d7dc084f..64b61be538 100644 --- a/plugins/octopus-deploy/CHANGELOG.md +++ b/plugins/octopus-deploy/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-octopus-deploy +## 0.2.7 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + ## 0.2.7-next.1 ### Patch Changes diff --git a/plugins/octopus-deploy/package.json b/plugins/octopus-deploy/package.json index 5e0bf27520..3da25dc2c3 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.7-next.1", + "version": "0.2.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -41,8 +41,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -50,9 +50,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/opencost/CHANGELOG.md b/plugins/opencost/CHANGELOG.md index 60edb74ed8..b20b34b9c4 100644 --- a/plugins/opencost/CHANGELOG.md +++ b/plugins/opencost/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-opencost +## 0.2.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- 777b9a16a4: Fix for broken image reference. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## 0.2.1-next.2 + +### Patch Changes + +- 777b9a16a4: Fix for broken image reference. +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + ## 0.2.1-next.1 ### Patch Changes diff --git a/plugins/opencost/README.md b/plugins/opencost/README.md index 39c5e7ee2e..05c63206a2 100644 --- a/plugins/opencost/README.md +++ b/plugins/opencost/README.md @@ -28,7 +28,7 @@ and </FlatRoutes> ``` -3. Add link to OpenCost to your sidebar +3. Import the `MoneyIcon` and add link to OpenCost to your sidebar ```typescript // packages/app/src/components/Root/Root.tsx diff --git a/plugins/opencost/package.json b/plugins/opencost/package.json index d733276152..f751ed3ba5 100644 --- a/plugins/opencost/package.json +++ b/plugins/opencost/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-opencost", - "version": "0.2.1-next.1", + "version": "0.2.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -40,7 +40,7 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0", "react-router-dom": "*" }, "devDependencies": { @@ -48,8 +48,8 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/opencost/src/components/OpenCostPage/OpenCostPage.tsx b/plugins/opencost/src/components/OpenCostPage/OpenCostPage.tsx index bd60fa0c35..4062eca155 100644 --- a/plugins/opencost/src/components/OpenCostPage/OpenCostPage.tsx +++ b/plugins/opencost/src/components/OpenCostPage/OpenCostPage.tsx @@ -17,6 +17,7 @@ import React from 'react'; import { Grid } from '@material-ui/core'; import { Header, Page, Content } from '@backstage/core-components'; import { OpenCostReport } from '../OpenCostReport'; +import logo from '../../images/pig.png'; export const OpenCostPage = () => ( <Page themeId="tool"> @@ -25,12 +26,7 @@ export const OpenCostPage = () => ( subtitle="Open source Kubernetes cloud cost monitoring" > <a href="https://opencost.io"> - <img - width={68} - height={64} - src={require('../../images/pig.png')} - alt="OpenCost" - /> + <img width={68} height={64} src={logo} alt="OpenCost" /> </a> </Header> <Content> diff --git a/plugins/org-react/CHANGELOG.md b/plugins/org-react/CHANGELOG.md index 2d5f4fbd7e..1b39333288 100644 --- a/plugins/org-react/CHANGELOG.md +++ b/plugins/org-react/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-org-react +## 0.1.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + +## 0.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + ## 0.1.14-next.1 ### Patch Changes diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index 28876a6700..2097c7658a 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.14-next.1", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -54,9 +54,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/org-react/src/components/GroupListPicker/GroupListPicker.tsx b/plugins/org-react/src/components/GroupListPicker/GroupListPicker.tsx index a47c346390..57a93ce0fe 100644 --- a/plugins/org-react/src/components/GroupListPicker/GroupListPicker.tsx +++ b/plugins/org-react/src/components/GroupListPicker/GroupListPicker.tsx @@ -74,7 +74,7 @@ export const GroupListPicker = (props: GroupListPickerProps) => { }, [catalogApi, groupTypes]); const handleChange = useCallback( - (_, v: GroupEntity | null) => { + (_: unknown, v: GroupEntity | null) => { onChange(v ?? undefined); setAnchorEl(null); }, diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index 6ede70db1b..1faaf20dbb 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-org +## 0.6.15 + +### Patch Changes + +- dc5b6b971b: Fixed the display of OwnershipCard with aggregated relations by loading relations when getting children of entity. + This allows the already existing recursive method to work properly when children of entity have children themselves. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 0.6.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + ## 0.6.15-next.1 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index 4f01b5fa09..b9bf7f0c02 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.15-next.1", + "version": "0.6.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -46,8 +46,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -59,10 +59,9 @@ "@backstage/plugin-permission-react": "workspace:^", "@backstage/test-utils": "workspace:^", "@backstage/types": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.0.1", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts index 587dc689e3..eac5a171ba 100644 --- a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts +++ b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts @@ -16,7 +16,7 @@ import { CompoundEntityRef, Entity } from '@backstage/catalog-model'; import { useGetEntities } from './useGetEntities'; import { CatalogApi } from '@backstage/catalog-client'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import { getEntityRelations } from '@backstage/plugin-catalog-react'; const givenParentGroup = 'team.squad1'; @@ -66,14 +66,14 @@ describe('useGetEntities', () => { describe('given aggregated relationsType', () => { const whenHookIsCalledWith = async (_entity: Entity) => { - const hook = renderHook( + const { result } = renderHook( ({ entity }) => useGetEntities(entity, 'aggregated'), { initialProps: { entity: _entity }, }, ); - await hook.waitForNextUpdate(); + await waitFor(() => expect(result.current.loading).toBe(false)); }; beforeEach(() => { @@ -207,14 +207,14 @@ describe('useGetEntities', () => { describe('given direct relationsType', () => { const whenHookIsCalledWith = async (_entity: Entity) => { - const hook = renderHook( + const { result } = renderHook( ({ entity }) => useGetEntities(entity, 'direct'), { initialProps: { entity: _entity }, }, ); - await hook.waitForNextUpdate(); + await waitFor(() => expect(result.current.loading).toBe(false)); }; it('given group entity should return directly owned entities', async () => { diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index d37d6b4033..457905f993 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-pagerduty +## 0.6.6 + +### Patch Changes + +- b9ce306814: Minor fix to avoid usage of deprecated prop +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-home-react@0.1.4 + - @backstage/theme@0.4.3 + +## 0.6.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-home-react@0.1.4-next.2 + ## 0.6.6-next.1 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index 4ade1d9224..0130724cfa 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.6-next.1", + "version": "0.6.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -50,8 +50,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -59,9 +59,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/periskop-backend/CHANGELOG.md b/plugins/periskop-backend/CHANGELOG.md index c4b41389b6..03f74fb422 100644 --- a/plugins/periskop-backend/CHANGELOG.md +++ b/plugins/periskop-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-periskop-backend +## 0.2.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## 0.2.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.2.2-next.1 ### Patch Changes diff --git a/plugins/periskop-backend/package.json b/plugins/periskop-backend/package.json index ff276b7a55..1ef6c62431 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.2-next.1", + "version": "0.2.3", "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 7030b94dfc..26c40e8b97 100644 --- a/plugins/periskop/CHANGELOG.md +++ b/plugins/periskop/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-periskop +## 0.1.23 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.1.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.1.23-next.1 ### Patch Changes diff --git a/plugins/periskop/package.json b/plugins/periskop/package.json index 9d47082842..9ec13e9ce1 100644 --- a/plugins/periskop/package.json +++ b/plugins/periskop/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-periskop", - "version": "0.1.23-next.1", + "version": "0.1.23", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -43,8 +43,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -52,9 +52,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/luxon": "^3.0.0", "msw": "^1.0.0" diff --git a/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md b/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md index 127e39e251..63e6e54cc2 100644 --- a/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md +++ b/plugins/permission-backend-module-policy-allow-all/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-permission-backend-module-allow-all-policy +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-permission-common@0.7.9 + +## 0.1.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 0.1.2-next.1 ### 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 2b309e852c..6ae8cc459d 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.2-next.1", + "version": "0.1.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-backend/CHANGELOG.md b/plugins/permission-backend/CHANGELOG.md index d3419ba508..a26b60baaf 100644 --- a/plugins/permission-backend/CHANGELOG.md +++ b/plugins/permission-backend/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-permission-backend +## 0.5.29 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## 0.5.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 0.5.28-next.1 ### Patch Changes diff --git a/plugins/permission-backend/package.json b/plugins/permission-backend/package.json index 2709204635..f222d51451 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.28-next.1", + "version": "0.5.29", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/permission-common/CHANGELOG.md b/plugins/permission-common/CHANGELOG.md index f39e4455ec..c017cd00fc 100644 --- a/plugins/permission-common/CHANGELOG.md +++ b/plugins/permission-common/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-permission-common +## 0.7.9 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.7.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + ## 0.7.8 ### Patch Changes diff --git a/plugins/permission-common/package.json b/plugins/permission-common/package.json index 050b696aef..0c8292a24d 100644 --- a/plugins/permission-common/package.json +++ b/plugins/permission-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-permission-common", "description": "Isomorphic types and client for Backstage permissions and authorization", - "version": "0.7.8", + "version": "0.7.9", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/plugins/permission-node/CHANGELOG.md b/plugins/permission-node/CHANGELOG.md index e387547156..222399e878 100644 --- a/plugins/permission-node/CHANGELOG.md +++ b/plugins/permission-node/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-permission-node +## 0.7.17 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## 0.7.17-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 0.7.16-next.1 ### Patch Changes diff --git a/plugins/permission-node/package.json b/plugins/permission-node/package.json index 9f57f44886..4ed3ceb7ae 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.16-next.1", + "version": "0.7.17", "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 0df727d454..493ee440b6 100644 --- a/plugins/permission-react/CHANGELOG.md +++ b/plugins/permission-react/CHANGELOG.md @@ -1,5 +1,24 @@ # @backstage/plugin-permission-react +## 0.4.16 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## 0.4.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 0.4.16-next.0 ### Patch Changes diff --git a/plugins/permission-react/package.json b/plugins/permission-react/package.json index 7e79128739..9a9650e762 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.16-next.0", + "version": "0.4.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -41,15 +41,15 @@ "swr": "^2.0.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3" + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0" }, "files": [ "dist" diff --git a/plugins/playlist-backend/CHANGELOG.md b/plugins/playlist-backend/CHANGELOG.md index c7f001ae4b..2fa8f35268 100644 --- a/plugins/playlist-backend/CHANGELOG.md +++ b/plugins/playlist-backend/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-playlist-backend +## 0.3.10 + +### Patch Changes + +- 9e46f5ff49: Added support to the playlist plugin for the new backend +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-playlist-common@0.1.11 + +## 0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-playlist-common@0.1.11-next.0 + ## 0.3.9-next.1 ### Patch Changes diff --git a/plugins/playlist-backend/package.json b/plugins/playlist-backend/package.json index 319206e6c6..d5b6a5bdaf 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.9-next.1", + "version": "0.3.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/playlist-backend/src/service/standaloneServer.ts b/plugins/playlist-backend/src/service/standaloneServer.ts index 3b6acfd09b..26a601822a 100644 --- a/plugins/playlist-backend/src/service/standaloneServer.ts +++ b/plugins/playlist-backend/src/service/standaloneServer.ts @@ -19,8 +19,7 @@ import { DatabaseManager, loadBackendConfig, ServerTokenManager, - SingleHostDiscovery, - useHotMemoize, + HostDiscovery, } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { DefaultIdentityClient } from '@backstage/plugin-auth-node'; @@ -40,18 +39,16 @@ export async function startStandaloneServer( ): Promise<Server> { const logger = options.logger.child({ service: 'playlist-backend' }); const config = await loadBackendConfig({ logger, argv: process.argv }); - const discovery = SingleHostDiscovery.fromConfig(config); + const discovery = HostDiscovery.fromConfig(config); - const database = useHotMemoize(module, () => { - const manager = DatabaseManager.fromConfig( - new ConfigReader({ - backend: { - database: { client: 'better-sqlite3', connection: ':memory:' }, - }, - }), - ); - return manager.forPlugin('playlist'); - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('playlist'); const identity = DefaultIdentityClient.create({ discovery, diff --git a/plugins/playlist-common/CHANGELOG.md b/plugins/playlist-common/CHANGELOG.md index b6d6eb8990..5916ed33e8 100644 --- a/plugins/playlist-common/CHANGELOG.md +++ b/plugins/playlist-common/CHANGELOG.md @@ -1,5 +1,19 @@ # @backstage/plugin-playlist-common +## 0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.9 + +## 0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 0.1.10 ### Patch Changes diff --git a/plugins/playlist-common/package.json b/plugins/playlist-common/package.json index f31094c5a6..e08afb8392 100644 --- a/plugins/playlist-common/package.json +++ b/plugins/playlist-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-playlist-common", "description": "Common functionalities for the playlist plugin", - "version": "0.1.10", + "version": "0.1.11", "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 301f289b8c..16c0f02912 100644 --- a/plugins/playlist/CHANGELOG.md +++ b/plugins/playlist/CHANGELOG.md @@ -1,5 +1,43 @@ # @backstage/plugin-playlist +## 0.1.17 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 65498193e8: Updated Playlist read me with additional screenshots +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/theme@0.4.3 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-playlist-common@0.1.11 + +## 0.1.17-next.2 + +### Patch Changes + +- 65498193e8: Updated Playlist read me with additional screenshots +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-permission-react@0.4.16-next.1 + - @backstage/plugin-playlist-common@0.1.11-next.0 + ## 0.1.17-next.1 ### Patch Changes diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index 10a3c651ed..de53e9fafe 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-playlist", - "version": "0.1.17-next.1", + "version": "0.1.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -51,19 +51,19 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", + "@backstage/plugin-search-common": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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", "msw": "^1.0.0", "swr": "^2.0.0" diff --git a/plugins/playlist/src/components/CreatePlaylistButton/CreatePlaylistButton.test.tsx b/plugins/playlist/src/components/CreatePlaylistButton/CreatePlaylistButton.test.tsx index ef8ca57b69..c21283bcce 100644 --- a/plugins/playlist/src/components/CreatePlaylistButton/CreatePlaylistButton.test.tsx +++ b/plugins/playlist/src/components/CreatePlaylistButton/CreatePlaylistButton.test.tsx @@ -22,8 +22,7 @@ import { } from '@backstage/plugin-permission-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { Button } from '@material-ui/core'; -import { fireEvent, waitFor } from '@testing-library/react'; -import { act } from '@testing-library/react-hooks'; +import { fireEvent, waitFor, act } from '@testing-library/react'; import React from 'react'; import { SWRConfig } from 'swr'; import { PlaylistApi, playlistApiRef } from '../../api'; @@ -111,6 +110,8 @@ describe('<CreatePlaylistButton/>', () => { act(() => { fireEvent.click(rendered.getByRole('button')); + }); + act(() => { fireEvent.click(rendered.getByTestId('mock-playlist-edit-dialog')); }); @@ -129,6 +130,8 @@ describe('<CreatePlaylistButton/>', () => { act(() => { fireEvent.click(rendered.getByRole('button')); + }); + act(() => { fireEvent.click(rendered.getByTestId('mock-playlist-edit-dialog')); }); diff --git a/plugins/playlist/src/components/EntityPlaylistDialog/EntityPlaylistDialog.test.tsx b/plugins/playlist/src/components/EntityPlaylistDialog/EntityPlaylistDialog.test.tsx index 828485bc3d..68e00b6b96 100644 --- a/plugins/playlist/src/components/EntityPlaylistDialog/EntityPlaylistDialog.test.tsx +++ b/plugins/playlist/src/components/EntityPlaylistDialog/EntityPlaylistDialog.test.tsx @@ -24,8 +24,7 @@ import { permissionApiRef, } from '@backstage/plugin-permission-react'; import { Button } from '@material-ui/core'; -import { fireEvent, getByRole, waitFor } from '@testing-library/react'; -import { act } from '@testing-library/react-hooks'; +import { fireEvent, getByRole, waitFor, act } from '@testing-library/react'; import React from 'react'; import { SWRConfig } from 'swr'; import { PlaylistApi, playlistApiRef } from '../../api'; diff --git a/plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.test.tsx b/plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.test.tsx index b01b5acbf2..eaf00cbde1 100644 --- a/plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.test.tsx +++ b/plugins/playlist/src/components/PlaylistEditDialog/PlaylistEditDialog.test.tsx @@ -16,8 +16,7 @@ import { IdentityApi, identityApiRef } from '@backstage/core-plugin-api'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { fireEvent, getByRole, waitFor } from '@testing-library/react'; -import { act } from '@testing-library/react-hooks'; +import { fireEvent, getByRole, waitFor, act } from '@testing-library/react'; import { PlaylistApi, playlistApiRef } from '../../api'; import React from 'react'; @@ -79,7 +78,9 @@ describe('<PlaylistEditDialog/>', () => { }, }, ); + }); + act(() => { fireEvent.input( getByRole( rendered.getByTestId('edit-dialog-description-input'), @@ -91,17 +92,25 @@ describe('<PlaylistEditDialog/>', () => { }, }, ); + }); + act(() => { fireEvent.mouseDown( getByRole(rendered.getByTestId('edit-dialog-owner-select'), 'button'), ); + }); + act(() => { fireEvent.click(rendered.getByText('test-owner')); + }); + act(() => { fireEvent.click( getByRole(rendered.getByTestId('edit-dialog-public-option'), 'radio'), ); + }); + act(() => { fireEvent.click(rendered.getByTestId('edit-dialog-save-button')); }); diff --git a/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.test.tsx b/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.test.tsx index d1bdf1d46a..96ec5677e7 100644 --- a/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.test.tsx +++ b/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.test.tsx @@ -21,8 +21,7 @@ import { } from '@backstage/plugin-catalog-react'; import { SearchApi, searchApiRef } from '@backstage/plugin-search-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { fireEvent, getByText } from '@testing-library/react'; -import { act } from '@testing-library/react-hooks'; +import { fireEvent, getByText, act } from '@testing-library/react'; import React from 'react'; import { AddEntitiesDrawer } from './AddEntitiesDrawer'; diff --git a/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx b/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx index d5a52dc83c..529327776e 100644 --- a/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx +++ b/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx @@ -15,6 +15,7 @@ */ import { + CompoundEntityRef, Entity, getCompoundEntityRef, stringifyEntityRef, @@ -22,6 +23,7 @@ import { import { useApi, useRouteRef } from '@backstage/core-plugin-api'; import { CatalogEntityDocument } from '@backstage/plugin-catalog-common'; import { catalogApiRef, entityRouteRef } from '@backstage/plugin-catalog-react'; +import type { SearchDocument } from '@backstage/plugin-search-common'; import { SearchBar, SearchContextProvider, @@ -131,13 +133,13 @@ export const AddEntitiesDrawer = ({ }; const addEntity = useCallback( - entityResult => { + (entityResult: SearchDocument) => { // TODO(kuangp): this parsing of the location is not great. Ideally `CatalogEntityDocument` // contains the `metadata.name` field so we can derive the full ref and we only fall back to // parsing location if it's missing (ie. for older versions) const match = entityResult.location.match(entityLocationRegex); if (match?.groups) { - onAdd(stringifyEntityRef(match?.groups)); + onAdd(stringifyEntityRef(match?.groups as CompoundEntityRef)); } else { // eslint-disable-next-line no-console console.error( diff --git a/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.test.tsx b/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.test.tsx index 21658ef36e..ba6f94e945 100644 --- a/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.test.tsx +++ b/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.test.tsx @@ -23,8 +23,7 @@ import { } from '@backstage/plugin-permission-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { Button } from '@material-ui/core'; -import { fireEvent, waitFor } from '@testing-library/react'; -import { act } from '@testing-library/react-hooks'; +import { fireEvent, waitFor, act } from '@testing-library/react'; import React from 'react'; import { SWRConfig } from 'swr'; import { PlaylistApi, playlistApiRef } from '../../api'; diff --git a/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.tsx b/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.tsx index c74859ce20..72d50506b0 100644 --- a/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.tsx +++ b/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.tsx @@ -72,7 +72,7 @@ export const PlaylistEntitiesTable = ({ ); const removeEntity = useCallback( - async (_, entity: Entity | Entity[]) => { + async (_: unknown, entity: Entity | Entity[]) => { try { const entityArray = [entity].flat(); const entityNames = entityArray.map( diff --git a/plugins/playlist/src/components/PlaylistPage/PlaylistHeader.test.tsx b/plugins/playlist/src/components/PlaylistPage/PlaylistHeader.test.tsx index 4594a43a88..480ac038f2 100644 --- a/plugins/playlist/src/components/PlaylistPage/PlaylistHeader.test.tsx +++ b/plugins/playlist/src/components/PlaylistPage/PlaylistHeader.test.tsx @@ -27,8 +27,7 @@ import { import { permissions, Playlist } from '@backstage/plugin-playlist-common'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { Button } from '@material-ui/core'; -import { fireEvent, waitFor } from '@testing-library/react'; -import { act } from '@testing-library/react-hooks'; +import { fireEvent, waitFor, act } from '@testing-library/react'; import React from 'react'; import { SWRConfig } from 'swr'; import { PlaylistApi, playlistApiRef } from '../../api'; @@ -193,6 +192,8 @@ describe('PlaylistHeader', () => { act(() => { fireEvent.click(rendered.getByTestId('header-action-menu')); + }); + act(() => { fireEvent.click( rendered .getAllByTestId('header-action-item') @@ -225,11 +226,15 @@ describe('PlaylistHeader', () => { act(() => { fireEvent.click(rendered.getByTestId('header-action-menu')); + }); + act(() => { fireEvent.click( rendered .getAllByTestId('header-action-item') .find(e => e.innerHTML.includes('Delete Playlist'))!, ); + }); + act(() => { fireEvent.click(rendered.getByTestId('delete-playlist-dialog-button')); }); diff --git a/plugins/playlist/src/components/PlaylistPage/PlaylistPage.test.tsx b/plugins/playlist/src/components/PlaylistPage/PlaylistPage.test.tsx index 65d3d79be6..ef9b6d060b 100644 --- a/plugins/playlist/src/components/PlaylistPage/PlaylistPage.test.tsx +++ b/plugins/playlist/src/components/PlaylistPage/PlaylistPage.test.tsx @@ -21,8 +21,7 @@ import { permissionApiRef, } from '@backstage/plugin-permission-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { fireEvent, getByText, waitFor } from '@testing-library/react'; -import { act } from '@testing-library/react-hooks'; +import { fireEvent, getByText, waitFor, act } from '@testing-library/react'; import React from 'react'; import { SWRConfig } from 'swr'; @@ -110,8 +109,8 @@ describe('PlaylistPage', () => { act(() => { fireEvent.click(rendered.getByTestId('playlist-page-follow-button')); - testPlaylist.isFollowing = true; }); + testPlaylist.isFollowing = true; await waitFor(() => { expect(playlistApi.followPlaylist).toHaveBeenCalledWith('id1'); @@ -125,8 +124,8 @@ describe('PlaylistPage', () => { act(() => { fireEvent.click(rendered.getByTestId('playlist-page-follow-button')); - testPlaylist.isFollowing = false; }); + testPlaylist.isFollowing = false; await waitFor(() => { expect(playlistApi.unfollowPlaylist).toHaveBeenCalledWith('id1'); diff --git a/plugins/playlist/src/components/PlaylistSortPicker/PlaylistSortPicker.test.tsx b/plugins/playlist/src/components/PlaylistSortPicker/PlaylistSortPicker.test.tsx index 9317bfd4c1..6c86b7b34d 100644 --- a/plugins/playlist/src/components/PlaylistSortPicker/PlaylistSortPicker.test.tsx +++ b/plugins/playlist/src/components/PlaylistSortPicker/PlaylistSortPicker.test.tsx @@ -14,8 +14,13 @@ * limitations under the License. */ -import { fireEvent, getByRole, render, waitFor } from '@testing-library/react'; -import { act } from '@testing-library/react-hooks'; +import { + fireEvent, + getByRole, + render, + waitFor, + act, +} from '@testing-library/react'; import React from 'react'; import { MockPlaylistListProvider } from '../../testUtils'; diff --git a/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx b/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx index 26e162ebf7..ce0d49802b 100644 --- a/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx +++ b/plugins/playlist/src/hooks/PlaylistListProvider.test.tsx @@ -22,7 +22,7 @@ import { } from '@backstage/core-plugin-api'; import { Playlist } from '@backstage/plugin-playlist-common'; import { TestApiProvider } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook, waitFor } from '@testing-library/react'; import qs from 'qs'; import React, { PropsWithChildren } from 'react'; import { MemoryRouter } from 'react-router-dom'; @@ -114,23 +114,22 @@ describe('<PlaylistListProvider />', () => { }); it('resolves backend filters', async () => { - const { result, waitForValueToChange } = renderHook( - () => usePlaylistList(), - { - wrapper, - }, - ); - await waitForValueToChange(() => result.current.backendPlaylists); - expect(result.current.backendPlaylists.length).toBe(2); - expect(mockPlaylistApi.getAllPlaylists).toHaveBeenCalled(); + const { result } = renderHook(() => usePlaylistList(), { + wrapper, + }); + await waitFor(() => { + expect(result.current.backendPlaylists.length).toBe(2); + expect(mockPlaylistApi.getAllPlaylists).toHaveBeenCalled(); + }); }); it('resolves frontend filters', async () => { - const { result, waitFor } = renderHook(() => usePlaylistList(), { + const { result } = renderHook(() => usePlaylistList(), { wrapper, }); - await waitFor(() => !!result.current.playlists.length); - expect(result.current.backendPlaylists.length).toBe(2); + await waitFor(() => { + expect(result.current.backendPlaylists.length).toBe(2); + }); act(() => result.current.updateFilters({ @@ -152,21 +151,21 @@ describe('<PlaylistListProvider />', () => { const query = qs.stringify({ filters: { personal: 'all', owners: ['user:default/guest'] }, }); - const { result, waitFor } = renderHook(() => usePlaylistList(), { - wrapper, - initialProps: { - location: `/playlist?${query}`, - }, + const { result } = renderHook(() => usePlaylistList(), { + wrapper: ({ children }) => + wrapper({ location: `/playlist?${query}`, children }), }); - await waitFor(() => !!result.current.queryParameters); - expect(result.current.queryParameters).toEqual({ - personal: 'all', - owners: ['user:default/guest'], + + await waitFor(() => { + expect(result.current.queryParameters).toEqual({ + personal: 'all', + owners: ['user:default/guest'], + }); }); }); it('does not fetch when only frontend filters change', async () => { - const { result, waitFor } = renderHook(() => usePlaylistList(), { + const { result } = renderHook(() => usePlaylistList(), { wrapper, }); @@ -191,7 +190,7 @@ describe('<PlaylistListProvider />', () => { }); it('applies custom sorting', async () => { - const { result, waitFor } = renderHook(() => usePlaylistList(), { + const { result } = renderHook(() => usePlaylistList(), { wrapper, }); @@ -216,7 +215,7 @@ describe('<PlaylistListProvider />', () => { it('returns an error on playlistApi failure', async () => { mockPlaylistApi.getAllPlaylists = jest.fn().mockRejectedValue('error'); - const { result, waitFor } = renderHook(() => usePlaylistList(), { + const { result } = renderHook(() => usePlaylistList(), { wrapper, }); await waitFor(() => { diff --git a/plugins/proxy-backend/CHANGELOG.md b/plugins/proxy-backend/CHANGELOG.md index 22dae797a3..6137545f06 100644 --- a/plugins/proxy-backend/CHANGELOG.md +++ b/plugins/proxy-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-proxy-backend +## 0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## 0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.4.2-next.1 ### Patch Changes diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index 9b21073dc7..adbfe9fce9 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.2-next.1", + "version": "0.4.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/proxy-backend/src/service/router.config.test.ts b/plugins/proxy-backend/src/service/router.config.test.ts index fffdcb5142..8643ee67c0 100644 --- a/plugins/proxy-backend/src/service/router.config.test.ts +++ b/plugins/proxy-backend/src/service/router.config.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { getVoidLogger, SingleHostDiscovery } from '@backstage/backend-common'; +import { getVoidLogger, HostDiscovery } from '@backstage/backend-common'; import { ConfigSources, MutableConfigSource, @@ -87,7 +87,7 @@ describe('createRouter reloadable configuration', () => { ]), ); - const discovery = SingleHostDiscovery.fromConfig(config); + const discovery = HostDiscovery.fromConfig(config); const router = await createRouter({ config, logger, diff --git a/plugins/proxy-backend/src/service/router.test.ts b/plugins/proxy-backend/src/service/router.test.ts index 23b6e17ecc..9149f36015 100644 --- a/plugins/proxy-backend/src/service/router.test.ts +++ b/plugins/proxy-backend/src/service/router.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { getVoidLogger, SingleHostDiscovery } from '@backstage/backend-common'; +import { getVoidLogger, HostDiscovery } from '@backstage/backend-common'; import { mockServices } from '@backstage/backend-test-utils'; import { ConfigReader } from '@backstage/config'; import { Request, Response } from 'express'; @@ -56,7 +56,7 @@ describe('createRouter', () => { }, }, }); - const discovery = SingleHostDiscovery.fromConfig(config); + const discovery = HostDiscovery.fromConfig(config); beforeEach(() => { mockCreateProxyMiddleware.mockClear(); @@ -150,7 +150,7 @@ describe('createRouter', () => { }, }, }); - const discovery = SingleHostDiscovery.fromConfig(config); + const discovery = HostDiscovery.fromConfig(config); await expect( createRouter({ config, @@ -185,7 +185,7 @@ describe('createRouter', () => { }, }, }); - const discovery = SingleHostDiscovery.fromConfig(config); + const discovery = HostDiscovery.fromConfig(config); const router = await createRouter({ config, logger, diff --git a/plugins/proxy-backend/src/service/standaloneServer.ts b/plugins/proxy-backend/src/service/standaloneServer.ts index 3a8401986c..44a1e34090 100644 --- a/plugins/proxy-backend/src/service/standaloneServer.ts +++ b/plugins/proxy-backend/src/service/standaloneServer.ts @@ -17,7 +17,7 @@ import { createServiceBuilder, loadBackendConfig, - SingleHostDiscovery, + HostDiscovery, } from '@backstage/backend-common'; import { Server } from 'http'; import { Logger } from 'winston'; @@ -37,7 +37,7 @@ export async function startStandaloneServer( logger.debug('Creating application...'); const config = await loadBackendConfig({ logger, argv: process.argv }); - const discovery = SingleHostDiscovery.fromConfig(config); + const discovery = HostDiscovery.fromConfig(config); const router = await createRouter({ config, logger, diff --git a/plugins/puppetdb/CHANGELOG.md b/plugins/puppetdb/CHANGELOG.md index 5d9dc0be04..2d184e7a48 100644 --- a/plugins/puppetdb/CHANGELOG.md +++ b/plugins/puppetdb/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-puppetdb +## 0.1.8 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.1.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.1.8-next.1 ### Patch Changes diff --git a/plugins/puppetdb/package.json b/plugins/puppetdb/package.json index ad23b77a8f..89cd83fcde 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.8-next.1", + "version": "0.1.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -57,8 +57,8 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.1" }, diff --git a/plugins/rollbar-backend/CHANGELOG.md b/plugins/rollbar-backend/CHANGELOG.md index 6d4b6b309e..dd2df54811 100644 --- a/plugins/rollbar-backend/CHANGELOG.md +++ b/plugins/rollbar-backend/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-rollbar-backend +## 0.1.51 + +### Patch Changes + +- 407f4284be: ensure rollbar token is hidden +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + +## 0.1.51-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.1.50-next.1 ### Patch Changes diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 019f851d04..e5dbd3a997 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.50-next.1", + "version": "0.1.51", "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 69c38eead1..46d27e8bad 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-rollbar +## 0.4.25 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 0.4.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + ## 0.4.25-next.1 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 5a5159ceb6..d82402c03e 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.25-next.1", + "version": "0.4.25", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -57,10 +57,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md index 366698d2e6..2b931dd7da 100644 --- a/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-confluence-to-markdown/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-scaffolder-backend-module-confluence-to-markdown +## 0.2.7 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.2.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + ## 0.2.6-next.1 ### 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 bb996d7da8..9d506d824b 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.6-next.1", + "version": "0.2.7", "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 8a4dc42f44..9c68b53d40 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-cookiecutter/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-scaffolder-backend-module-cookiecutter +## 0.2.30 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.2.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + ## 0.2.29-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 908f907f13..fed7cd4596 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.29-next.1", + "version": "0.2.30", "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 3cd1812ca7..2582ed3227 100644 --- a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-scaffolder-backend-module-gitlab +## 0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + +## 0.2.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.2.8-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index 89d755f1dd..99c84ed4b9 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.8-next.1", + "version": "0.2.9", "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 c51d36eb64..70af7932b8 100644 --- a/plugins/scaffolder-backend-module-rails/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-rails/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-scaffolder-backend-module-rails +## 0.4.23 + +### Patch Changes + +- de42eebaaf: Bumped dev dependencies `@types/node` and `mock-fs`. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.4.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + ## 0.4.22-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index c58fb6a035..2bc91478e4 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.22-next.1", + "version": "0.4.23", "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 e07feaa885..9e0bd8734b 100644 --- a/plugins/scaffolder-backend-module-sentry/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-sentry/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-scaffolder-backend-module-sentry +## 0.1.14 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + +## 0.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.1.13-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-sentry/package.json b/plugins/scaffolder-backend-module-sentry/package.json index 366f7a9126..ce1b8247f8 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.13-next.1", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md index a24ec57bb3..fa7774558a 100644 --- a/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-yeoman/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-scaffolder-backend-module-yeoman +## 0.2.27 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + +## 0.2.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + ## 0.2.26-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-yeoman/package.json b/plugins/scaffolder-backend-module-yeoman/package.json index cd4350f681..36b8c4e76b 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.26-next.1", + "version": "0.2.27", "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 50fda07ce7..f2258517a6 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,79 @@ # @backstage/plugin-scaffolder-backend +## 1.18.0 + +### Minor Changes + +- dea0aafda7: Updated `publish:gitlab` action properties to support additional Gitlab project settings: + + - general project settings provided by gitlab project create API (new `settings` property) + - branch level settings to create additional branches and make them protected (new `branches` property) + - project level environment variables settings (new `projectVariables` property) + + Marked existed properties `repoVisibility` and `topics` as deprecated, as they are covered by `settings` property. + +- f41099bb31: Display meaningful error to the output if Gitlab namespace not found inside `publish:gitlab`. + +### Patch Changes + +- 7dd82cc07e: Add examples for `github:issues:label` scaffolder action & improve related tests +- 733ddf7130: Add examples for `publish:Azure` scaffolder action. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-backend@1.14.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/plugin-scaffolder-node@0.2.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-scaffolder-common@1.4.2 + +## 1.18.0-next.2 + +### Minor Changes + +- dea0aafda7: Updated `publish:gitlab` action properties to support additional Gitlab project settings: + + - general project settings provided by gitlab project create API (new `settings` property) + - branch level settings to create additional branches and make them protected (new `branches` property) + - project level environment variables settings (new `projectVariables` property) + + Marked existed properties `repoVisibility` and `topics` as deprecated, as they are covered by `settings` property. + +### Patch Changes + +- 7dd82cc07e: Add examples for `github:issues:label` scaffolder action & improve related tests +- 733ddf7130: Add examples for `publish:Azure` scaffolder action. +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/plugin-catalog-backend@1.14.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.1.3-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/plugin-scaffolder-node@0.2.6-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-scaffolder-common@1.4.2-next.0 + ## 1.18.0-next.1 ### Minor Changes diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 17e13131cf..ba7576b1bb 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -679,6 +679,36 @@ export function createPublishGitlabAction(options: { gitAuthorEmail?: string | undefined; setUserAsOwner?: boolean | undefined; topics?: string[] | undefined; + settings?: + | { + path?: string | undefined; + auto_devops_enabled?: boolean | undefined; + ci_config_path?: string | undefined; + description?: string | undefined; + topics?: string[] | undefined; + visibility?: 'internal' | 'private' | 'public' | undefined; + } + | undefined; + branches?: + | { + name: string; + protect?: boolean | undefined; + create?: boolean | undefined; + ref?: string | undefined; + }[] + | undefined; + projectVariables?: + | { + key: string; + value: string; + description?: string | undefined; + variable_type?: string | undefined; + protected?: boolean | undefined; + masked?: boolean | undefined; + raw?: boolean | undefined; + environment_scope?: string | undefined; + }[] + | undefined; }, JsonObject >; diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index cab9abae96..20c56e9a8d 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.18.0-next.1", + "version": "1.18.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -107,13 +107,11 @@ "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", "@types/libsodium-wrappers": "^0.7.10", - "@types/mock-fs": "^4.13.0", "@types/nunjucks": "^3.1.4", "@types/supertest": "^2.0.8", "@types/zen-observable": "^0.8.0", "esbuild": "^0.19.0", "jest-when": "^3.1.0", - "mock-fs": "^5.2.0", "msw": "^1.0.0", "supertest": "^6.1.3", "wait-for-expect": "^3.0.2", diff --git a/plugins/scaffolder-backend/src/lib/files/deserializeDirectoryContents.test.ts b/plugins/scaffolder-backend/src/lib/files/deserializeDirectoryContents.test.ts index c272e04205..e374e0d713 100644 --- a/plugins/scaffolder-backend/src/lib/files/deserializeDirectoryContents.test.ts +++ b/plugins/scaffolder-backend/src/lib/files/deserializeDirectoryContents.test.ts @@ -14,29 +14,25 @@ * limitations under the License. */ -import mockFs from 'mock-fs'; +import { createMockDirectory } from '@backstage/backend-test-utils'; import { deserializeDirectoryContents } from './deserializeDirectoryContents'; import { serializeDirectoryContents } from './serializeDirectoryContents'; describe('deserializeDirectoryContents', () => { - beforeEach(() => { - mockFs({ - root: {}, - }); - }); + const mockDir = createMockDirectory(); - afterEach(() => { - mockFs.restore(); + beforeEach(() => { + mockDir.clear(); }); it('deserializes contents into a directory', async () => { - await deserializeDirectoryContents('root', [ + await deserializeDirectoryContents(mockDir.path, [ { path: 'a.txt', content: Buffer.from('a', 'utf8'), }, ]); - await expect(serializeDirectoryContents('root')).resolves.toEqual([ + await expect(serializeDirectoryContents(mockDir.path)).resolves.toEqual([ { path: 'a.txt', content: Buffer.from('a', 'utf8'), @@ -47,7 +43,7 @@ describe('deserializeDirectoryContents', () => { }); it('deserializes contents into a deep directory structure', async () => { - await deserializeDirectoryContents('root', [ + await deserializeDirectoryContents(mockDir.path, [ { path: 'a.txt', content: Buffer.from('a', 'utf8'), @@ -61,7 +57,7 @@ describe('deserializeDirectoryContents', () => { content: Buffer.from('c', 'utf8'), }, ]); - await expect(serializeDirectoryContents('root')).resolves.toEqual([ + await expect(serializeDirectoryContents(mockDir.path)).resolves.toEqual([ { path: 'a.txt', content: Buffer.from('a', 'utf8'), diff --git a/plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.test.ts b/plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.test.ts index a22ea85301..afc1b755ff 100644 --- a/plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.test.ts +++ b/plugins/scaffolder-backend/src/lib/files/serializeDirectoryContents.test.ts @@ -14,13 +14,11 @@ * limitations under the License. */ +import { createMockDirectory } from '@backstage/backend-test-utils'; import { serializeDirectoryContents } from './serializeDirectoryContents'; -import mockFs from 'mock-fs'; describe('serializeDirectoryContents', () => { - afterEach(() => { - mockFs.restore(); - }); + const mockDir = createMockDirectory(); it('should list files in this directory', async () => { await expect(serializeDirectoryContents(__dirname)).resolves.toEqual( @@ -54,25 +52,23 @@ describe('serializeDirectoryContents', () => { }); it('should list files in a mock directory', async () => { - mockFs({ - root: { - 'a.txt': 'a', - b: { - 'b1.txt': 'b1', - 'b2.txt': 'b2', - }, - c: { - c1: { - 'c11.txt': 'c11', - c11: { - 'c111.txt': 'c111', - }, + mockDir.setContent({ + 'a.txt': 'a', + b: { + 'b1.txt': 'b1', + 'b2.txt': 'b2', + }, + c: { + c1: { + 'c11.txt': 'c11', + c11: { + 'c111.txt': 'c111', }, }, }, }); - await expect(serializeDirectoryContents('root')).resolves.toEqual([ + await expect(serializeDirectoryContents(mockDir.path)).resolves.toEqual([ { path: 'a.txt', executable: false, @@ -107,16 +103,12 @@ describe('serializeDirectoryContents', () => { }); it('should ignore symlinked files', async () => { - mockFs({ - root: { - 'a.txt': 'some text', - sym: mockFs.symlink({ - path: './a.txt', - }), - }, + mockDir.setContent({ + 'a.txt': 'some text', + sym: ctx => ctx.symlink('./a.txt'), }); - await expect(serializeDirectoryContents('root')).resolves.toEqual([ + await expect(serializeDirectoryContents(mockDir.path)).resolves.toEqual([ { path: 'a.txt', executable: false, @@ -127,18 +119,14 @@ describe('serializeDirectoryContents', () => { }); it('should pick up broken symlinks', async () => { - mockFs({ - root: { - 'b.txt': mockFs.symlink({ - path: './a.txt', - }), - }, + mockDir.setContent({ + 'b.txt': ctx => ctx.symlink('./a.txt'), }); - await expect(serializeDirectoryContents('root')).resolves.toEqual([ + await expect(serializeDirectoryContents(mockDir.path)).resolves.toEqual([ { path: 'b.txt', - executable: false, + executable: true, symlink: true, content: Buffer.from('./a.txt', 'utf8'), }, @@ -146,19 +134,15 @@ describe('serializeDirectoryContents', () => { }); it('should ignore symlinked folder files', async () => { - mockFs({ - root: { - 'a.txt': 'some text', - linkme: { - 'b.txt': 'lols', - }, - sym: mockFs.symlink({ - path: './linkme', - }), + mockDir.setContent({ + 'a.txt': 'some text', + linkme: { + 'b.txt': 'lols', }, + sym: ctx => ctx.symlink('./linkme'), }); - await expect(serializeDirectoryContents('root')).resolves.toEqual([ + await expect(serializeDirectoryContents(mockDir.path)).resolves.toEqual([ { path: 'a.txt', executable: false, @@ -175,16 +159,14 @@ describe('serializeDirectoryContents', () => { }); it('should ignore gitignored files', async () => { - mockFs({ - root: { - '.gitignore': '*.txt', - 'a.txt': 'a', - 'a.log': 'a', - }, + mockDir.setContent({ + '.gitignore': '*.txt', + 'a.txt': 'a', + 'a.log': 'a', }); await expect( - serializeDirectoryContents('root', { + serializeDirectoryContents(mockDir.path, { gitignore: true, }), ).resolves.toEqual([ @@ -204,26 +186,24 @@ describe('serializeDirectoryContents', () => { }); it('should use custom glob patterns', async () => { - mockFs({ - root: { - '.a': 'a', - 'a.log': 'a', - 'a.txt': 'a', - b: { - '.b': 'b', - 'b.log': 'b', - 'b.txt': 'b', - }, - c: { - '.c': 'c', - 'c.log': 'c', - 'c.txt': 'c', - }, + mockDir.setContent({ + '.a': 'a', + 'a.log': 'a', + 'a.txt': 'a', + b: { + '.b': 'b', + 'b.log': 'b', + 'b.txt': 'b', + }, + c: { + '.c': 'c', + 'c.log': 'c', + 'c.txt': 'c', }, }); await expect( - serializeDirectoryContents('root', { + serializeDirectoryContents(mockDir.path, { gitignore: true, globPatterns: ['**/*.txt', '*/.?', '*/*.log', '!c/**/.*', '!b/*.log'], }).then(files => files.sort((a, b) => a.path.localeCompare(b.path))), diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.examples.test.ts index a7f5a1804a..901f3e5011 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.examples.test.ts @@ -15,44 +15,41 @@ */ import { getVoidLogger } from '@backstage/backend-common'; -import mockFs from 'mock-fs'; -import os from 'os'; import { Writable } from 'stream'; import { createDebugLogAction } from './log'; import { join } from 'path'; import yaml from 'yaml'; import { examples } from './log.examples'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('debug:log examples', () => { const logStream = { write: jest.fn(), } as jest.Mocked<Partial<Writable>> as jest.Mocked<Writable>; - const mockTmpDir = os.tmpdir(); + const mockDir = createMockDirectory(); + const workspacePath = mockDir.resolve('workspace'); + const mockContext = { input: {}, baseUrl: 'somebase', - workspacePath: mockTmpDir, + workspacePath, logger: getVoidLogger(), logStream, output: jest.fn(), - createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), + createTemporaryDirectory: jest.fn(), }; const action = createDebugLogAction(); beforeEach(() => { - mockFs({ - [`${mockContext.workspacePath}/README.md`]: '', - [`${mockContext.workspacePath}/a-directory/index.md`]: '', + mockDir.setContent({ + [`${workspacePath}/README.md`]: '', + [`${workspacePath}/a-directory/index.md`]: '', }); jest.resetAllMocks(); }); - afterEach(() => { - mockFs.restore(); - }); - it('should log message', async () => { const context = { ...mockContext, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.test.ts index 6b7ad8816f..d6fc5174b3 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/log.test.ts @@ -15,43 +15,40 @@ */ import { getVoidLogger } from '@backstage/backend-common'; -import mockFs from 'mock-fs'; -import os from 'os'; import { Writable } from 'stream'; import { createDebugLogAction } from './log'; import { join } from 'path'; import yaml from 'yaml'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('debug:log', () => { const logStream = { write: jest.fn(), } as jest.Mocked<Partial<Writable>> as jest.Mocked<Writable>; - const mockTmpDir = os.tmpdir(); + const mockDir = createMockDirectory(); + const workspacePath = mockDir.resolve('workspace'); + const mockContext = { input: {}, baseUrl: 'somebase', - workspacePath: mockTmpDir, + workspacePath, logger: getVoidLogger(), logStream, output: jest.fn(), - createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), + createTemporaryDirectory: jest.fn(), }; const action = createDebugLogAction(); beforeEach(() => { - mockFs({ + mockDir.setContent({ [`${mockContext.workspacePath}/README.md`]: '', [`${mockContext.workspacePath}/a-directory/index.md`]: '', }); jest.resetAllMocks(); }); - afterEach(() => { - mockFs.restore(); - }); - it('should do nothing', async () => { await action.handler(mockContext); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.examples.test.ts index 595ae7c3b6..9b755d86dd 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.examples.test.ts @@ -15,12 +15,11 @@ */ import { getVoidLogger } from '@backstage/backend-common'; -import mockFs from 'mock-fs'; import { createWaitAction } from './wait'; import { Writable } from 'stream'; -import os from 'os'; import { examples } from './wait.examples'; import yaml from 'yaml'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('debug:wait examples', () => { const action = createWaitAction(); @@ -29,25 +28,23 @@ describe('debug:wait examples', () => { write: jest.fn(), } as jest.Mocked<Partial<Writable>> as jest.Mocked<Writable>; - const mockTmpDir = os.tmpdir(); + const mockDir = createMockDirectory(); + const workspacePath = mockDir.resolve('workspace'); + const mockContext = { input: {}, baseUrl: 'somebase', - workspacePath: mockTmpDir, + workspacePath, logger: getVoidLogger(), logStream, output: jest.fn(), - createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), + createTemporaryDirectory: jest.fn(), }; beforeEach(() => { jest.resetAllMocks(); }); - afterEach(() => { - mockFs.restore(); - }); - it('should wait for specified period of seconds', async () => { const context = { ...mockContext, @@ -56,6 +53,7 @@ describe('debug:wait examples', () => { const start = new Date().getTime(); await action.handler(context); const end = new Date().getTime(); - expect(end - start).toBeGreaterThanOrEqual(50); + expect(end - start).toBeGreaterThanOrEqual(45); // should rarely by markedly less + expect(end - start).toBeLessThanOrEqual(500); // can get delayed a bit in CI }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.test.ts index 0d4cdaba4b..6f80604a6d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/debug/wait.test.ts @@ -15,10 +15,9 @@ */ import { getVoidLogger } from '@backstage/backend-common'; -import mockFs from 'mock-fs'; import { createWaitAction } from './wait'; import { Writable } from 'stream'; -import os from 'os'; +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('debug:wait', () => { const action = createWaitAction(); @@ -27,25 +26,23 @@ describe('debug:wait', () => { write: jest.fn(), } as jest.Mocked<Partial<Writable>> as jest.Mocked<Writable>; - const mockTmpDir = os.tmpdir(); + const mockDir = createMockDirectory(); + const workspacePath = mockDir.resolve('workspace'); + const mockContext = { input: {}, baseUrl: 'somebase', - workspacePath: mockTmpDir, + workspacePath, logger: getVoidLogger(), logStream, output: jest.fn(), - createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), + createTemporaryDirectory: jest.fn(), }; beforeEach(() => { jest.resetAllMocks(); }); - afterEach(() => { - mockFs.restore(); - }); - it('should wait for specified period of time', async () => { const context = { ...mockContext, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.examples.test.ts index 43bed5a048..a1c8381178 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.examples.test.ts @@ -14,10 +14,8 @@ * limitations under the License. */ -import os from 'os'; import { join as joinPath, sep as pathSep } from 'path'; import fs from 'fs-extra'; -import mockFs from 'mock-fs'; import { getVoidLogger, resolvePackagePath, @@ -33,6 +31,7 @@ import { } from '@backstage/plugin-scaffolder-node'; import { examples } from './template.examples'; import yaml from 'yaml'; +import { createMockDirectory } from '@backstage/backend-test-utils'; jest.mock('@backstage/plugin-scaffolder-node', () => ({ ...jest.requireActual('@backstage/plugin-scaffolder-node'), @@ -45,16 +44,6 @@ type FetchTemplateInput = ReturnType< ? U : never; -const realFiles = Object.fromEntries( - [ - resolvePackagePath( - '@backstage/plugin-scaffolder-backend', - 'assets', - 'nunjucks.js.txt', - ), - ].map(k => [k, mockFs.load(k)]), -); - const aBinaryFile = fs.readFileSync( resolvePackagePath( '@backstage/plugin-scaffolder-backend', @@ -69,14 +58,8 @@ const mockFetchContents = fetchContents as jest.MockedFunction< describe('fetch:template examples', () => { let action: TemplateAction<any>; - const workspacePath = os.tmpdir(); - const createTemporaryDirectory: jest.MockedFunction< - ActionContext<FetchTemplateInput>['createTemporaryDirectory'] - > = jest.fn(() => - Promise.resolve( - joinPath(workspacePath, `${createTemporaryDirectory.mock.calls.length}`), - ), - ); + const mockDir = createMockDirectory(); + const workspacePath = mockDir.resolve('workspace'); const logger = getVoidLogger(); @@ -90,24 +73,20 @@ describe('fetch:template examples', () => { logStream: new PassThrough(), logger, workspacePath, - createTemporaryDirectory, + + async createTemporaryDirectory() { + return fs.mkdtemp(mockDir.resolve('tmp-')); + }, }); beforeEach(() => { - mockFs({ - ...realFiles, - }); - + mockDir.clear(); action = createFetchTemplateAction({ reader: Symbol('UrlReader') as unknown as UrlReader, integrations: Symbol('Integrations') as unknown as ScmIntegrations, }); }); - afterEach(() => { - mockFs.restore(); - }); - describe('handler', () => { describe('with valid input', () => { let context: ActionContext<FetchTemplateInput>; @@ -116,13 +95,13 @@ describe('fetch:template examples', () => { context = mockContext(yaml.parse(examples[0].example).steps[0].input); mockFetchContents.mockImplementation(({ outputPath }) => { - mockFs({ - ...realFiles, + mockDir.setContent({ [outputPath]: { - 'an-executable.sh': mockFs.file({ - content: '#!/usr/bin/env bash', - mode: parseInt('100755', 8), - }), + 'an-executable.sh': ctx => + fs.writeFileSync(ctx.path, '#!/usr/bin/env bash', { + encoding: 'utf8', + mode: parseInt('100755', 8), + }), 'empty-dir-${{ values.count }}': {}, 'static.txt': 'static content', '${{ values.name }}.txt': 'static content', @@ -132,12 +111,8 @@ describe('fetch:template examples', () => { }, '.${{ values.name }}': '${{ values.itemList | dump }}', 'a-binary-file.png': aBinaryFile, - symlink: mockFs.symlink({ - path: 'a-binary-file.png', - }), - brokenSymlink: mockFs.symlink({ - path: './not-a-real-file.txt', - }), + symlink: ctx => ctx.symlink('a-binary-file.png'), + brokenSymlink: ctx => ctx.symlink('./not-a-real-file.txt'), }, }); @@ -212,7 +187,11 @@ describe('fetch:template examples', () => { await expect( fs.realpath(`${workspacePath}/target/symlink`), - ).resolves.toBe(joinPath(workspacePath, 'target', 'a-binary-file.png')); + ).resolves.toBe( + fs.realpathSync( + joinPath(workspacePath, 'target', 'a-binary-file.png'), + ), + ); }); it('copies broken symlinks as-is without processing them', async () => { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts index 95f8c7b954..d396a00c26 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts @@ -19,10 +19,8 @@ jest.mock('@backstage/plugin-scaffolder-node', () => { return { ...actual, fetchContents: jest.fn() }; }); -import os from 'os'; import { join as joinPath, sep as pathSep } from 'path'; import fs from 'fs-extra'; -import mockFs from 'mock-fs'; import { getVoidLogger, resolvePackagePath, @@ -36,6 +34,7 @@ import { ActionContext, TemplateAction, } from '@backstage/plugin-scaffolder-node'; +import { createMockDirectory } from '@backstage/backend-test-utils'; type FetchTemplateInput = ReturnType< typeof createFetchTemplateAction @@ -43,16 +42,6 @@ type FetchTemplateInput = ReturnType< ? U : never; -const realFiles = Object.fromEntries( - [ - resolvePackagePath( - '@backstage/plugin-scaffolder-backend', - 'assets', - 'nunjucks.js.txt', - ), - ].map(k => [k, mockFs.load(k)]), -); - const aBinaryFile = fs.readFileSync( resolvePackagePath( '@backstage/plugin-scaffolder-backend', @@ -67,14 +56,8 @@ const mockFetchContents = fetchContents as jest.MockedFunction< describe('fetch:template', () => { let action: TemplateAction<any>; - const workspacePath = os.tmpdir(); - const createTemporaryDirectory: jest.MockedFunction< - ActionContext<FetchTemplateInput>['createTemporaryDirectory'] - > = jest.fn(() => - Promise.resolve( - joinPath(workspacePath, `${createTemporaryDirectory.mock.calls.length}`), - ), - ); + const mockDir = createMockDirectory(); + const workspacePath = mockDir.resolve('workspace'); const logger = getVoidLogger(); @@ -95,24 +78,21 @@ describe('fetch:template', () => { logStream: new PassThrough(), logger, workspacePath, - createTemporaryDirectory, + async createTemporaryDirectory() { + return fs.mkdtemp(mockDir.resolve('tmp-')); + }, }); beforeEach(() => { - mockFs({ - ...realFiles, + mockDir.setContent({ + workspace: {}, }); - action = createFetchTemplateAction({ reader: Symbol('UrlReader') as unknown as UrlReader, integrations: Symbol('Integrations') as unknown as ScmIntegrations, }); }); - afterEach(() => { - mockFs.restore(); - }); - it(`returns a TemplateAction with the id 'fetch:template'`, () => { expect(action.id).toEqual('fetch:template'); }); @@ -190,8 +170,7 @@ describe('fetch:template', () => { }); mockFetchContents.mockImplementation(({ outputPath }) => { - mockFs({ - ...realFiles, + mockDir.setContent({ [outputPath]: { '{% if values.showDummyFile %}dummy-file.txt{% else %}{% endif %}': 'dummy file', @@ -282,13 +261,8 @@ describe('fetch:template', () => { }); mockFetchContents.mockImplementation(({ outputPath }) => { - mockFs({ - ...realFiles, + mockDir.setContent({ [outputPath]: { - 'an-executable.sh': mockFs.file({ - content: '#!/usr/bin/env bash', - mode: parseInt('100755', 8), - }), 'empty-dir-${{ values.count }}': {}, 'static.txt': 'static content', '${{ values.name }}.txt': 'static content', @@ -298,12 +272,13 @@ describe('fetch:template', () => { }, '.${{ values.name }}': '${{ values.itemList | dump }}', 'a-binary-file.png': aBinaryFile, - symlink: mockFs.symlink({ - path: 'a-binary-file.png', - }), - brokenSymlink: mockFs.symlink({ - path: './not-a-real-file.txt', - }), + 'an-executable.sh': ctx => + fs.writeFileSync(ctx.path, '#!/usr/bin/env bash', { + encoding: 'utf-8', + mode: parseInt('100755', 8), + }), + symlink: ctx => ctx.symlink('a-binary-file.png'), + brokenSymlink: ctx => ctx.symlink('./not-a-real-file.txt'), }, }); @@ -378,7 +353,11 @@ describe('fetch:template', () => { await expect( fs.realpath(`${workspacePath}/target/symlink`), - ).resolves.toBe(joinPath(workspacePath, 'target', 'a-binary-file.png')); + ).resolves.toBe( + fs.realpathSync( + joinPath(workspacePath, 'target', 'a-binary-file.png'), + ), + ); }); it('copies broken symlinks as-is without processing them', async () => { @@ -408,8 +387,7 @@ describe('fetch:template', () => { }); mockFetchContents.mockImplementation(({ outputPath }) => { - mockFs({ - ...realFiles, + mockDir.setContent({ [outputPath]: { processed: { 'templated-content-${{ values.name }}.txt': '${{ values.count }}', @@ -458,8 +436,7 @@ describe('fetch:template', () => { }); mockFetchContents.mockImplementation(({ outputPath }) => { - mockFs({ - ...realFiles, + mockDir.setContent({ [outputPath]: { processed: { 'templated-content-${{ values.name }}.txt': '${{ values.count }}', @@ -509,8 +486,7 @@ describe('fetch:template', () => { }); mockFetchContents.mockImplementation(({ outputPath }) => { - mockFs({ - ...realFiles, + mockDir.setContent({ [outputPath]: { '{{ cookiecutter.name }}.txt': 'static content', subdir: { @@ -564,8 +540,7 @@ describe('fetch:template', () => { }); mockFetchContents.mockImplementation(({ outputPath }) => { - mockFs({ - ...realFiles, + mockDir.setContent({ [outputPath]: { 'empty-dir-${{ values.count }}': {}, 'static.txt': 'static content', @@ -646,8 +621,7 @@ describe('fetch:template', () => { }); mockFetchContents.mockImplementation(({ outputPath }) => { - mockFs({ - ...realFiles, + mockDir.setContent({ [outputPath]: { '${{ values.name }}.njk': '${{ values.name }}: ${{ values.count }}', '${{ values.name }}.txt.jinja2': @@ -687,8 +661,7 @@ describe('fetch:template', () => { }); mockFetchContents.mockImplementation(({ outputPath }) => { - mockFs({ - ...realFiles, + mockDir.setContent({ [joinPath(workspacePath, 'target')]: { 'static-content.txt': 'static-content', }, @@ -703,10 +676,6 @@ describe('fetch:template', () => { await action.handler(context); }); - afterEach(() => { - mockFs.restore(); - }); - it('overwrites existing file', async () => { await expect( fs.readFile(`${workspacePath}/target/static-content.txt`, 'utf-8'), @@ -728,8 +697,7 @@ describe('fetch:template', () => { }); mockFetchContents.mockImplementation(({ outputPath }) => { - mockFs({ - ...realFiles, + mockDir.setContent({ [joinPath(workspacePath, 'target')]: { 'static-content.txt': 'static-content', }, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.test.ts index 10994e3824..023f049ebc 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.examples.test.ts @@ -18,18 +18,17 @@ import { createFilesystemDeleteAction } from './delete'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; import { resolve as resolvePath } from 'path'; -import * as os from 'os'; -import mockFs from 'mock-fs'; import fs from 'fs-extra'; import yaml from 'yaml'; import { examples } from './delete.examples'; - -const root = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir'; -const workspacePath = resolvePath(root, 'my-workspace'); +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('fs:delete examples', () => { const action = createFilesystemDeleteAction(); + const mockDir = createMockDirectory(); + const workspacePath = resolvePath(mockDir.path, 'workspace'); + const files: string[] = yaml.parse(examples[0].example).steps[0].input.files; const mockContext = { @@ -46,7 +45,7 @@ describe('fs:delete examples', () => { beforeEach(() => { jest.restoreAllMocks(); - mockFs({ + mockDir.setContent({ [workspacePath]: { [files[0]]: 'hello', [files[1]]: 'world', @@ -57,10 +56,6 @@ describe('fs:delete examples', () => { }); }); - afterEach(() => { - mockFs.restore(); - }); - it('should call fs.rm with the correct values', async () => { files.forEach(file => { const filePath = resolvePath(workspacePath, file); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts index 713de5b0ad..2a4f45b862 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts @@ -14,20 +14,19 @@ * limitations under the License. */ -import * as os from 'os'; -import mockFs from 'mock-fs'; import { resolve as resolvePath } from 'path'; import { createFilesystemDeleteAction } from './delete'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; import fs from 'fs-extra'; - -const root = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir'; -const workspacePath = resolvePath(root, 'my-workspace'); +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('fs:delete', () => { const action = createFilesystemDeleteAction(); + const mockDir = createMockDirectory(); + const workspacePath = resolvePath(mockDir.path, 'workspace'); + const mockContext = { input: { files: ['unit-test-a.js', 'unit-test-b.js'], @@ -42,7 +41,7 @@ describe('fs:delete', () => { beforeEach(() => { jest.restoreAllMocks(); - mockFs({ + mockDir.setContent({ [workspacePath]: { 'unit-test-a.js': 'hello', 'unit-test-b.js': 'world', @@ -53,10 +52,6 @@ describe('fs:delete', () => { }); }); - afterEach(() => { - mockFs.restore(); - }); - it('should throw an error when files is not an array', async () => { await expect( action.handler({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.test.ts index 5139469959..cbb0fa0d0b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.examples.test.ts @@ -14,8 +14,6 @@ * limitations under the License. */ -import * as os from 'os'; -import mockFs from 'mock-fs'; import { resolve as resolvePath } from 'path'; import { createFilesystemRenameAction } from './rename'; import { getVoidLogger } from '@backstage/backend-common'; @@ -23,15 +21,16 @@ import { PassThrough } from 'stream'; import fs from 'fs-extra'; import yaml from 'yaml'; import { examples } from './rename.examples'; - -const root = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir'; -const workspacePath = resolvePath(root, 'my-workspace'); +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('fs:rename examples', () => { const action = createFilesystemRenameAction(); const files: { from: string; to: string }[] = yaml.parse(examples[0].example) .steps[0].input.files; + const mockDir = createMockDirectory(); + const workspacePath = resolvePath(mockDir.path, 'workspace'); + const mockContext = { input: { files: files, @@ -46,7 +45,7 @@ describe('fs:rename examples', () => { beforeEach(() => { jest.restoreAllMocks(); - mockFs({ + mockDir.setContent({ [workspacePath]: { [files[0].from]: 'hello', [files[1].from]: 'world', @@ -59,10 +58,6 @@ describe('fs:rename examples', () => { }); }); - afterEach(() => { - mockFs.restore(); - }); - it('should call fs.move with the correct values', async () => { mockContext.input.files.forEach(file => { const filePath = resolvePath(workspacePath, file.from); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts index 6804c9f5a9..d37e967f43 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts @@ -14,20 +14,19 @@ * limitations under the License. */ -import * as os from 'os'; -import mockFs from 'mock-fs'; import { resolve as resolvePath } from 'path'; import { createFilesystemRenameAction } from './rename'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; import fs from 'fs-extra'; - -const root = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir'; -const workspacePath = resolvePath(root, 'my-workspace'); +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('fs:rename', () => { const action = createFilesystemRenameAction(); + const mockDir = createMockDirectory(); + const workspacePath = resolvePath(mockDir.path, 'workspace'); + const mockInputFiles = [ { from: 'unit-test-a.js', @@ -56,7 +55,7 @@ describe('fs:rename', () => { beforeEach(() => { jest.restoreAllMocks(); - mockFs({ + mockDir.setContent({ [workspacePath]: { 'unit-test-a.js': 'hello', 'unit-test-b.js': 'world', @@ -68,10 +67,6 @@ describe('fs:rename', () => { }); }); - afterEach(() => { - mockFs.restore(); - }); - it('should throw an error when files is not an array', async () => { await expect( action.handler({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.test.ts new file mode 100644 index 0000000000..9d74d53c6d --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.test.ts @@ -0,0 +1,120 @@ +/* + * 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 { TemplateAction } from '@backstage/plugin-scaffolder-node'; +import { getVoidLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { + DefaultGithubCredentialsProvider, + GithubCredentialsProvider, + ScmIntegrations, +} from '@backstage/integration'; +import { PassThrough } from 'stream'; +import { createGithubIssuesLabelAction } from './githubIssuesLabel'; +import yaml from 'yaml'; +import { examples } from './githubIssuesLabel.examples'; +import { getOctokitOptions } from './helpers'; + +jest.mock('./helpers', () => { + return { + getOctokitOptions: jest.fn(), + }; +}); + +const mockOctokit = { + rest: { + issues: { + addLabels: jest.fn(), + }, + }, +}; +jest.mock('octokit', () => ({ + Octokit: class { + constructor() { + return mockOctokit; + } + }, +})); + +describe('github:issues:label examples', () => { + const config = new ConfigReader({ + integrations: { + github: [ + { host: 'github.com', token: 'tokenlols' }, + { host: 'ghe.github.com' }, + ], + }, + }); + + const getOctokitOptionsMock = getOctokitOptions as jest.Mock; + const integrations = ScmIntegrations.fromConfig(config); + let githubCredentialsProvider: GithubCredentialsProvider; + let action: TemplateAction<any>; + + const mockContext = { + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + + beforeEach(() => { + jest.resetAllMocks(); + githubCredentialsProvider = + DefaultGithubCredentialsProvider.fromIntegrations(integrations); + action = createGithubIssuesLabelAction({ + integrations, + githubCredentialsProvider, + }); + }); + + afterEach(jest.resetAllMocks); + + it('should call the githubApi for adding labels without token', async () => { + await action.handler({ + ...mockContext, + input: yaml.parse(examples[0].example).steps[0].input, + }); + + expect(mockOctokit.rest.issues.addLabels).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + issue_number: '1', + labels: ['bug'], + }); + + expect(getOctokitOptionsMock.mock.calls[0][0].token).toBeUndefined(); + }); + + it('should call the githubApi for adding labels with token', async () => { + await action.handler({ + ...mockContext, + input: yaml.parse(examples[1].example).steps[0].input, + }); + + expect(mockOctokit.rest.issues.addLabels).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + issue_number: '1', + labels: ['bug', 'documentation'], + }); + + expect(getOctokitOptionsMock.mock.calls[0][0].token).toEqual( + 'gph_YourGitHubToken', + ); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.ts new file mode 100644 index 0000000000..e0f631df7b --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.examples.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 { TemplateExample } from '@backstage/plugin-scaffolder-node'; +import yaml from 'yaml'; + +export const examples: TemplateExample[] = [ + { + description: 'Add labels to pull request or issue', + example: yaml.stringify({ + steps: [ + { + action: 'github:issues:label', + name: 'Add labels to pull request or issue', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + number: '1', + labels: ['bug'], + }, + }, + ], + }), + }, + { + description: 'Add labels to pull request or issue with specific token', + example: yaml.stringify({ + steps: [ + { + action: 'github:issues:label', + name: 'Add labels to pull request or issue with token', + input: { + repoUrl: 'github.com?repo=repo&owner=owner', + number: '1', + labels: ['bug', 'documentation'], + token: 'gph_YourGitHubToken', + }, + }, + ], + }), + }, +]; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.test.ts index a1a0274304..3da16e677a 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.test.ts @@ -24,6 +24,13 @@ import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; import { PassThrough } from 'stream'; +import { getOctokitOptions } from './helpers'; + +jest.mock('./helpers', () => { + return { + getOctokitOptions: jest.fn(), + }; +}); const mockOctokit = { rest: { @@ -50,6 +57,7 @@ describe('github:issues:label', () => { }, }); + const getOctokitOptionsMock = getOctokitOptions as jest.Mock; const integrations = ScmIntegrations.fromConfig(config); let githubCredentialsProvider: GithubCredentialsProvider; let action: TemplateAction<any>; @@ -85,5 +93,22 @@ describe('github:issues:label', () => { issue_number: '1', labels: ['label1', 'label2'], }); + expect(getOctokitOptionsMock.mock.calls[0][0].token).toBeUndefined(); + }); + + it('should call the githubApi for adding labels with token', async () => { + await action.handler({ + ...mockContext, + input: { ...mockContext.input, token: 'gph_YourGitHubToken' }, + }); + expect(mockOctokit.rest.issues.addLabels).toHaveBeenCalledWith({ + owner: 'owner', + repo: 'repo', + issue_number: '1', + labels: ['label1', 'label2'], + }); + expect(getOctokitOptionsMock.mock.calls[0][0].token).toEqual( + 'gph_YourGitHubToken', + ); }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.ts index 2dad0aa33a..73a65ffb14 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubIssuesLabel.ts @@ -23,6 +23,7 @@ import { assertError, InputError } from '@backstage/errors'; import { Octokit } from 'octokit'; import { getOctokitOptions } from './helpers'; import { parseRepoUrl } from '../publish/util'; +import { examples } from './githubIssuesLabel.examples'; /** * Adds labels to a pull request or issue on GitHub @@ -42,6 +43,7 @@ export function createGithubIssuesLabelAction(options: { }>({ id: 'github:issues:label', description: 'Adds labels to a pull request or issue on GitHub.', + examples, schema: { input: { type: 'object', diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.examples.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.examples.test.ts new file mode 100644 index 0000000000..e4fd18ef59 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.examples.test.ts @@ -0,0 +1,121 @@ +/* + * 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 yaml from 'yaml'; +import { ConfigReader } from '@backstage/config'; +import { createPublishAzureAction } from './azure'; +import { ScmIntegrations } from '@backstage/integration'; +import { getVoidLogger } from '@backstage/backend-common'; +import { WebApi } from 'azure-devops-node-api'; +import { PassThrough } from 'stream'; +import { initRepoAndPush } from '../helpers'; +import { examples } from './azure.examples'; + +jest.mock('azure-devops-node-api', () => ({ + WebApi: jest.fn(), + getPersonalAccessTokenHandler: jest.fn().mockReturnValue(() => {}), +})); + +jest.mock('../helpers', () => { + return { + initRepoAndPush: jest.fn().mockResolvedValue({ + commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', + }), + commitAndPushRepo: jest.fn().mockResolvedValue({ + commitHash: '220f19cc36b551763d157f1b5e4a4b446165dbd6', + }), + }; +}); + +describe('publish:azure examples', () => { + const config = new ConfigReader({ + integrations: { + azure: [ + { + host: 'dev.azure.com', + credentials: [{ personalAccessToken: 'tokenlols' }], + }, + ], + }, + }); + + const integrations = ScmIntegrations.fromConfig(config); + const action = createPublishAzureAction({ integrations, config }); + const mockContext = { + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + + const mockGitClient = { + createRepository: jest.fn(), + }; + const mockGitApi = { + getGitApi: jest.fn().mockReturnValue(mockGitClient), + }; + + (WebApi as unknown as jest.Mock).mockImplementation(() => mockGitApi); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should call initRepoAndPush with the correct values', async () => { + mockGitClient.createRepository.mockResolvedValue({ + remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', + id: '709e891c-dee7-4f91-b963-534713c0737f', + }); + + await action.handler({ + ...mockContext, + input: yaml.parse(examples[0].example).steps[0].input, + }); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', + defaultBranch: 'master', + auth: { username: 'notempty', password: 'tokenlols' }, + logger: mockContext.logger, + commitMessage: 'initial commit', + gitAuthorInfo: {}, + }); + }); + + it('should call initRepoAndPush with a changed default branch', async () => { + mockGitClient.createRepository.mockResolvedValue({ + remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', + id: '709e891c-dee7-4f91-b963-534713c0737f', + }); + + await action.handler({ + ...mockContext, + input: yaml.parse(examples[2].example).steps[0].input, + }); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', + defaultBranch: 'main', + auth: { username: 'notempty', password: 'tokenlols' }, + logger: mockContext.logger, + commitMessage: 'initial commit', + gitAuthorInfo: {}, + }); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.examples.ts new file mode 100644 index 0000000000..48b57c410d --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.examples.ts @@ -0,0 +1,73 @@ +/* + * 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 { TemplateExample } from '@backstage/plugin-scaffolder-node'; +import yaml from 'yaml'; + +export const examples: TemplateExample[] = [ + { + description: + 'Initializes a git repository of the content in the workspace, and publishes it to Azure.', + example: yaml.stringify({ + steps: [ + { + id: 'publish', + action: 'publish:azure', + name: 'Publish to Azure', + input: { + repoUrl: + 'dev.azure.com?organization=organization&owner=project&repo=repo', + }, + }, + ], + }), + }, + { + description: 'Add a description.', + example: yaml.stringify({ + steps: [ + { + id: 'publish', + action: 'publish:azure', + name: 'Publish to Azure', + input: { + repoUrl: + 'dev.azure.com?organization=organization&owner=project&repo=repo', + description: 'Initialize a git repository', + }, + }, + ], + }), + }, + { + description: 'Change the default branch.', + example: yaml.stringify({ + steps: [ + { + id: 'publish', + action: 'publish:azure', + name: 'Publish to Azure', + input: { + repoUrl: + 'dev.azure.com?organization=organization&owner=project&repo=repo', + description: 'Initialize a git repository', + defaultBranch: 'main', + }, + }, + ], + }), + }, +]; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts index b6c0226163..a7df154687 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts @@ -29,6 +29,7 @@ import { import { getRepoSourceDirectory, parseRepoUrl } from './util'; import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; import { Config } from '@backstage/config'; +import { examples } from './azure.examples'; /** * Creates a new action that initializes a git repository of the content in the workspace @@ -52,6 +53,7 @@ export function createPublishAzureAction(options: { gitAuthorEmail?: string; }>({ id: 'publish:azure', + examples, description: 'Initializes a git repository of the content in the workspace, and publishes it to Azure.', schema: { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts index b6987335f9..a1f3712a9d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts @@ -24,21 +24,17 @@ import { ActionContext, TemplateAction, } from '@backstage/plugin-scaffolder-node'; -import mockFs from 'mock-fs'; -import os from 'os'; -import { resolve as resolvePath } from 'path'; +import fs from 'fs-extra'; import { Writable } from 'stream'; import { createPublishGithubPullRequestAction, OctokitWithPullRequestPluginClient, } from './githubPullRequest'; +import { createMockDirectory } from '@backstage/backend-test-utils'; // Make sure root logger is initialized ahead of FS mock createRootLogger(); -const root = os.platform() === 'win32' ? 'C:\\root' : '/root'; -const workspacePath = resolvePath(root, 'my-workspace'); - type GithubPullRequestActionInput = ReturnType< typeof createPublishGithubPullRequestAction > extends TemplateAction<infer U> @@ -54,7 +50,12 @@ describe('createPublishGithubPullRequestAction', () => { }; }; + const mockDir = createMockDirectory(); + const workspacePath = mockDir.resolve('workspace'); + beforeEach(() => { + mockDir.clear(); + const integrations = ScmIntegrations.fromConfig(new ConfigReader({})); fakeClient = { createPullRequest: jest.fn(async (_: any) => { @@ -92,7 +93,6 @@ describe('createPublishGithubPullRequestAction', () => { }); afterEach(() => { - mockFs.restore(); jest.resetAllMocks(); }); @@ -132,7 +132,7 @@ describe('createPublishGithubPullRequestAction', () => { draft: true, }; - mockFs({ + mockDir.setContent({ [workspacePath]: { 'file.txt': 'Hello there!' }, }); @@ -197,7 +197,7 @@ describe('createPublishGithubPullRequestAction', () => { draft: true, }; - mockFs({ + mockDir.setContent({ [workspacePath]: { 'file.txt': 'Hello there!' }, }); @@ -261,7 +261,7 @@ describe('createPublishGithubPullRequestAction', () => { sourcePath: 'source', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -323,7 +323,7 @@ describe('createPublishGithubPullRequestAction', () => { description: 'This PR is really good', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { 'file.txt': 'Hello there!' }, }); @@ -385,7 +385,7 @@ describe('createPublishGithubPullRequestAction', () => { teamReviewers: ['team-foo'], }; - mockFs({ [workspacePath]: {} }); + mockDir.setContent({ [workspacePath]: {} }); ctx = { createTemporaryDirectory: jest.fn(), @@ -437,7 +437,7 @@ describe('createPublishGithubPullRequestAction', () => { description: 'This PR is really good', }; - mockFs({ [workspacePath]: {} }); + mockDir.setContent({ [workspacePath]: {} }); ctx = { createTemporaryDirectory: jest.fn(), @@ -469,11 +469,9 @@ describe('createPublishGithubPullRequestAction', () => { description: 'This PR is really good', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { - Makefile: mockFs.symlink({ - path: '../../nothing/yet', - }), + Makefile: c => c.symlink('../../nothing/yet'), }, }); @@ -523,12 +521,13 @@ describe('createPublishGithubPullRequestAction', () => { description: 'This PR is really good', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { - 'hello.sh': mockFs.file({ - content: 'echo Hello there!', - mode: 0o100755, - }), + 'hello.sh': c => + fs.writeFileSync(c.path, 'echo Hello there!', { + encoding: 'utf8', + mode: 0o100755, + }), }, }); @@ -588,12 +587,13 @@ describe('createPublishGithubPullRequestAction', () => { description: 'This PR is really good', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { - 'hello.sh': mockFs.file({ - content: 'echo Hello there!', - mode: 0o100775, - }), + 'hello.sh': c => + fs.writeFileSync(c.path, 'echo Hello there!', { + encoding: 'utf8', + mode: 0o100775, + }), }, }); @@ -654,7 +654,7 @@ describe('createPublishGithubPullRequestAction', () => { commitMessage: 'Create my new app, but in the commit message', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { 'file.txt': 'Hello there!' }, }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts index ac259866e3..b20fcf52e9 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.examples.ts @@ -68,4 +68,79 @@ export const examples: TemplateExample[] = [ ], }), }, + { + description: 'Initializes a git repository with additional settings.', + example: yaml.stringify({ + steps: [ + { + id: 'publish', + action: 'publish:gitlab', + name: 'Publish to GitLab', + input: { + repoUrl: 'gitlab.com?repo=project_name&owner=group_name', + settings: { + ci_config_path: '.gitlab-ci.yml', + visibility: 'public', + }, + }, + }, + ], + }), + }, + { + description: 'Initializes a git repository with branches settings', + example: yaml.stringify({ + steps: [ + { + id: 'publish', + action: 'publish:gitlab', + name: 'Publish to GitLab', + input: { + repoUrl: 'gitlab.com?repo=project_name&owner=group_name', + branches: [ + { + name: 'dev', + create: true, + protected: true, + ref: 'master', + }, + { + name: 'master', + protected: true, + }, + ], + }, + }, + ], + }), + }, + { + description: 'Initializes a git repository with environment variables', + example: yaml.stringify({ + steps: [ + { + id: 'publish', + action: 'publish:gitlab', + name: 'Publish to GitLab', + input: { + repoUrl: 'gitlab.com?repo=project_name&owner=group_name', + projectVariables: [ + { + key: 'key1', + value: 'value1', + protected: true, + masked: false, + }, + { + key: 'key2', + value: 'value2', + protected: true, + masked: false, + }, + ], + }, + }, + ], + }), + }, ]; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index dc8e3eb0ee..b2f3dc6480 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -45,6 +45,15 @@ const mockGitlabClient = { ProjectMembers: { add: jest.fn(), }, + Branches: { + create: jest.fn(), + }, + ProtectedBranches: { + protect: jest.fn(), + }, + ProjectVariables: { + create: jest.fn(), + }, }; jest.mock('@gitbeaker/node', () => ({ Gitlab: class { @@ -77,6 +86,73 @@ describe('publish:gitlab', () => { input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', repoVisibility: 'private' as const, + settings: { + ci_config_path: '.gitlab-ci.yml', + }, + }, + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + const mockContextWithSettings = { + input: { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + repoVisibility: 'private' as const, + topics: ['topic'], + settings: { + ci_config_path: '.gitlab-ci.yml', + visibility: 'internal' as const, + topics: ['topic1', 'topic2'], + }, + }, + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + const mockContextWithBranches = { + input: { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + repoVisibility: 'private' as const, + branches: [ + { + name: 'dev', + create: true, + ref: 'master', + protect: true, + }, + { + name: 'stage', + create: true, + }, + { + name: 'perf', + protect: true, + }, + ], + }, + workspacePath: 'lol', + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + const mockContextWithVariables = { + input: { + repoUrl: 'gitlab.com?repo=repo&owner=owner', + repoVisibility: 'private' as const, + projectVariables: [ + { + key: 'key', + value: 'value', + description: 'description', + protected: true, + masked: true, + }, + ], }, workspacePath: 'lol', logger: getVoidLogger(), @@ -146,6 +222,8 @@ describe('publish:gitlab', () => { name: 'bob', visibility: 'private', }); + expect(mockGitlabClient.Branches.create).not.toHaveBeenCalled(); + expect(mockGitlabClient.ProtectedBranches.protect).not.toHaveBeenCalled(); }); it('should call the correct Gitlab APIs when the owner is an organization', async () => { @@ -162,7 +240,10 @@ describe('publish:gitlab', () => { namespace_id: 1234, name: 'repo', visibility: 'private', + ci_config_path: '.gitlab-ci.yml', }); + expect(mockGitlabClient.Branches.create).not.toHaveBeenCalled(); + expect(mockGitlabClient.ProtectedBranches.protect).not.toHaveBeenCalled(); }); it('should call the correct Gitlab APIs when the owner is not an organization', async () => { @@ -179,7 +260,103 @@ describe('publish:gitlab', () => { namespace_id: 12345, name: 'repo', visibility: 'private', + ci_config_path: '.gitlab-ci.yml', }); + expect(mockGitlabClient.Branches.create).not.toHaveBeenCalled(); + expect(mockGitlabClient.ProtectedBranches.protect).not.toHaveBeenCalled(); + }); + + it('should call the correct Gitlab APIs when using project settings with override of visibility and topics', async () => { + mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 }); + mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); + mockGitlabClient.Projects.create.mockResolvedValue({ + http_url_to_repo: 'http://mockurl.git', + }); + + await action.handler(mockContextWithSettings); + + expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner'); + expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({ + namespace_id: 1234, + name: 'repo', + visibility: 'internal', + topics: ['topic1', 'topic2'], + ci_config_path: '.gitlab-ci.yml', + }); + expect(mockGitlabClient.Branches.create).not.toHaveBeenCalled(); + expect(mockGitlabClient.ProtectedBranches.protect).not.toHaveBeenCalled(); + }); + + it('should call the correct Gitlab APIs for branches and protectd branches when branch settings provided', async () => { + mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 }); + mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); + mockGitlabClient.Projects.create.mockResolvedValue({ + id: 123456, + http_url_to_repo: 'http://mockurl.git', + }); + + await action.handler(mockContextWithBranches); + + expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner'); + expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({ + namespace_id: 1234, + name: 'repo', + visibility: 'private', + }); + expect(mockGitlabClient.Branches.create).toHaveBeenCalledTimes(2); + expect(mockGitlabClient.ProtectedBranches.protect).toHaveBeenCalledTimes(2); + + expect(mockGitlabClient.Branches.create).toHaveBeenCalledWith( + 123456, + 'dev', + 'master', + ); + expect(mockGitlabClient.Branches.create).toHaveBeenCalledWith( + 123456, + 'stage', + 'master', + ); + + expect(mockGitlabClient.ProtectedBranches.protect).toHaveBeenCalledWith( + 123456, + 'dev', + ); + expect(mockGitlabClient.ProtectedBranches.protect).toHaveBeenCalledWith( + 123456, + 'perf', + ); + }); + + it('should call the correct Gitlab APIs for variables when their configuration is provided', async () => { + mockGitlabClient.Users.current.mockResolvedValue({ id: 12345 }); + mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); + mockGitlabClient.Projects.create.mockResolvedValue({ + id: 123456, + http_url_to_repo: 'http://mockurl.git', + }); + + await action.handler(mockContextWithVariables); + + expect(mockGitlabClient.Namespaces.show).toHaveBeenCalledWith('owner'); + expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({ + namespace_id: 1234, + name: 'repo', + visibility: 'private', + }); + + expect(mockGitlabClient.ProjectVariables.create).toHaveBeenCalledWith( + 123456, + { + key: 'key', + value: 'value', + description: 'description', + variable_type: 'env_var', + protected: true, + masked: true, + raw: false, + environment_scope: '*', + }, + ); }); it('should call initRepoAndPush with the correct values', async () => { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index 25f78452a4..6d86841a20 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -38,6 +38,7 @@ export function createPublishGitlabAction(options: { return createTemplateAction<{ repoUrl: string; defaultBranch?: string; + /** @deprecated in favour of settings.visibility field */ repoVisibility?: 'private' | 'internal' | 'public'; sourcePath?: string; token?: string; @@ -45,7 +46,32 @@ export function createPublishGitlabAction(options: { gitAuthorName?: string; gitAuthorEmail?: string; setUserAsOwner?: boolean; + /** @deprecated in favour of settings.topics field */ topics?: string[]; + settings?: { + path?: string; + auto_devops_enabled?: boolean; + ci_config_path?: string; + description?: string; + topics?: string[]; + visibility?: 'private' | 'internal' | 'public'; + }; + branches?: Array<{ + name: string; + protect?: boolean; + create?: boolean; + ref?: string; + }>; + projectVariables?: Array<{ + key: string; + value: string; + description?: string; + variable_type?: string; + protected?: boolean; + masked?: boolean; + raw?: boolean; + environment_scope?: string; + }>; }>({ id: 'publish:gitlab', description: @@ -63,6 +89,7 @@ export function createPublishGitlabAction(options: { }, repoVisibility: { title: 'Repository Visibility', + description: `Sets the visibility of the repository. The default value is 'private'. (deprecated, use settings.visibility instead)`, type: 'string', enum: ['private', 'public', 'internal'], }, @@ -105,12 +132,135 @@ export function createPublishGitlabAction(options: { }, topics: { title: 'Topic labels', - description: 'Topic labels to apply on the repository.', + description: + 'Topic labels to apply on the repository. (deprecated, use settings.topics instead)', type: 'array', items: { type: 'string', }, }, + settings: { + title: 'Project settings', + description: + 'Additional project settings, based on https://docs.gitlab.com/ee/api/projects.html#create-project attributes', + type: 'object', + properties: { + path: { + title: 'Project path', + description: + 'Repository name for new project. Generated based on name if not provided (generated as lowercase with dashes).', + type: 'string', + }, + auto_devops_enabled: { + title: 'Auto DevOps enabled', + description: 'Enable Auto DevOps for this project', + type: 'boolean', + }, + ci_config_path: { + title: 'CI config path', + description: 'Custom CI config path for this project', + type: 'string', + }, + description: { + title: 'Project description', + description: 'Short project description', + type: 'string', + }, + topics: { + title: 'Topic labels', + description: 'Topic labels to apply on the repository', + type: 'array', + items: { + type: 'string', + }, + }, + visibility: { + title: 'Project visibility', + description: + 'The visibility of the project. Can be private, internal, or public. The default value is private.', + type: 'string', + enum: ['private', 'public', 'internal'], + }, + }, + }, + branches: { + title: 'Project branches settings', + type: 'array', + items: { + type: 'object', + required: ['name'], + properties: { + name: { + title: 'Branch name', + type: 'string', + }, + protect: { + title: 'Should branch be protected', + description: `Will mark branch as protected. The default value is 'false'`, + type: 'boolean', + }, + create: { + title: 'Should branch be created', + description: `If branch does not exist, it will be created from provided ref. The default value is 'false'`, + type: 'boolean', + }, + ref: { + title: 'Branch reference', + description: `Branch reference to create branch from. The default value is 'master'`, + type: 'string', + }, + }, + }, + }, + projectVariables: { + title: 'Project variables', + description: + 'Project variables settings based on Gitlab Project Environments API - https://docs.gitlab.com/ee/api/project_level_variables.html#create-a-variable', + type: 'array', + items: { + type: 'object', + required: ['key', 'value'], + properties: { + key: { + title: 'Variable key', + description: + 'The key of a variable; must have no more than 255 characters; only A-Z, a-z, 0-9, and _ are allowed', + type: 'string', + }, + value: { + title: 'Variable value', + description: 'The value of a variable', + type: 'string', + }, + description: { + title: 'Variable description', + description: `The description of the variable. The default value is 'null'`, + type: 'string', + }, + variable_type: { + title: 'Variable type', + description: `The type of a variable. The default value is 'env_var'`, + type: 'string', + enum: ['env_var', 'file'], + }, + protected: { + title: 'Variable protection', + description: `Whether the variable is protected. The default value is 'false'`, + type: 'boolean', + }, + raw: { + title: 'Variable raw', + description: `Whether the variable is in raw format. The default value is 'false'`, + type: 'boolean', + }, + environment_scope: { + title: 'Variable environment scope', + description: `The environment_scope of the variable. The default value is '*'`, + type: 'string', + }, + }, + }, + }, }, }, output: { @@ -145,6 +295,9 @@ export function createPublishGitlabAction(options: { gitAuthorEmail, setUserAsOwner = false, topics = [], + settings = {}, + branches = [], + projectVariables = [], } = ctx.input; const { owner, repo, host } = parseRepoUrl(repoUrl, integrations); @@ -204,6 +357,7 @@ export function createPublishGitlabAction(options: { name: repo, visibility: repoVisibility, ...(topics.length ? { topics } : {}), + ...(Object.keys(settings).length ? { ...settings } : {}), }); // When setUserAsOwner is true the input token is expected to come from an unprivileged user GitLab @@ -247,6 +401,66 @@ export function createPublishGitlabAction(options: { gitAuthorInfo, }); + if (branches) { + for (const branch of branches) { + const { + name, + protect = false, + create = false, + ref = 'master', + } = branch; + + if (create) { + try { + await client.Branches.create(projectId, name, ref); + } catch (e) { + throw new InputError( + `Branch creation failed for ${name}. ${printGitlabError(e)}`, + ); + } + ctx.logger.info( + `Branch ${name} created for ${projectId} with ref ${ref}`, + ); + } + + if (protect) { + try { + await client.ProtectedBranches.protect(projectId, name); + } catch (e) { + throw new InputError( + `Branch protection failed for ${name}. ${printGitlabError(e)}`, + ); + } + ctx.logger.info(`Branch ${name} protected for ${projectId}`); + } + } + } + + if (projectVariables) { + for (const variable of projectVariables) { + const variableWithDefaults = Object.assign(variable, { + variable_type: variable.variable_type ?? 'env_var', + protected: variable.protected ?? false, + masked: variable.masked ?? false, + raw: variable.raw ?? false, + environment_scope: variable.environment_scope ?? '*', + }); + + try { + await client.ProjectVariables.create( + projectId, + variableWithDefaults, + ); + } catch (e) { + throw new InputError( + `Environment variable creation failed for ${ + variableWithDefaults.key + }. ${printGitlabError(e)}`, + ); + } + } + } + ctx.output('commitHash', commitResult?.commitHash); ctx.output('remoteUrl', remoteUrl); ctx.output('repoContentsUrl', repoContentsUrl); @@ -254,3 +468,7 @@ export function createPublishGitlabAction(options: { }, }); } + +function printGitlabError(error: any): string { + return JSON.stringify({ code: error.code, message: error.description }); +} diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.test.ts index 6445d243b5..71a2273aed 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlabMergeRequest.test.ts @@ -17,18 +17,13 @@ import { createRootLogger, getRootLogger } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; -import mockFs from 'mock-fs'; -import os from 'os'; -import { resolve as resolvePath } from 'path'; import { Writable } from 'stream'; import { createPublishGitlabMergeRequestAction } from './gitlabMergeRequest'; +import { createMockDirectory } from '@backstage/backend-test-utils'; // Make sure root logger is initialized ahead of FS mock createRootLogger(); -const root = os.platform() === 'win32' ? 'C:\\root' : '/root'; -const workspacePath = resolvePath(root, 'my-workspace'); - const mockGitlabClient = { Namespaces: { show: jest.fn(), @@ -79,7 +74,12 @@ jest.mock('@gitbeaker/node', () => ({ describe('createGitLabMergeRequest', () => { let instance: TemplateAction<any>; + const mockDir = createMockDirectory(); + const workspacePath = mockDir.resolve('workspace'); + beforeEach(() => { + mockDir.clear(); + const config = new ConfigReader({ integrations: { gitlab: [ @@ -100,10 +100,6 @@ describe('createGitLabMergeRequest', () => { instance = createPublishGitlabMergeRequestAction({ integrations }); }); - afterEach(() => { - mockFs.restore(); - }); - describe('createGitLabMergeRequestWithSpecifiedTargetBranch', () => { it('removeSourceBranch is false by default when not passed in options', async () => { const input = { @@ -114,7 +110,7 @@ describe('createGitLabMergeRequest', () => { description: 'This MR is really good', targetPath: 'Subdirectory', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -156,7 +152,7 @@ describe('createGitLabMergeRequest', () => { description: 'This MR is really good', targetPath: 'Subdirectory', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -200,7 +196,7 @@ describe('createGitLabMergeRequest', () => { removeSourceBranch: true, targetPath: 'Subdirectory', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -235,7 +231,7 @@ describe('createGitLabMergeRequest', () => { removeSourceBranch: false, targetPath: 'Subdirectory', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -276,7 +272,7 @@ describe('createGitLabMergeRequest', () => { targetPath: 'Subdirectory', assignee: 'John Smith', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -316,7 +312,7 @@ describe('createGitLabMergeRequest', () => { targetPath: 'Subdirectory', assingnee: 'John Doe', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -356,7 +352,7 @@ describe('createGitLabMergeRequest', () => { removeSourceBranch: false, targetPath: 'Subdirectory', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -395,7 +391,7 @@ describe('createGitLabMergeRequest', () => { targetPath: 'Subdirectory', assignee: 'Unknown', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -431,7 +427,7 @@ describe('createGitLabMergeRequest', () => { branchName: 'new-mr', description: 'This MR is really good', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -480,7 +476,7 @@ describe('createGitLabMergeRequest', () => { description: 'This MR is really good', targetPath: 'source', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -523,7 +519,7 @@ describe('createGitLabMergeRequest', () => { commitAction: 'create', targetPath: 'source', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -565,7 +561,7 @@ describe('createGitLabMergeRequest', () => { commitAction: 'update', targetPath: 'source', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -607,7 +603,7 @@ describe('createGitLabMergeRequest', () => { commitAction: 'delete', targetPath: 'source', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -652,7 +648,7 @@ describe('createGitLabMergeRequest', () => { commitAction: 'create', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, @@ -697,7 +693,7 @@ describe('createGitLabMergeRequest', () => { commitAction: 'create', }; - mockFs({ + mockDir.setContent({ [workspacePath]: { source: { 'foo.txt': 'Hello there!' }, irrelevant: { 'bar.txt': 'Nothing to see here' }, diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts index d94a8eac69..6907f8cc2c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts @@ -14,10 +14,7 @@ * limitations under the License. */ -import mockFs from 'mock-fs'; -import * as winston from 'winston'; - -import { getVoidLogger, resolvePackagePath } from '@backstage/backend-common'; +import { getVoidLogger } from '@backstage/backend-common'; import { NunjucksWorkflowRunner } from './NunjucksWorkflowRunner'; import { TemplateActionRegistry } from '../actions'; import { ScmIntegrations } from '@backstage/integration'; @@ -36,19 +33,7 @@ import { PermissionEvaluator, } from '@backstage/plugin-permission-common'; import { RESOURCE_TYPE_SCAFFOLDER_ACTION } from '@backstage/plugin-scaffolder-common/alpha'; - -// The Stream module is lazy loaded, so make sure it's in the module cache before mocking fs -void winston.transports.Stream; - -const realFiles = Object.fromEntries( - [ - resolvePackagePath( - '@backstage/plugin-scaffolder-backend', - 'assets', - 'nunjucks.js.txt', - ), - ].map(k => [k, mockFs.load(k)]), -); +import { createMockDirectory } from '@backstage/backend-test-utils'; describe('DefaultWorkflowRunner', () => { const logger = getVoidLogger(); @@ -56,6 +41,8 @@ describe('DefaultWorkflowRunner', () => { let runner: NunjucksWorkflowRunner; let fakeActionHandler: jest.Mock; + const mockDir = createMockDirectory(); + const mockedPermissionApi: jest.Mocked<PermissionEvaluator> = { authorizeConditional: jest.fn(), } as unknown as jest.Mocked<PermissionEvaluator>; @@ -84,11 +71,7 @@ describe('DefaultWorkflowRunner', () => { }); beforeEach(() => { - winston.format.simple(); // put logform in the require.cache before mocking fs - mockFs({ - '/tmp': mockFs.directory(), - ...realFiles, - }); + mockDir.clear(); jest.resetAllMocks(); actionRegistry = new TemplateActionRegistry(); @@ -148,16 +131,12 @@ describe('DefaultWorkflowRunner', () => { runner = new NunjucksWorkflowRunner({ actionRegistry, integrations, - workingDirectory: '/tmp', + workingDirectory: mockDir.path, logger, permissions: mockedPermissionApi, }); }); - afterEach(() => { - mockFs.restore(); - }); - it('should throw an error if the action does not exist', async () => { const task = createMockTaskWithSpec({ apiVersion: 'scaffolder.backstage.io/v1beta3', diff --git a/plugins/scaffolder-common/CHANGELOG.md b/plugins/scaffolder-common/CHANGELOG.md index bf11adfc0e..6e81966514 100644 --- a/plugins/scaffolder-common/CHANGELOG.md +++ b/plugins/scaffolder-common/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-scaffolder-common +## 1.4.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## 1.4.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 1.4.1 ### Patch Changes diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index f1a2a45fe0..0d9ef37999 100644 --- a/plugins/scaffolder-common/package.json +++ b/plugins/scaffolder-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-common", "description": "Common functionalities for the scaffolder, to be shared between scaffolder and scaffolder-backend plugin", - "version": "1.4.1", + "version": "1.4.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/scaffolder-common/src/Template.v1beta3.schema.json b/plugins/scaffolder-common/src/Template.v1beta3.schema.json index 1de68205b2..d4be9b7538 100644 --- a/plugins/scaffolder-common/src/Template.v1beta3.schema.json +++ b/plugins/scaffolder-common/src/Template.v1beta3.schema.json @@ -14,6 +14,7 @@ }, "spec": { "owner": "artist-relations-team", + "type": "website", "parameters": { "required": ["name", "description", "repoUrl"], "backstage:permissions": { diff --git a/plugins/scaffolder-node/CHANGELOG.md b/plugins/scaffolder-node/CHANGELOG.md index c3a17eaf61..33bf8dd380 100644 --- a/plugins/scaffolder-node/CHANGELOG.md +++ b/plugins/scaffolder-node/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-scaffolder-node +## 0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.2 + +## 0.2.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.2-next.0 + ## 0.2.5-next.1 ### Patch Changes diff --git a/plugins/scaffolder-node/package.json b/plugins/scaffolder-node/package.json index b46d4207c5..3194f0c0d6 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.5-next.1", + "version": "0.2.6", "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 77ef8b2d45..2aed192d7d 100644 --- a/plugins/scaffolder-react/CHANGELOG.md +++ b/plugins/scaffolder-react/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-scaffolder-react +## 1.5.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/types@1.1.1 + - @backstage/plugin-scaffolder-common@1.4.2 + +## 1.5.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-scaffolder-common@1.4.2-next.0 + ## 1.5.6-next.1 ### Patch Changes diff --git a/plugins/scaffolder-react/alpha-api-report.md b/plugins/scaffolder-react/alpha-api-report.md index 11bb2c10c4..a31d9b1d60 100644 --- a/plugins/scaffolder-react/alpha-api-report.md +++ b/plugins/scaffolder-react/alpha-api-report.md @@ -6,13 +6,15 @@ /// <reference types="react" /> import { ApiHolder } from '@backstage/core-plugin-api'; +import { ComponentType } from 'react'; import { CustomFieldExtensionSchema } from '@backstage/plugin-scaffolder-react'; +import { CustomFieldValidator } from '@backstage/plugin-scaffolder-react'; import { Dispatch } from 'react'; import { Extension } from '@backstage/core-plugin-api'; import { FieldExtensionComponent } from '@backstage/plugin-scaffolder-react'; -import { FieldProps } from '@rjsf/utils'; +import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; import { FieldValidation } from '@rjsf/utils'; -import { FormProps as FormProps_2 } from '@rjsf/core-v5'; +import { FormProps } from '@backstage/plugin-scaffolder-react'; import { IconComponent } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; import { JsonValue } from '@backstage/types'; @@ -21,24 +23,39 @@ import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; +import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderRJSFFieldProps } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderRJSFFormProps } from '@backstage/plugin-scaffolder-react'; import { ScaffolderStep } from '@backstage/plugin-scaffolder-react'; import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; import { SetStateAction } from 'react'; import { TaskStep } from '@backstage/plugin-scaffolder-common'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; +import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react'; import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; -import { UIOptionsType } from '@rjsf/utils'; import { UiSchema } from '@rjsf/utils'; +// @alpha (undocumented) +export const createAsyncValidators: ( + rootSchema: JsonObject, + validators: Record< + string, + undefined | CustomFieldValidator<unknown, unknown> + >, + context: { + apiHolder: ApiHolder; + }, +) => (formData: JsonObject) => Promise<FormValidation>; + // @alpha export const createFieldValidation: () => FieldValidation; // @alpha -export function createNextScaffolderFieldExtension< +export function createLegacyScaffolderFieldExtension< TReturnValue = unknown, - TInputProps extends UIOptionsType = {}, + TInputProps = unknown, >( - options: NextFieldExtensionOptions<TReturnValue, TInputProps>, + options: LegacyFieldExtensionOptions<TReturnValue, TInputProps>, ): Extension<FieldExtensionComponent<TReturnValue, TInputProps>>; // @alpha @@ -57,59 +74,47 @@ export const extractSchemaFromStep: (inputStep: JsonObject) => { // @alpha export const Form: ( - props: PropsWithChildren<FormProps_2>, + props: PropsWithChildren<ScaffolderRJSFFormProps>, ) => React_2.JSX.Element; -// @alpha -export type FormProps = Pick< - FormProps_2, - 'transformErrors' | 'noHtml5Validate' ->; +// @alpha (undocumented) +export type FormValidation = { + [name: string]: FieldValidation | FormValidation; +}; // @alpha -export type NextCustomFieldValidator< - TFieldReturnValue, - TUiOptions = unknown, -> = ( +export type LegacyCustomFieldValidator<TFieldReturnValue> = ( data: TFieldReturnValue, field: FieldValidation, context: { apiHolder: ApiHolder; - formData: JsonObject; - schema: JsonObject; - uiSchema?: NextFieldExtensionUiSchema<TFieldReturnValue, TUiOptions>; }, ) => void | Promise<void>; // @alpha -export interface NextFieldExtensionComponentProps< +export interface LegacyFieldExtensionComponentProps< TFieldReturnValue, - TUiOptions = {}, -> extends PropsWithChildren<FieldProps<TFieldReturnValue>> { + TUiOptions = unknown, +> extends ScaffolderRJSFFieldProps<TFieldReturnValue> { // (undocumented) - uiSchema?: NextFieldExtensionUiSchema<TFieldReturnValue, TUiOptions>; + uiSchema: ScaffolderRJSFFieldProps['uiSchema'] & { + 'ui:options'?: TUiOptions; + }; } // @alpha -export type NextFieldExtensionOptions< +export type LegacyFieldExtensionOptions< TFieldReturnValue = unknown, - TUiOptions = unknown, + TInputProps = unknown, > = { name: string; component: ( - props: NextFieldExtensionComponentProps<TFieldReturnValue, TUiOptions>, + props: LegacyFieldExtensionComponentProps<TFieldReturnValue, TInputProps>, ) => JSX.Element | null; - validation?: NextCustomFieldValidator<TFieldReturnValue, TUiOptions>; + validation?: LegacyCustomFieldValidator<TFieldReturnValue>; schema?: CustomFieldExtensionSchema; }; -// @alpha -export interface NextFieldExtensionUiSchema<TFieldReturnValue, TUiOptions> - extends UiSchema<TFieldReturnValue> { - // (undocumented) - 'ui:options'?: TUiOptions & UIOptionsType; -} - // @alpha export interface ParsedTemplateSchema { // (undocumented) @@ -176,12 +181,13 @@ export const Stepper: (stepperProps: StepperProps) => React_2.JSX.Element; // @alpha export type StepperProps = { manifest: TemplateParameterSchema; - extensions: NextFieldExtensionOptions<any, any>[]; + extensions: FieldExtensionOptions<any, any>[]; templateName?: string; - FormProps?: FormProps; + formProps?: FormProps; initialState?: Record<string, JsonValue>; onCreate: (values: Record<string, JsonValue>) => Promise<void>; components?: { + ReviewStepComponent?: ComponentType<ReviewStepProps>; ReviewStateComponent?: (props: ReviewStateProps) => JSX.Element; createButtonText?: ReactNode; reviewButtonText?: ReactNode; @@ -236,12 +242,6 @@ export const TemplateGroup: ( props: TemplateGroupProps, ) => React_2.JSX.Element | null; -// @alpha (undocumented) -export type TemplateGroupFilter = { - title?: React_2.ReactNode; - filter: (entity: TemplateEntityV1beta3) => boolean; -}; - // @alpha export interface TemplateGroupProps { // (undocumented) @@ -314,11 +314,14 @@ export type WorkflowProps = { description?: string; namespace: string; templateName: string; + components?: { + ReviewStepComponent?: React_2.ComponentType<ReviewStepProps>; + }; onError(error: Error | undefined): JSX.Element | null; } & Pick< StepperProps, | 'extensions' - | 'FormProps' + | 'formProps' | 'components' | 'onCreate' | 'initialState' diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index da95e6746e..6acc2f9812 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -7,18 +7,42 @@ import { ApiHolder } from '@backstage/core-plugin-api'; import { ApiRef } from '@backstage/core-plugin-api'; +import { ComponentType } from 'react'; +import { CustomValidator } from '@rjsf/utils'; +import { ElementType } from 'react'; +import { ErrorSchema } from '@rjsf/utils'; +import { ErrorTransformer } from '@rjsf/utils'; +import { Experimental_DefaultFormStateBehavior } from '@rjsf/utils'; import { Extension } from '@backstage/core-plugin-api'; -import { FieldProps } from '@rjsf/core'; -import { FieldValidation } from '@rjsf/core'; -import type { FormProps } from '@rjsf/core-v5'; +import { FieldValidation } from '@rjsf/utils'; +import Form from '@rjsf/core'; +import { FormContextType } from '@rjsf/utils'; +import { FormEvent } from 'react'; +import type { FormProps as FormProps_2 } from '@rjsf/core'; +import { GenericObjectType } from '@rjsf/utils'; +import { HTMLAttributes } from 'react'; +import { IChangeEvent } from '@rjsf/core'; +import { IdSchema } from '@rjsf/utils'; import { JsonObject } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; import { JsonValue } from '@backstage/types'; import { Observable } from '@backstage/types'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; +import { ReactNode } from 'react'; +import { Ref } from 'react'; +import { Registry } from '@rjsf/utils'; +import { RegistryWidgetsType } from '@rjsf/utils'; +import { RJSFSchema } from '@rjsf/utils'; +import { RJSFValidationError } from '@rjsf/utils'; +import { StrictRJSFSchema } from '@rjsf/utils'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TaskStep } from '@backstage/plugin-scaffolder-common'; +import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; +import { TemplatesType } from '@rjsf/utils'; +import { UIOptionsType } from '@rjsf/utils'; +import { UiSchema } from '@rjsf/utils'; +import { ValidatorType } from '@rjsf/utils'; // @public export type Action = { @@ -40,7 +64,7 @@ export type ActionExample = { // @public export function createScaffolderFieldExtension< TReturnValue = unknown, - TInputProps = unknown, + TInputProps extends UIOptionsType = {}, >( options: FieldExtensionOptions<TReturnValue, TInputProps>, ): Extension<FieldExtensionComponent<TReturnValue, TInputProps>>; @@ -57,11 +81,14 @@ export type CustomFieldExtensionSchema = { }; // @public -export type CustomFieldValidator<TFieldReturnValue> = ( +export type CustomFieldValidator<TFieldReturnValue, TUiOptions = unknown> = ( data: TFieldReturnValue, field: FieldValidation, context: { apiHolder: ApiHolder; + formData: JsonObject; + schema: JsonObject; + uiSchema?: FieldExtensionUiSchema<TFieldReturnValue, TUiOptions>; }, ) => void | Promise<void>; @@ -71,27 +98,38 @@ export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; // @public export interface FieldExtensionComponentProps< TFieldReturnValue, - TUiOptions = unknown, -> extends FieldProps<TFieldReturnValue> { + TUiOptions = {}, +> extends PropsWithChildren<ScaffolderRJSFFieldProps<TFieldReturnValue>> { // (undocumented) - uiSchema: FieldProps['uiSchema'] & { - 'ui:options'?: TUiOptions; - }; + uiSchema: FieldExtensionUiSchema<TFieldReturnValue, TUiOptions>; } // @public export type FieldExtensionOptions< TFieldReturnValue = unknown, - TInputProps = unknown, + TUiOptions = unknown, > = { name: string; component: ( - props: FieldExtensionComponentProps<TFieldReturnValue, TInputProps>, + props: FieldExtensionComponentProps<TFieldReturnValue, TUiOptions>, ) => JSX.Element | null; - validation?: CustomFieldValidator<TFieldReturnValue>; + validation?: CustomFieldValidator<TFieldReturnValue, TUiOptions>; schema?: CustomFieldExtensionSchema; }; +// @public +export interface FieldExtensionUiSchema<TFieldReturnValue, TUiOptions> + extends UiSchema<TFieldReturnValue> { + // (undocumented) + 'ui:options'?: TUiOptions & UIOptionsType<TFieldReturnValue>; +} + +// @public +export type FormProps = Pick< + FormProps_2, + 'transformErrors' | 'noHtml5Validate' +>; + // @public export type LayoutComponent<_TInputProps> = () => null; @@ -105,7 +143,7 @@ export interface LayoutOptions<P = any> { // @public export type LayoutTemplate<T = any> = NonNullable< - FormProps<T>['uiSchema'] + FormProps_2<T>['uiSchema'] >['ui:ObjectFieldTemplate']; // @public @@ -124,6 +162,20 @@ export type LogEvent = { taskId: string; }; +// @public +export type ReviewStepProps = { + disableButtons: boolean; + formData: JsonObject; + handleBack: () => void; + handleReset: () => void; + handleCreate: () => void; + steps: { + uiSchema: UiSchema; + mergedSchema: JsonObject; + schema: JsonObject; + }[]; +}; + // @public export interface ScaffolderApi { cancelTask(taskId: string): Promise<void>; @@ -186,8 +238,8 @@ export interface ScaffolderDryRunResponse { } // @public -export const ScaffolderFieldExtensions: React_2.ComponentType< - React_2.PropsWithChildren<{}> +export const ScaffolderFieldExtensions: React.ComponentType< + React.PropsWithChildren<{}> >; // @public @@ -226,6 +278,113 @@ export type ScaffolderOutputText = { content?: string; }; +// @public +export type ScaffolderRJSFField< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> = ComponentType<ScaffolderRJSFFieldProps<T, S, F>>; + +// @public +export interface ScaffolderRJSFFieldProps< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> extends GenericObjectType, + Pick< + HTMLAttributes<HTMLElement>, + Exclude< + keyof HTMLAttributes<HTMLElement>, + 'onBlur' | 'onFocus' | 'onChange' + > + > { + autofocus?: boolean; + disabled: boolean; + errorSchema?: ErrorSchema<T>; + formContext?: F; + formData: T; + hideError?: boolean; + idPrefix?: string; + idSchema: IdSchema<T>; + idSeparator?: string; + name: string; + onBlur: (id: string, value: any) => void; + onChange: ( + newFormData: T | undefined, + es?: ErrorSchema<T>, + id?: string, + ) => any; + onFocus: (id: string, value: any) => void; + rawErrors: string[]; + readonly: boolean; + registry: Registry<T, S, F>; + required?: boolean; + schema: S; + uiSchema: UiSchema<T, S, F>; +} + +// @public +export interface ScaffolderRJSFFormProps< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> { + acceptcharset?: string; + action?: string; + autoComplete?: string; + children?: ReactNode; + className?: string; + customValidate?: CustomValidator<T, S, F>; + disabled?: boolean; + enctype?: string; + experimental_defaultFormStateBehavior?: Experimental_DefaultFormStateBehavior; + extraErrors?: ErrorSchema<T>; + fields?: ScaffolderRJSFRegistryFieldsType<T, S, F>; + focusOnFirstError?: boolean | ((error: RJSFValidationError) => void); + formContext?: F; + formData?: T; + id?: string; + idPrefix?: string; + idSeparator?: string; + _internalFormWrapper?: ElementType; + liveOmit?: boolean; + liveValidate?: boolean; + method?: string; + name?: string; + noHtml5Validate?: boolean; + // @deprecated + noValidate?: boolean; + omitExtraData?: boolean; + onBlur?: (id: string, data: any) => void; + onChange?: (data: IChangeEvent<T, S, F>, id?: string) => void; + onError?: (errors: RJSFValidationError[]) => void; + onFocus?: (id: string, data: any) => void; + onSubmit?: (data: IChangeEvent<T, S, F>, event: FormEvent<any>) => void; + readonly?: boolean; + ref?: Ref<Form<T, S, F>>; + schema: S; + showErrorList?: false | 'top' | 'bottom'; + tagName?: ElementType; + target?: string; + templates?: Partial<Omit<TemplatesType<T, S, F>, 'ButtonTemplates'>> & { + ButtonTemplates?: Partial<TemplatesType<T, S, F>['ButtonTemplates']>; + }; + transformErrors?: ErrorTransformer<T, S, F>; + translateString?: Registry['translateString']; + uiSchema?: UiSchema<T, S, F>; + validator: ValidatorType<T, S, F>; + widgets?: RegistryWidgetsType<T, S, F>; +} + +// @public +export type ScaffolderRJSFRegistryFieldsType< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> = { + [name: string]: ScaffolderRJSFField<T, S, F>; +}; + // @public export interface ScaffolderScaffoldOptions { // (undocumented) @@ -313,6 +472,12 @@ export type TaskStream = { output?: ScaffolderTaskOutput; }; +// @public (undocumented) +export type TemplateGroupFilter = { + title?: React.ReactNode; + filter: (entity: TemplateEntityV1beta3) => boolean; +}; + // @public export type TemplateParameterSchema = { title: string; diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 9722c366c4..5f29f96946 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.5.6-next.1", + "version": "1.5.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -60,10 +60,8 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", "@react-hookz/web": "^20.0.0", - "@rjsf/core": "^3.2.1", - "@rjsf/core-v5": "npm:@rjsf/core@5.13.0", - "@rjsf/material-ui": "^3.2.1", - "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@5.13.0", + "@rjsf/core": "5.13.0", + "@rjsf/material-ui": "5.13.0", "@rjsf/utils": "5.13.0", "@rjsf/validator-ajv8": "5.13.0", "@types/json-schema": "^7.0.9", @@ -83,8 +81,8 @@ "zod-to-json-schema": "^3.20.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -93,10 +91,9 @@ "@backstage/plugin-catalog": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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/humanize-duration": "^3.18.1", "@types/luxon": "^3.0.0" diff --git a/plugins/scaffolder-react/src/alpha.ts b/plugins/scaffolder-react/src/alpha.ts index 731b8e07d9..224ee97c06 100644 --- a/plugins/scaffolder-react/src/alpha.ts +++ b/plugins/scaffolder-react/src/alpha.ts @@ -15,4 +15,4 @@ */ export * from './next'; -export type { FormProps } from './next'; +export * from './legacy'; diff --git a/plugins/scaffolder-react/src/components/index.ts b/plugins/scaffolder-react/src/components/index.ts new file mode 100644 index 0000000000..92cb965d75 --- /dev/null +++ b/plugins/scaffolder-react/src/components/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './types'; diff --git a/plugins/scaffolder-react/src/components/types.ts b/plugins/scaffolder-react/src/components/types.ts new file mode 100644 index 0000000000..597998bac4 --- /dev/null +++ b/plugins/scaffolder-react/src/components/types.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 { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; +import type { FormProps as SchemaFormProps } from '@rjsf/core'; +import { UiSchema } from '@rjsf/utils'; +import { JsonObject } from '@backstage/types'; + +/** @public */ +export type TemplateGroupFilter = { + title?: React.ReactNode; + filter: (entity: TemplateEntityV1beta3) => boolean; +}; + +/** + * Any `@rjsf/core` form properties that are publicly exposed to the `ScaffolderPage` + * + * @public + */ +export type FormProps = Pick< + SchemaFormProps, + 'transformErrors' | 'noHtml5Validate' +>; + +/** + * The props for the Last Step in scaffolder template form. + * Which represents the summary of the input provided by the end user. + * + * @public + */ +export type ReviewStepProps = { + disableButtons: boolean; + formData: JsonObject; + handleBack: () => void; + handleReset: () => void; + handleCreate: () => void; + steps: { + uiSchema: UiSchema; + mergedSchema: JsonObject; + schema: JsonObject; + }[]; +}; diff --git a/plugins/scaffolder-react/src/extensions/index.tsx b/plugins/scaffolder-react/src/extensions/index.tsx index d70f5e36c5..5372a8cf7e 100644 --- a/plugins/scaffolder-react/src/extensions/index.tsx +++ b/plugins/scaffolder-react/src/extensions/index.tsx @@ -14,23 +14,17 @@ * limitations under the License. */ -import React from 'react'; import { - CustomFieldExtensionSchema, CustomFieldValidator, FieldExtensionOptions, FieldExtensionComponentProps, + FieldExtensionUiSchema, + CustomFieldExtensionSchema, } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; +import { UIOptionsType } from '@rjsf/utils'; import { FIELD_EXTENSION_KEY, FIELD_EXTENSION_WRAPPER_KEY } from './keys'; -/** - * The type used to wrap up the Layout and embed the input props - * - * @public - */ -export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; - /** * Method for creating field extensions that can be used in the scaffolder * frontend form. @@ -38,7 +32,7 @@ export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; */ export function createScaffolderFieldExtension< TReturnValue = unknown, - TInputProps = unknown, + TInputProps extends UIOptionsType = {}, >( options: FieldExtensionOptions<TReturnValue, TInputProps>, ): Extension<FieldExtensionComponent<TReturnValue, TInputProps>> { @@ -72,9 +66,19 @@ attachComponentData( true, ); +/** + * The type used to wrap up the Layout and embed the input props + * + * @public + */ +export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; + export type { - CustomFieldExtensionSchema, CustomFieldValidator, FieldExtensionOptions, FieldExtensionComponentProps, + FieldExtensionUiSchema, + CustomFieldExtensionSchema, }; + +export * from './rjsf'; diff --git a/plugins/scaffolder-react/src/extensions/rjsf.ts b/plugins/scaffolder-react/src/extensions/rjsf.ts new file mode 100644 index 0000000000..cacedad080 --- /dev/null +++ b/plugins/scaffolder-react/src/extensions/rjsf.ts @@ -0,0 +1,292 @@ +/* + * 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, ElementType, FormEvent, ReactNode, Ref } from 'react'; +import { + ErrorSchema, + FormContextType, + GenericObjectType, + IdSchema, + Registry, + RJSFSchema, + StrictRJSFSchema, + UiSchema, + ValidatorType, + TemplatesType, + RegistryWidgetsType, + RJSFValidationError, + CustomValidator, + Experimental_DefaultFormStateBehavior, + ErrorTransformer, +} from '@rjsf/utils'; +import { HTMLAttributes } from 'react'; +import Form, { IChangeEvent } from '@rjsf/core'; + +/** + * The props for the `Field` components + * @public + */ +export interface ScaffolderRJSFFieldProps< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> extends GenericObjectType, + Pick< + HTMLAttributes<HTMLElement>, + Exclude< + keyof HTMLAttributes<HTMLElement>, + 'onBlur' | 'onFocus' | 'onChange' + > + > { + /** The JSON subschema object for this field */ + schema: S; + /** The uiSchema for this field */ + uiSchema: UiSchema<T, S, F>; + /** The tree of unique ids for every child field */ + idSchema: IdSchema<T>; + /** The data for this field */ + formData: T; + /** The tree of errors for this field and its children */ + errorSchema?: ErrorSchema<T>; + /** The field change event handler; called with the updated form data and an optional `ErrorSchema` */ + onChange: ( + newFormData: T | undefined, + es?: ErrorSchema<T>, + id?: string, + ) => any; + /** The input blur event handler; call it with the field id and value */ + onBlur: (id: string, value: any) => void; + /** The input focus event handler; call it with the field id and value */ + onFocus: (id: string, value: any) => void; + /** The `formContext` object that you passed to `Form` */ + formContext?: F; + /** A boolean value stating if the field should autofocus */ + autofocus?: boolean; + /** A boolean value stating if the field is disabled */ + disabled: boolean; + /** A boolean value stating if the field is hiding its errors */ + hideError?: boolean; + /** A boolean value stating if the field is read-only */ + readonly: boolean; + /** The required status of this field */ + required?: boolean; + /** The unique name of the field, usually derived from the name of the property in the JSONSchema */ + name: string; + /** To avoid collisions with existing ids in the DOM, it is possible to change the prefix used for ids; + * Default is `root` + */ + idPrefix?: string; + /** To avoid using a path separator that is present in field names, it is possible to change the separator used for + * ids (Default is `_`) + */ + idSeparator?: string; + /** An array of strings listing all generated error messages from encountered errors for this field */ + rawErrors: string[]; + /** The `registry` object */ + registry: Registry<T, S, F>; +} + +/** + * The properties that are passed to the `Form` + * @public + */ +export interface ScaffolderRJSFFormProps< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> { + /** The JSON schema object for the form */ + schema: S; + /** An implementation of the `ValidatorType` interface that is needed for form validation to work */ + validator: ValidatorType<T, S, F>; + /** The optional children for the form, if provided, it will replace the default `SubmitButton` */ + children?: ReactNode; + /** The uiSchema for the form */ + uiSchema?: UiSchema<T, S, F>; + /** The data for the form, used to prefill a form with existing data */ + formData?: T; + /** You can provide a `formContext` object to the form, which is passed down to all fields and widgets. Useful for + * implementing context aware fields and widgets. + * + * NOTE: Setting `{readonlyAsDisabled: false}` on the formContext will make the antd theme treat readOnly fields as + * disabled. + */ + formContext?: F; + /** To avoid collisions with existing ids in the DOM, it is possible to change the prefix used for ids; + * Default is `root` + */ + idPrefix?: string; + /** To avoid using a path separator that is present in field names, it is possible to change the separator used for + * ids (Default is `_`) + */ + idSeparator?: string; + /** It's possible to disable the whole form by setting the `disabled` prop. The `disabled` prop is then forwarded down + * to each field of the form. If you just want to disable some fields, see the `ui:disabled` parameter in `uiSchema` + */ + disabled?: boolean; + /** It's possible to make the whole form read-only by setting the `readonly` prop. The `readonly` prop is then + * forwarded down to each field of the form. If you just want to make some fields read-only, see the `ui:readonly` + * parameter in `uiSchema` + */ + readonly?: boolean; + /** The dictionary of registered fields in the form */ + fields?: ScaffolderRJSFRegistryFieldsType<T, S, F>; + /** The dictionary of registered templates in the form; Partial allows a subset to be provided beyond the defaults */ + templates?: Partial<Omit<TemplatesType<T, S, F>, 'ButtonTemplates'>> & { + ButtonTemplates?: Partial<TemplatesType<T, S, F>['ButtonTemplates']>; + }; + /** The dictionary of registered widgets in the form */ + widgets?: RegistryWidgetsType<T, S, F>; + /** If you plan on being notified every time the form data are updated, you can pass an `onChange` handler, which will + * receive the same args as `onSubmit` any time a value is updated in the form. Can also return the `id` of the field + * that caused the change + */ + onChange?: (data: IChangeEvent<T, S, F>, id?: string) => void; + /** To react when submitted form data are invalid, pass an `onError` handler. It will be passed the list of + * encountered errors + */ + onError?: (errors: RJSFValidationError[]) => void; + /** You can pass a function as the `onSubmit` prop of your `Form` component to listen to when the form is submitted + * and its data are valid. It will be passed a result object having a `formData` attribute, which is the valid form + * data you're usually after. The original event will also be passed as a second parameter + */ + onSubmit?: (data: IChangeEvent<T, S, F>, event: FormEvent<any>) => void; + /** Sometimes you may want to trigger events or modify external state when a field has been touched, so you can pass + * an `onBlur` handler, which will receive the id of the input that was blurred and the field value + */ + onBlur?: (id: string, data: any) => void; + /** Sometimes you may want to trigger events or modify external state when a field has been focused, so you can pass + * an `onFocus` handler, which will receive the id of the input that is focused and the field value + */ + onFocus?: (id: string, data: any) => void; + /** The value of this prop will be passed to the `accept-charset` HTML attribute on the form */ + acceptcharset?: string; + /** The value of this prop will be passed to the `action` HTML attribute on the form + * + * NOTE: this just renders the `action` attribute in the HTML markup. There is no real network request being sent to + * this `action` on submit. Instead, react-jsonschema-form catches the submit event with `event.preventDefault()` + * and then calls the `onSubmit` function, where you could send a request programmatically with `fetch` or similar. + */ + action?: string; + /** The value of this prop will be passed to the `autocomplete` HTML attribute on the form */ + autoComplete?: string; + /** The value of this prop will be passed to the `class` HTML attribute on the form */ + className?: string; + /** The value of this prop will be passed to the `enctype` HTML attribute on the form */ + enctype?: string; + /** The value of this prop will be passed to the `id` HTML attribute on the form */ + id?: string; + /** The value of this prop will be passed to the `name` HTML attribute on the form */ + name?: string; + /** The value of this prop will be passed to the `method` HTML attribute on the form */ + method?: string; + /** It's possible to change the default `form` tag name to a different HTML tag, which can be helpful if you are + * nesting forms. However, native browser form behaviour, such as submitting when the `Enter` key is pressed, may no + * longer work + */ + tagName?: ElementType; + /** The value of this prop will be passed to the `target` HTML attribute on the form */ + target?: string; + /** Formerly the `validate` prop; Takes a function that specifies custom validation rules for the form */ + customValidate?: CustomValidator<T, S, F>; + /** This prop allows passing in custom errors that are augmented with the existing JSON Schema errors on the form; it + * can be used to implement asynchronous validation + */ + extraErrors?: ErrorSchema<T>; + /** If set to true, turns off HTML5 validation on the form; Set to `false` by default */ + noHtml5Validate?: boolean; + /** If set to true, turns off all validation. Set to `false` by default + * + * @deprecated - In a future release, this switch may be replaced by making `validator` prop optional + */ + noValidate?: boolean; + /** If set to true, the form will perform validation and show any validation errors whenever the form data is changed, + * rather than just on submit + */ + liveValidate?: boolean; + /** If `omitExtraData` and `liveOmit` are both set to true, then extra form data values that are not in any form field + * will be removed whenever `onChange` is called. Set to `false` by default + */ + liveOmit?: boolean; + /** If set to true, then extra form data values that are not in any form field will be removed whenever `onSubmit` is + * called. Set to `false` by default. + */ + omitExtraData?: boolean; + /** When this prop is set to `top` or 'bottom', a list of errors (or the custom error list defined in the `ErrorList`) will also + * show. When set to false, only inline input validation errors will be shown. Set to `top` by default + */ + showErrorList?: false | 'top' | 'bottom'; + /** A function can be passed to this prop in order to make modifications to the default errors resulting from JSON + * Schema validation + */ + transformErrors?: ErrorTransformer<T, S, F>; + /** If set to true, then the first field with an error will receive the focus when the form is submitted with errors + */ + focusOnFirstError?: boolean | ((error: RJSFValidationError) => void); + /** Optional string translation function, if provided, allows users to change the translation of the RJSF internal + * strings. Some strings contain replaceable parameter values as indicated by `%1`, `%2`, etc. The number after the + * `%` indicates the order of the parameter. The ordering of parameters is important because some languages may choose + * to put the second parameter before the first in its translation. + */ + translateString?: Registry['translateString']; + /** Optional configuration object with flags, if provided, allows users to override default form state behavior + * Currently only affecting minItems on array fields and handling of setting defaults based on the value of + * `emptyObjectFields` + */ + experimental_defaultFormStateBehavior?: Experimental_DefaultFormStateBehavior; + /** + * _internalFormWrapper is currently used by the semantic-ui theme to provide a custom wrapper around `<Form />` + * that supports the proper rendering of those themes. To use this prop, one must pass a component that takes two + * props: `children` and `as`. That component, at minimum, should render the `children` inside of a <form /> tag + * unless `as` is provided, in which case, use the `as` prop in place of `<form />`. + * i.e.: + * ``` + * export default function InternalForm({ children, as }) { + * const FormTag = as || 'form'; + * return <FormTag>{children}</FormTag>; + * } + * ``` + * + * Use at your own risk as this prop is private and may change at any time without notice. + */ + _internalFormWrapper?: ElementType; + /** Support receiving a React ref to the Form + */ + ref?: Ref<Form<T, S, F>>; +} + +/** + * The set of `Fields` stored in the `Registry` + * @public + */ +export type ScaffolderRJSFRegistryFieldsType< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> = { + /** A `Field` indexed by `name` */ + [name: string]: ScaffolderRJSFField<T, S, F>; +}; + +/** + * The `Field` type for Field Extensions + * @public + */ +export type ScaffolderRJSFField< + T = any, + S extends StrictRJSFSchema = RJSFSchema, + F extends FormContextType = any, +> = ComponentType<ScaffolderRJSFFieldProps<T, S, F>>; diff --git a/plugins/scaffolder-react/src/extensions/types.ts b/plugins/scaffolder-react/src/extensions/types.ts index 5d560a20bc..b77dc39c73 100644 --- a/plugins/scaffolder-react/src/extensions/types.ts +++ b/plugins/scaffolder-react/src/extensions/types.ts @@ -14,19 +14,23 @@ * limitations under the License. */ import { ApiHolder } from '@backstage/core-plugin-api'; -import { FieldValidation, FieldProps } from '@rjsf/core'; +import { PropsWithChildren } from 'react'; +import { JsonObject } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; +import { UiSchema, UIOptionsType, FieldValidation } from '@rjsf/utils'; +import { ScaffolderRJSFFieldProps } from './rjsf'; /** - * Field validation type for Custom Field Extensions. + * Type for Field Extension Props for RJSF v5 * * @public */ -export type CustomFieldValidator<TFieldReturnValue> = ( - data: TFieldReturnValue, - field: FieldValidation, - context: { apiHolder: ApiHolder }, -) => void | Promise<void>; +export interface FieldExtensionComponentProps< + TFieldReturnValue, + TUiOptions = {}, +> extends PropsWithChildren<ScaffolderRJSFFieldProps<TFieldReturnValue>> { + uiSchema: FieldExtensionUiSchema<TFieldReturnValue, TUiOptions>; +} /** * Type for the Custom Field Extension schema. @@ -38,6 +42,32 @@ export type CustomFieldExtensionSchema = { uiOptions?: JSONSchema7; }; +/** + * Type for Field Extension UiSchema + * + * @public + */ +export interface FieldExtensionUiSchema<TFieldReturnValue, TUiOptions> + extends UiSchema<TFieldReturnValue> { + 'ui:options'?: TUiOptions & UIOptionsType<TFieldReturnValue>; +} + +/** + * Field validation type for Custom Field Extensions. + * + * @public + */ +export type CustomFieldValidator<TFieldReturnValue, TUiOptions = unknown> = ( + data: TFieldReturnValue, + field: FieldValidation, + context: { + apiHolder: ApiHolder; + formData: JsonObject; + schema: JsonObject; + uiSchema?: FieldExtensionUiSchema<TFieldReturnValue, TUiOptions>; + }, +) => void | Promise<void>; + /** * Type for the Custom Field Extension with the * name and components and validation function. @@ -46,27 +76,12 @@ export type CustomFieldExtensionSchema = { */ export type FieldExtensionOptions< TFieldReturnValue = unknown, - TInputProps = unknown, + TUiOptions = unknown, > = { name: string; component: ( - props: FieldExtensionComponentProps<TFieldReturnValue, TInputProps>, + props: FieldExtensionComponentProps<TFieldReturnValue, TUiOptions>, ) => JSX.Element | null; - validation?: CustomFieldValidator<TFieldReturnValue>; + validation?: CustomFieldValidator<TFieldReturnValue, TUiOptions>; schema?: CustomFieldExtensionSchema; }; - -/** - * Type for field extensions and being able to type - * incoming props easier. - * - * @public - */ -export interface FieldExtensionComponentProps< - TFieldReturnValue, - TUiOptions = unknown, -> extends FieldProps<TFieldReturnValue> { - uiSchema: FieldProps['uiSchema'] & { - 'ui:options'?: TUiOptions; - }; -} diff --git a/plugins/scaffolder-react/src/index.ts b/plugins/scaffolder-react/src/index.ts index 1b20c19414..70560cc694 100644 --- a/plugins/scaffolder-react/src/index.ts +++ b/plugins/scaffolder-react/src/index.ts @@ -15,6 +15,7 @@ */ export * from './extensions'; +export * from './components'; export * from './types'; export * from './secrets'; export * from './api'; diff --git a/plugins/scaffolder-react/src/layouts/createScaffolderLayout.ts b/plugins/scaffolder-react/src/layouts/createScaffolderLayout.ts index 6b2ae1b33b..d950285a7d 100644 --- a/plugins/scaffolder-react/src/layouts/createScaffolderLayout.ts +++ b/plugins/scaffolder-react/src/layouts/createScaffolderLayout.ts @@ -16,7 +16,7 @@ import { LAYOUTS_KEY, LAYOUTS_WRAPPER_KEY } from './keys'; import { attachComponentData, Extension } from '@backstage/core-plugin-api'; -import type { FormProps as SchemaFormProps } from '@rjsf/core-v5'; +import type { FormProps as SchemaFormProps } from '@rjsf/core'; import React from 'react'; /** diff --git a/plugins/scaffolder-react/src/next/extensions/index.tsx b/plugins/scaffolder-react/src/legacy/extensions/index.tsx similarity index 74% rename from plugins/scaffolder-react/src/next/extensions/index.tsx rename to plugins/scaffolder-react/src/legacy/extensions/index.tsx index 70751936c5..870d797fc4 100644 --- a/plugins/scaffolder-react/src/next/extensions/index.tsx +++ b/plugins/scaffolder-react/src/legacy/extensions/index.tsx @@ -15,13 +15,11 @@ */ import { - NextCustomFieldValidator, - NextFieldExtensionOptions, - NextFieldExtensionComponentProps, - NextFieldExtensionUiSchema, + LegacyCustomFieldValidator, + LegacyFieldExtensionOptions, + LegacyFieldExtensionComponentProps, } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; -import { UIOptionsType } from '@rjsf/utils'; import { FIELD_EXTENSION_KEY } from '../../extensions/keys'; import { FieldExtensionComponent } from '@backstage/plugin-scaffolder-react'; @@ -30,11 +28,11 @@ import { FieldExtensionComponent } from '@backstage/plugin-scaffolder-react'; * frontend form. * @alpha */ -export function createNextScaffolderFieldExtension< +export function createLegacyScaffolderFieldExtension< TReturnValue = unknown, - TInputProps extends UIOptionsType = {}, + TInputProps = unknown, >( - options: NextFieldExtensionOptions<TReturnValue, TInputProps>, + options: LegacyFieldExtensionOptions<TReturnValue, TInputProps>, ): Extension<FieldExtensionComponent<TReturnValue, TInputProps>> { return { expose() { @@ -52,8 +50,7 @@ export function createNextScaffolderFieldExtension< } export type { - NextCustomFieldValidator, - NextFieldExtensionOptions, - NextFieldExtensionComponentProps, - NextFieldExtensionUiSchema, + LegacyCustomFieldValidator, + LegacyFieldExtensionOptions, + LegacyFieldExtensionComponentProps, }; diff --git a/plugins/scaffolder-react/src/legacy/extensions/types.ts b/plugins/scaffolder-react/src/legacy/extensions/types.ts new file mode 100644 index 0000000000..54c38ad2cd --- /dev/null +++ b/plugins/scaffolder-react/src/legacy/extensions/types.ts @@ -0,0 +1,65 @@ +/* + * 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 { ApiHolder } from '@backstage/core-plugin-api'; +import { FieldValidation } from '@rjsf/utils'; +import { + CustomFieldExtensionSchema, + ScaffolderRJSFFieldProps, +} from '@backstage/plugin-scaffolder-react'; + +/** + * Field validation type for Custom Field Extensions. + * + * @alpha + */ +export type LegacyCustomFieldValidator<TFieldReturnValue> = ( + data: TFieldReturnValue, + field: FieldValidation, + context: { apiHolder: ApiHolder }, +) => void | Promise<void>; + +/** + * Type for the Custom Field Extension with the + * name and components and validation function. + * + * @alpha + */ +export type LegacyFieldExtensionOptions< + TFieldReturnValue = unknown, + TInputProps = unknown, +> = { + name: string; + component: ( + props: LegacyFieldExtensionComponentProps<TFieldReturnValue, TInputProps>, + ) => JSX.Element | null; + validation?: LegacyCustomFieldValidator<TFieldReturnValue>; + schema?: CustomFieldExtensionSchema; +}; + +/** + * Type for field extensions and being able to type + * incoming props easier. + * + * @alpha + */ +export interface LegacyFieldExtensionComponentProps< + TFieldReturnValue, + TUiOptions = unknown, +> extends ScaffolderRJSFFieldProps<TFieldReturnValue> { + uiSchema: ScaffolderRJSFFieldProps['uiSchema'] & { + 'ui:options'?: TUiOptions; + }; +} diff --git a/plugins/scaffolder-react/src/legacy/index.ts b/plugins/scaffolder-react/src/legacy/index.ts new file mode 100644 index 0000000000..c539a8ba60 --- /dev/null +++ b/plugins/scaffolder-react/src/legacy/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './extensions'; diff --git a/plugins/scaffolder-react/src/next/components/Form/Form.tsx b/plugins/scaffolder-react/src/next/components/Form/Form.tsx index 790c9027fe..85e75e2c0d 100644 --- a/plugins/scaffolder-react/src/next/components/Form/Form.tsx +++ b/plugins/scaffolder-react/src/next/components/Form/Form.tsx @@ -14,26 +14,47 @@ * limitations under the License. */ -import { FormProps, withTheme } from '@rjsf/core-v5'; +import { withTheme } from '@rjsf/core'; import React from 'react'; import { PropsWithChildren } from 'react'; import { FieldTemplate } from './FieldTemplate'; import { DescriptionFieldTemplate } from './DescriptionFieldTemplate'; +import { FieldProps } from '@rjsf/utils'; +import { ScaffolderRJSFFormProps } from '@backstage/plugin-scaffolder-react'; +import { Theme as MuiTheme } from '@rjsf/material-ui'; -// TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly -// which is what we're using here as the default types, it needs to depend on @rjsf/core-v5 because -// of the re-writing we're doing. Once we've migrated, we can import this the exact same as before. -const WrappedForm = withTheme(require('@rjsf/material-ui-v5').Theme); +const WrappedForm = withTheme(MuiTheme); /** * The Form component * @alpha */ -export const Form = (props: PropsWithChildren<FormProps>) => { +export const Form = (props: PropsWithChildren<ScaffolderRJSFFormProps>) => { + // This is where we unbreak the changes from RJSF, and make it work with our custom fields so we don't pass on this + // breaking change to our users. We will look more into a better API for this in scaffolderv2. + const wrappedFields = Object.fromEntries( + Object.entries(props.fields ?? {}).map(([key, Component]) => [ + key, + (wrapperProps: FieldProps) => { + return ( + <Component + {...wrapperProps} + uiSchema={wrapperProps.uiSchema ?? {}} + formData={wrapperProps.formData} + rawErrors={wrapperProps.rawErrors ?? []} + /> + ); + }, + ]), + ); + const templates = { FieldTemplate, DescriptionFieldTemplate, ...props.templates, }; - return <WrappedForm {...props} templates={templates} />; + + return ( + <WrappedForm {...props} templates={templates} fields={wrappedFields} /> + ); }; 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 6183f32a6c..34243e232d 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx @@ -20,7 +20,7 @@ import { renderInTestApp } from '@backstage/test-utils'; import { act, fireEvent } from '@testing-library/react'; import type { RJSFValidationError } from '@rjsf/utils'; import { JsonValue } from '@backstage/types'; -import { NextFieldExtensionComponentProps } from '../../extensions'; +import { FieldExtensionComponentProps } from '../../../extensions'; import { LayoutTemplate } from '../../../layouts'; describe('Stepper', () => { @@ -115,7 +115,7 @@ describe('Stepper', () => { it('should merge nested formData correctly in multiple steps', async () => { const Repo = ({ onChange, - }: NextFieldExtensionComponentProps<{ repository: string }, any>) => ( + }: FieldExtensionComponentProps<{ repository: string }, any>) => ( <input aria-label="repo" type="text" @@ -126,7 +126,7 @@ describe('Stepper', () => { const Owner = ({ onChange, - }: NextFieldExtensionComponentProps<{ owner: string }, any>) => ( + }: FieldExtensionComponentProps<{ owner: string }, any>) => ( <input aria-label="owner" type="text" @@ -273,12 +273,12 @@ describe('Stepper', () => { />, ); - await act(async () => { - await fireEvent.click(getByRole('button', { name: 'Review' })); - - expect(getByRole('progressbar')).toBeInTheDocument(); - expect(getByRole('button', { name: 'Review' })).toBeDisabled(); + act(() => { + fireEvent.click(getByRole('button', { name: 'Review' })); }); + + expect(getByRole('progressbar')).toBeInTheDocument(); + expect(getByRole('button', { name: 'Review' })).toBeDisabled(); }); it('should transform default error message', async () => { @@ -312,7 +312,7 @@ describe('Stepper', () => { manifest={manifest} extensions={[]} onCreate={jest.fn()} - FormProps={{ transformErrors }} + formProps={{ transformErrors }} />, ); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index e15953bf1f..1e43eba770 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -23,10 +23,15 @@ import { makeStyles, LinearProgress, } from '@material-ui/core'; -import { type IChangeEvent } from '@rjsf/core-v5'; +import { type IChangeEvent } from '@rjsf/core'; import { ErrorSchema } from '@rjsf/utils'; -import React, { useCallback, useMemo, useState, type ReactNode } from 'react'; -import { NextFieldExtensionOptions } from '../../extensions'; +import React, { + useCallback, + useMemo, + useState, + type ReactNode, + ComponentType, +} from 'react'; import { createAsyncValidators, type FormValidation, @@ -35,7 +40,6 @@ import { ReviewState, type ReviewStateProps } from '../ReviewState'; import { useTemplateSchema } from '../../hooks/useTemplateSchema'; import validator from '@rjsf/validator-ajv8'; import { useFormDataFromQuery } from '../../hooks'; -import { FormProps } from '../../types'; import { useTransformSchemaToProps } from '../../hooks/useTransformSchemaToProps'; import { hasErrors } from './utils'; import * as FieldOverrides from './FieldOverrides'; @@ -43,7 +47,10 @@ import { Form } from '../Form'; import { TemplateParameterSchema, LayoutOptions, + FieldExtensionOptions, + FormProps, } from '@backstage/plugin-scaffolder-react'; +import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; const useStyles = makeStyles(theme => ({ backButton: { @@ -66,12 +73,13 @@ const useStyles = makeStyles(theme => ({ */ export type StepperProps = { manifest: TemplateParameterSchema; - extensions: NextFieldExtensionOptions<any, any>[]; + extensions: FieldExtensionOptions<any, any>[]; templateName?: string; - FormProps?: FormProps; + formProps?: FormProps; initialState?: Record<string, JsonValue>; onCreate: (values: Record<string, JsonValue>) => Promise<void>; components?: { + ReviewStepComponent?: ComponentType<ReviewStepProps>; ReviewStateComponent?: (props: ReviewStateProps) => JSX.Element; createButtonText?: ReactNode; reviewButtonText?: ReactNode; @@ -87,6 +95,7 @@ export const Stepper = (stepperProps: StepperProps) => { const { layouts = [], components = {}, ...props } = stepperProps; const { ReviewStateComponent = ReviewState, + ReviewStepComponent, createButtonText = 'Create', reviewButtonText = 'Review', } = components; @@ -128,6 +137,13 @@ export const Stepper = (stepperProps: StepperProps) => { [setFormState], ); + const handleCreate = useCallback(() => { + props.onCreate(formState); + const name = + typeof formState.name === 'string' ? formState.name : undefined; + analytics.captureEvent('create', name ?? props.templateName ?? 'unknown'); + }, [props, formState, analytics]); + const currentStep = useTransformSchemaToProps(steps[activeStep], { layouts }); const handleNext = async ({ @@ -171,6 +187,7 @@ export const Stepper = (stepperProps: StepperProps) => { </MuiStep> </MuiStepper> <div className={styles.formWrapper}> + {/* eslint-disable-next-line no-nested-ternary */} {activeStep < steps.length ? ( <Form validator={validator} @@ -183,7 +200,7 @@ export const Stepper = (stepperProps: StepperProps) => { fields={{ ...FieldOverrides, ...extensions }} showErrorList={false} onChange={handleChange} - {...(props.FormProps ?? {})} + {...(props.formProps ?? {})} > <div className={styles.footer}> <Button @@ -203,6 +220,16 @@ export const Stepper = (stepperProps: StepperProps) => { </Button> </div> </Form> + ) : // TODO: potentially move away from this pattern, deprecate? + ReviewStepComponent ? ( + <ReviewStepComponent + disableButtons={isValidating} + formData={formState} + handleBack={handleBack} + handleReset={() => {}} + steps={steps} + handleCreate={handleCreate} + /> ) : ( <> <ReviewStateComponent formState={formState} schemas={steps} /> @@ -217,17 +244,7 @@ export const Stepper = (stepperProps: StepperProps) => { <Button variant="contained" color="primary" - onClick={() => { - props.onCreate(formState); - const name = - typeof formState.name === 'string' - ? formState.name - : undefined; - analytics.captureEvent( - 'create', - name ?? props.templateName ?? 'unknown', - ); - }} + onClick={handleCreate} > {createButtonText} </Button> diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts index 3633410769..f4dab376bc 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { JsonObject } from '@backstage/types'; -import { NextCustomFieldValidator } from '../../extensions'; +import { CustomFieldValidator } from '../../../extensions'; import { createAsyncValidators } from './createAsyncValidators'; describe('createAsyncValidators', () => { @@ -158,16 +158,13 @@ describe('createAsyncValidators', () => { }, }; - const NameField: NextCustomFieldValidator<string> = ( - value, - { addError }, - ) => { + const NameField: CustomFieldValidator<string> = (value, { addError }) => { if (!value) { addError('something is broken here!'); } }; - const AddressField: NextCustomFieldValidator<{ + const AddressField: CustomFieldValidator<{ street?: string; postcode?: string; }> = (value, { addError }) => { @@ -183,8 +180,8 @@ describe('createAsyncValidators', () => { const validate = createAsyncValidators( schema, { - NameField: NameField as NextCustomFieldValidator<unknown>, - AddressField: AddressField as NextCustomFieldValidator<unknown>, + NameField: NameField as CustomFieldValidator<unknown>, + AddressField: AddressField as CustomFieldValidator<unknown>, }, { apiHolder: { get: jest.fn() }, @@ -298,7 +295,7 @@ describe('createAsyncValidators', () => { }, }; - const AddressField: NextCustomFieldValidator<{ + const AddressField: CustomFieldValidator<{ street?: string; postcode?: string; }> = (value, { addError }) => { @@ -311,18 +308,15 @@ describe('createAsyncValidators', () => { } }; - const NameField: NextCustomFieldValidator<string> = ( - value, - { addError }, - ) => { + const NameField: CustomFieldValidator<string> = (value, { addError }) => { if (!value) { addError('something is broken here!'); } }; const validators = { - AddressField: AddressField as NextCustomFieldValidator<unknown>, - NameField: NameField as NextCustomFieldValidator<unknown>, + AddressField: AddressField as CustomFieldValidator<unknown>, + NameField: NameField as CustomFieldValidator<unknown>, }; const validate = createAsyncValidators(schema, validators, { diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index ceef701255..f50f44d8f5 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -19,22 +19,23 @@ import type { JsonObject, JsonValue } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; import { Draft07 as JSONSchema } from 'json-schema-library'; import { createFieldValidation, extractSchemaFromStep } from '../../lib'; -import { NextCustomFieldValidator } from '../../extensions'; +import { + CustomFieldValidator, + FieldExtensionUiSchema, +} from '@backstage/plugin-scaffolder-react'; import { isObject } from './utils'; -import { NextFieldExtensionUiSchema } from '../../extensions/types'; -/** - * @internal - */ +/** @alpha */ export type FormValidation = { [name: string]: FieldValidation | FormValidation; }; +/** @alpha */ export const createAsyncValidators = ( rootSchema: JsonObject, validators: Record< string, - undefined | NextCustomFieldValidator<unknown, unknown> + undefined | CustomFieldValidator<unknown, unknown> >, context: { apiHolder: ApiHolder; @@ -53,7 +54,7 @@ export const createAsyncValidators = ( key: string, value: JsonValue | undefined, schema: JsonObject, - uiSchema: NextFieldExtensionUiSchema<unknown, unknown>, + uiSchema: FieldExtensionUiSchema<unknown, unknown>, ) => { const validator = validators[validatorName]; if (validator) { @@ -82,7 +83,7 @@ export const createAsyncValidators = ( const doValidateItem = async ( propValue: JsonObject, itemSchema: JsonObject, - itemUiSchema: NextFieldExtensionUiSchema<unknown, unknown>, + itemUiSchema: FieldExtensionUiSchema<unknown, unknown>, ) => { await validateForm( propValue['ui:field'] as string, diff --git a/plugins/scaffolder-react/src/next/components/Stepper/index.ts b/plugins/scaffolder-react/src/next/components/Stepper/index.ts index daa47f078e..5f33c2ff78 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/index.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/index.ts @@ -14,3 +14,7 @@ * limitations under the License. */ export { Stepper, type StepperProps } from './Stepper'; +export { + createAsyncValidators, + type FormValidation, +} from './createAsyncValidators'; diff --git a/plugins/scaffolder-react/src/next/components/TemplateCategoryPicker/TemplateCategoryPicker.test.tsx b/plugins/scaffolder-react/src/next/components/TemplateCategoryPicker/TemplateCategoryPicker.test.tsx index ce6e342809..f3a6a99c42 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCategoryPicker/TemplateCategoryPicker.test.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCategoryPicker/TemplateCategoryPicker.test.tsx @@ -20,6 +20,7 @@ import { TemplateCategoryPicker } from './TemplateCategoryPicker'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { alertApiRef } from '@backstage/core-plugin-api'; import { fireEvent } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; jest.mock('@backstage/plugin-catalog-react', () => ({ useEntityTypeFilter: jest.fn(), @@ -91,7 +92,7 @@ describe('TemplateCategoryPicker', () => { ); const openButton = getByRole('button', { name: 'Open' }); - openButton.click(); + await userEvent.click(openButton); expect(getByRole('checkbox', { name: 'Foo' })).toBeInTheDocument(); expect(getByRole('checkbox', { name: 'Bar' })).toBeInTheDocument(); diff --git a/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.test.tsx b/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.test.tsx index 894c6ea4d0..66c9d01ffd 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.test.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.test.tsx @@ -18,7 +18,7 @@ jest.mock('@backstage/plugin-catalog-react', () => ({ useEntityList: jest.fn(), })); -jest.mock('@backstage/plugin-scaffolder-react/alpha', () => ({ +jest.mock('../TemplateGroup/TemplateGroup', () => ({ TemplateGroup: jest.fn(() => null), })); @@ -27,7 +27,7 @@ import { useEntityList } from '@backstage/plugin-catalog-react'; import { TemplateGroups } from './TemplateGroups'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { errorApiRef } from '@backstage/core-plugin-api'; -import { TemplateGroup } from '@backstage/plugin-scaffolder-react/alpha'; +import { TemplateGroup } from '../TemplateGroup/TemplateGroup'; describe('TemplateGroups', () => { beforeEach(() => jest.clearAllMocks()); diff --git a/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.tsx b/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.tsx index f0f06b3410..800ec67a16 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateGroups/TemplateGroups.tsx @@ -23,15 +23,8 @@ import { import { Progress, Link } from '@backstage/core-components'; import { Typography } from '@material-ui/core'; import { errorApiRef, IconComponent, useApi } from '@backstage/core-plugin-api'; -import { TemplateGroup } from '@backstage/plugin-scaffolder-react/alpha'; - -/** - * @alpha - */ -export type TemplateGroupFilter = { - title?: React.ReactNode; - filter: (entity: TemplateEntityV1beta3) => boolean; -}; +import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react'; +import { TemplateGroup } from '../TemplateGroup/TemplateGroup'; /** * @alpha diff --git a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx index 228f5cefd9..e7c56378a7 100644 --- a/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx +++ b/plugins/scaffolder-react/src/next/components/Workflow/Workflow.tsx @@ -27,6 +27,7 @@ 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 { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; const useStyles = makeStyles<BackstageTheme>(() => ({ markdown: { @@ -48,11 +49,14 @@ export type WorkflowProps = { description?: string; namespace: string; templateName: string; + components?: { + ReviewStepComponent?: React.ComponentType<ReviewStepProps>; + }; onError(error: Error | undefined): JSX.Element | null; } & Pick< StepperProps, | 'extensions' - | 'FormProps' + | 'formProps' | 'components' | 'onCreate' | 'initialState' diff --git a/plugins/scaffolder-react/src/next/extensions/types.ts b/plugins/scaffolder-react/src/next/extensions/types.ts deleted file mode 100644 index 803dcb2be6..0000000000 --- a/plugins/scaffolder-react/src/next/extensions/types.ts +++ /dev/null @@ -1,84 +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. - */ -import { ApiHolder } from '@backstage/core-plugin-api'; -import { - UIOptionsType, - FieldProps as FieldPropsV5, - UiSchema as UiSchemaV5, - FieldValidation as FieldValidationV5, -} from '@rjsf/utils'; -import { PropsWithChildren } from 'react'; -import { JsonObject } from '@backstage/types'; -import { CustomFieldExtensionSchema } from '@backstage/plugin-scaffolder-react'; - -/** - * Type for Field Extension Props for RJSF v5 - * - * @alpha - */ -export interface NextFieldExtensionComponentProps< - TFieldReturnValue, - TUiOptions = {}, -> extends PropsWithChildren<FieldPropsV5<TFieldReturnValue>> { - uiSchema?: NextFieldExtensionUiSchema<TFieldReturnValue, TUiOptions>; -} - -/** - * Type for Field Extension UiSchema - * - * @alpha - */ -export interface NextFieldExtensionUiSchema<TFieldReturnValue, TUiOptions> - extends UiSchemaV5<TFieldReturnValue> { - 'ui:options'?: TUiOptions & UIOptionsType; -} - -/** - * Field validation type for Custom Field Extensions. - * - * @alpha - */ -export type NextCustomFieldValidator< - TFieldReturnValue, - TUiOptions = unknown, -> = ( - data: TFieldReturnValue, - field: FieldValidationV5, - context: { - apiHolder: ApiHolder; - formData: JsonObject; - schema: JsonObject; - uiSchema?: NextFieldExtensionUiSchema<TFieldReturnValue, TUiOptions>; - }, -) => void | Promise<void>; - -/** - * Type for the Custom Field Extension with the - * name and components and validation function. - * - * @alpha - */ -export type NextFieldExtensionOptions< - TFieldReturnValue = unknown, - TUiOptions = unknown, -> = { - name: string; - component: ( - props: NextFieldExtensionComponentProps<TFieldReturnValue, TUiOptions>, - ) => JSX.Element | null; - validation?: NextCustomFieldValidator<TFieldReturnValue, TUiOptions>; - schema?: CustomFieldExtensionSchema; -}; diff --git a/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.test.tsx b/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.test.tsx index 9a0732442c..d2771b2eb9 100644 --- a/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.test.tsx +++ b/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import { useTemplateSchema } from './useTemplateSchema'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { featureFlagsApiRef } from '@backstage/core-plugin-api'; diff --git a/plugins/scaffolder-react/src/next/hooks/useTransformSchemaToProps.test.tsx b/plugins/scaffolder-react/src/next/hooks/useTransformSchemaToProps.test.tsx index 7ee5cbfdfd..4138c8cde0 100644 --- a/plugins/scaffolder-react/src/next/hooks/useTransformSchemaToProps.test.tsx +++ b/plugins/scaffolder-react/src/next/hooks/useTransformSchemaToProps.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React, { PropsWithChildren } from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { TestApiProvider } from '@backstage/test-utils'; import { type ParsedTemplateSchema } from './useTemplateSchema'; import { useTransformSchemaToProps } from './useTransformSchemaToProps'; diff --git a/plugins/scaffolder-react/src/next/index.ts b/plugins/scaffolder-react/src/next/index.ts index a18649f506..f13bb76d7a 100644 --- a/plugins/scaffolder-react/src/next/index.ts +++ b/plugins/scaffolder-react/src/next/index.ts @@ -14,7 +14,5 @@ * limitations under the License. */ export * from './components'; -export * from './extensions'; -export * from './types'; export * from './lib'; export * from './hooks'; diff --git a/plugins/scaffolder-react/src/next/types.ts b/plugins/scaffolder-react/src/next/types.ts deleted file mode 100644 index 192fdf4146..0000000000 --- a/plugins/scaffolder-react/src/next/types.ts +++ /dev/null @@ -1,31 +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 type { FormProps as SchemaFormProps } from '@rjsf/core-v5'; - -// TODO(Rugvip): The FormProps type is actually supposed to be alpha, but since we want to -// refer to it from @backstage/plugin-scaffolder, it needs to be public for now. -// Once we support internal alpha re-exports this should be switched to an alpha export. - -/** - * Any `@rjsf/core` form properties that are publicly exposed to the `NextScaffolderpage` - * - * @alpha - */ -export type FormProps = Pick< - SchemaFormProps, - 'transformErrors' | 'noHtml5Validate' ->; diff --git a/plugins/scaffolder-react/src/secrets/SecretsContext.test.tsx b/plugins/scaffolder-react/src/secrets/SecretsContext.test.tsx index 553f27d2a9..4d56b5764c 100644 --- a/plugins/scaffolder-react/src/secrets/SecretsContext.test.tsx +++ b/plugins/scaffolder-react/src/secrets/SecretsContext.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; import { useTemplateSecrets, SecretsContextProvider } from './SecretsContext'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from '@testing-library/react'; describe('SecretsContext', () => { it('should allow the setting of secrets in the context', async () => { diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index 75417547a2..2f681837ea 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,56 @@ # @backstage/plugin-scaffolder +## 1.15.1 + +### Patch Changes + +- b337d78c3b: fixed issue related template editor fails with multiple templates per file. +- ff2ab02690: Make entity picker more reliable with only one available entity +- 83e4a42ccd: Display log visibility button on the template panel +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 4c70fe497d: `RepoUrlPickerRepoName` now correctly handles value changes in allowed repos. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-permission-react@0.4.16 + - @backstage/plugin-scaffolder-react@1.5.6 + - @backstage/theme@0.4.3 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-scaffolder-common@1.4.2 + +## 1.15.1-next.2 + +### Patch Changes + +- ff2ab02690: Make entity picker more reliable with only one available entity +- 83e4a42ccd: Display log visibility button on the template panel +- 4c70fe497d: `RepoUrlPickerRepoName` now correctly handles value changes in allowed repos. +- Updated dependencies + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-react@0.4.16-next.1 + - @backstage/plugin-scaffolder-common@1.4.2-next.0 + - @backstage/plugin-scaffolder-react@1.5.6-next.2 + ## 1.15.1-next.1 ### Patch Changes diff --git a/plugins/scaffolder/alpha-api-report.md b/plugins/scaffolder/alpha-api-report.md index 8cacf6105e..55d14bff75 100644 --- a/plugins/scaffolder/alpha-api-report.md +++ b/plugins/scaffolder/alpha-api-report.md @@ -5,50 +5,58 @@ ```ts /// <reference types="react" /> -import { FormProps as FormProps_2 } from '@backstage/plugin-scaffolder-react/alpha'; -import type { FormProps as FormProps_3 } from '@rjsf/core-v5'; +import { ComponentType } from 'react'; +import { Entity } from '@backstage/catalog-model'; +import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; +import type { FormProps as FormProps_2 } from '@rjsf/core'; +import { FormProps as FormProps_3 } from '@backstage/plugin-scaffolder-react'; import { JSX as JSX_2 } from 'react'; import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; -import { NextFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; -import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; +import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; -import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react/alpha'; +import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react'; // @alpha @deprecated export type FormProps = Pick< - FormProps_3, + FormProps_2, 'transformErrors' | 'noHtml5Validate' >; // @alpha -export type NextRouterProps = { +export const LegacyRouter: (props: LegacyRouterProps) => React_2.JSX.Element; + +// @alpha +export type LegacyRouterProps = { components?: { - TemplateCardComponent?: React_2.ComponentType<{ - template: TemplateEntityV1beta3; - }>; - TaskPageComponent?: React_2.ComponentType<PropsWithChildren<{}>>; - TemplateOutputsComponent?: React_2.ComponentType<{ - output?: ScaffolderTaskOutput; - }>; - TemplateListPageComponent?: React_2.ComponentType<TemplateListPageProps>; - TemplateWizardPageComponent?: React_2.ComponentType<TemplateWizardPageProps>; + ReviewStepComponent?: ComponentType<ReviewStepProps>; + TemplateCardComponent?: + | ComponentType<{ + template: TemplateEntityV1beta3; + }> + | undefined; + TaskPageComponent?: ComponentType<PropsWithChildren<{}>>; }; - groups?: TemplateGroupFilter[]; + groups?: Array<{ + title?: React_2.ReactNode; + filter: (entity: Entity) => boolean; + }>; templateFilter?: (entity: TemplateEntityV1beta3) => boolean; - FormProps?: FormProps_2; + defaultPreviewTemplate?: string; + headerOptions?: { + pageTitleOverride?: string; + title?: string; + subtitle?: string; + }; contextMenu?: { editor?: boolean; actions?: boolean; - tasks?: boolean; }; }; // @alpha -export const NextScaffolderPage: ( - props: PropsWithChildren<NextRouterProps>, -) => JSX_2.Element; +export const LegacyScaffolderPage: (props: LegacyRouterProps) => JSX_2.Element; // @alpha (undocumented) export type TemplateListPageProps = { @@ -66,9 +74,12 @@ export type TemplateListPageProps = { // @alpha (undocumented) export type TemplateWizardPageProps = { - customFieldExtensions: NextFieldExtensionOptions<any, any>[]; + customFieldExtensions: FieldExtensionOptions<any, any>[]; + components?: { + ReviewStepComponent?: React_2.ComponentType<ReviewStepProps>; + }; layouts?: LayoutOptions[]; - FormProps?: FormProps_2; + formProps?: FormProps_3; }; // (No @packageDocumentation comment for this package) diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index ddda40d95f..6f8479990b 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -14,15 +14,14 @@ import { createScaffolderLayout as createScaffolderLayout_2 } from '@backstage/p import { CustomFieldExtensionSchema as CustomFieldExtensionSchema_2 } from '@backstage/plugin-scaffolder-react'; import { CustomFieldValidator as CustomFieldValidator_2 } from '@backstage/plugin-scaffolder-react'; import { DiscoveryApi } from '@backstage/core-plugin-api'; -import { Entity } from '@backstage/catalog-model'; import { ExternalRouteRef } from '@backstage/core-plugin-api'; import { FetchApi } from '@backstage/core-plugin-api'; import { FieldExtensionComponent as FieldExtensionComponent_2 } from '@backstage/plugin-scaffolder-react'; import { FieldExtensionComponentProps as FieldExtensionComponentProps_2 } from '@backstage/plugin-scaffolder-react'; import { FieldExtensionOptions as FieldExtensionOptions_2 } from '@backstage/plugin-scaffolder-react'; -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; +import { FormProps } from '@backstage/plugin-scaffolder-react'; import { IdentityApi } from '@backstage/core-plugin-api'; -import { JsonObject } from '@backstage/types'; import { JSX as JSX_2 } from 'react'; import { LayoutOptions as LayoutOptions_2 } from '@backstage/plugin-scaffolder-react'; import { LayoutTemplate as LayoutTemplate_2 } from '@backstage/plugin-scaffolder-react'; @@ -33,6 +32,7 @@ import { PathParams } from '@backstage/core-plugin-api'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; +import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; import { RouteRef } from '@backstage/core-plugin-api'; import { ScaffolderApi as ScaffolderApi_2 } from '@backstage/plugin-scaffolder-react'; import { ScaffolderDryRunOptions as ScaffolderDryRunOptions_2 } from '@backstage/plugin-scaffolder-react'; @@ -50,8 +50,10 @@ import { ScaffolderUseTemplateSecrets as ScaffolderUseTemplateSecrets_2 } from ' import { ScmIntegrationRegistry } from '@backstage/integration'; import { SubRouteRef } from '@backstage/core-plugin-api'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; +import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react'; +import { TemplateListPageProps } from '@backstage/plugin-scaffolder/alpha'; import { TemplateParameterSchema as TemplateParameterSchema_2 } from '@backstage/plugin-scaffolder-react'; -import { UiSchema } from '@rjsf/utils'; +import { TemplateWizardPageProps } from '@backstage/plugin-scaffolder/alpha'; import { z } from 'zod'; // @public @deprecated (undocumented) @@ -419,19 +421,7 @@ export const RepoUrlPickerFieldSchema: FieldSchema< export type RepoUrlPickerUiOptions = typeof RepoUrlPickerFieldSchema.uiOptionsType; -// @public -export type ReviewStepProps = { - disableButtons: boolean; - formData: JsonObject; - handleBack: () => void; - handleReset: () => void; - handleCreate: () => void; - steps: { - uiSchema: UiSchema; - mergedSchema: JsonObject; - schema: JsonObject; - }[]; -}; +export { ReviewStepProps }; // @public @deprecated (undocumented) export const rootRouteRef: RouteRef<undefined>; @@ -439,28 +429,30 @@ export const rootRouteRef: RouteRef<undefined>; // @public export type RouterProps = { components?: { - ReviewStepComponent?: ComponentType<ReviewStepProps>; - TemplateCardComponent?: - | ComponentType<{ - template: TemplateEntityV1beta3; - }> - | undefined; - TaskPageComponent?: ComponentType<PropsWithChildren<{}>>; + ReviewStepComponent?: React_2.ComponentType<ReviewStepProps>; + TemplateCardComponent?: React_2.ComponentType<{ + template: TemplateEntityV1beta3; + }>; + TaskPageComponent?: React_2.ComponentType<PropsWithChildren<{}>>; + EXPERIMENTAL_TemplateOutputsComponent?: React_2.ComponentType<{ + output?: ScaffolderTaskOutput_2; + }>; + EXPERIMENTAL_TemplateListPageComponent?: React_2.ComponentType<TemplateListPageProps>; + EXPERIMENTAL_TemplateWizardPageComponent?: React_2.ComponentType<TemplateWizardPageProps>; }; - groups?: Array<{ - title?: React_2.ReactNode; - filter: (entity: Entity) => boolean; - }>; + groups?: TemplateGroupFilter[]; templateFilter?: (entity: TemplateEntityV1beta3) => boolean; - defaultPreviewTemplate?: string; headerOptions?: { pageTitleOverride?: string; title?: string; subtitle?: string; }; + defaultPreviewTemplate?: string; + formProps?: FormProps; contextMenu?: { editor?: boolean; actions?: boolean; + tasks?: boolean; }; }; @@ -537,7 +529,9 @@ export const ScaffolderLayouts: ComponentType<{ export type ScaffolderOutputlink = ScaffolderOutputLink; // @public -export const ScaffolderPage: (props: RouterProps) => JSX_2.Element; +export const ScaffolderPage: ( + props: PropsWithChildren<RouterProps>, +) => JSX_2.Element; // @public export const scaffolderPlugin: BackstagePlugin< @@ -585,10 +579,14 @@ export type ScaffolderTaskStatus = ScaffolderTaskStatus_2; // @public @deprecated (undocumented) export type ScaffolderUseTemplateSecrets = ScaffolderUseTemplateSecrets_2; -// @public -export const TaskPage: (props: TaskPageProps) => React_2.JSX.Element; +// @public (undocumented) +export const TaskPage: (props: { + TemplateOutputsComponent?: React_2.ComponentType<{ + output?: ScaffolderTaskOutput_2; + }>; +}) => React_2.JSX.Element; -// @public +// @public @deprecated export type TaskPageProps = { loadingText?: string; }; diff --git a/plugins/scaffolder/dev/index.tsx b/plugins/scaffolder/dev/index.tsx index 68c59eec2d..b683345ff5 100644 --- a/plugins/scaffolder/dev/index.tsx +++ b/plugins/scaffolder/dev/index.tsx @@ -24,7 +24,7 @@ import { } from '@backstage/plugin-catalog-react'; import React from 'react'; import { scaffolderApiRef, ScaffolderClient } from '../src'; -import { NextScaffolderPage, ScaffolderPage } from '../src/plugin'; +import { ScaffolderPage, LegacyScaffolderPage } from '../src/plugin'; import { discoveryApiRef, fetchApiRef, @@ -69,9 +69,9 @@ createDevApp() element: <ScaffolderPage />, }) .addPage({ - path: '/next-create', + path: '/legacy-create', title: 'Create (next)', - element: <NextScaffolderPage />, + element: <LegacyScaffolderPage />, }) .addPage({ path: '/create-groups', @@ -92,10 +92,10 @@ createDevApp() ), }) .addPage({ - path: '/next-create-groups', + path: '/legacy-create-groups', title: 'Groups (next)', element: ( - <NextScaffolderPage + <LegacyScaffolderPage groups={[ { filter: e => e.metadata.tags?.includes('techdocs') || false, diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 841e6d61d6..d36ce86acc 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.15.1-next.1", + "version": "1.15.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -68,8 +68,8 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", "@react-hookz/web": "^20.0.0", - "@rjsf/core": "^3.2.1", - "@rjsf/material-ui": "^3.2.1", + "@rjsf/core": "5.13.0", + "@rjsf/material-ui": "5.13.0", "@rjsf/utils": "5.13.0", "@rjsf/validator-ajv8": "5.13.0", "@types/react": "^16.13.1 || ^17.0.0", @@ -92,8 +92,8 @@ "zod-to-json-schema": "^3.20.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -102,10 +102,9 @@ "@backstage/dev-utils": "workspace:^", "@backstage/plugin-catalog": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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/humanize-duration": "^3.18.1", "@types/json-schema": "^7.0.9", diff --git a/plugins/scaffolder/src/alpha.ts b/plugins/scaffolder/src/alpha.ts index d2bd762190..92ec945de4 100644 --- a/plugins/scaffolder/src/alpha.ts +++ b/plugins/scaffolder/src/alpha.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -export { NextScaffolderPage } from './plugin'; export { - type NextRouterProps, type FormProps, type TemplateListPageProps, type TemplateWizardPageProps, } from './next'; + +export * from './legacy'; diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx index a402e078a8..614e3fcff0 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx @@ -22,6 +22,7 @@ import { import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import { ApiProvider } from '@backstage/core-app-api'; import { rootRouteRef } from '../../routes'; +import { userEvent } from '@testing-library/user-event'; const scaffolderApiMock: jest.Mocked<ScaffolderApi> = { scaffold: jest.fn(), @@ -261,7 +262,7 @@ describe('TemplatePage', () => { expect(rendered.queryByText('nested prop b')).not.toBeInTheDocument(); expect(rendered.queryByText('number')).not.toBeInTheDocument(); - objectChip.click(); + await userEvent.click(objectChip); expect(rendered.queryByText('nested prop a')).toBeInTheDocument(); expect(rendered.queryByText('string')).toBeInTheDocument(); @@ -323,7 +324,7 @@ describe('TemplatePage', () => { expect(rendered.queryByText('nested prop b')).not.toBeInTheDocument(); expect(rendered.queryByText('nested object c')).not.toBeInTheDocument(); - objectChip.click(); + await userEvent.click(objectChip); expect(rendered.queryByText('nested object a')).toBeInTheDocument(); expect(rendered.queryByText('nested prop b')).toBeInTheDocument(); @@ -331,7 +332,7 @@ describe('TemplatePage', () => { const allObjectChips = rendered.getAllByText('object'); expect(allObjectChips.length).toBe(2); - allObjectChips[1].click(); + await userEvent.click(allObjectChips[1]); expect(rendered.queryByText('nested object a')).toBeInTheDocument(); expect(rendered.queryByText('nested prop b')).toBeInTheDocument(); @@ -374,7 +375,7 @@ describe('TemplatePage', () => { expect(rendered.queryByText('No schema defined')).not.toBeInTheDocument(); - objectChip.click(); + await userEvent.click(objectChip); expect(rendered.queryByText('No schema defined')).toBeInTheDocument(); }); @@ -471,7 +472,7 @@ describe('TemplatePage', () => { expect(rendered.queryByText('nested object a')).not.toBeInTheDocument(); expect(rendered.queryByText('nested prop b')).not.toBeInTheDocument(); - objectChip.click(); + await userEvent.click(objectChip); expect(rendered.queryByText('nested object a')).toBeInTheDocument(); expect(rendered.queryByText('nested prop b')).toBeInTheDocument(); diff --git a/plugins/scaffolder/src/next/OngoingTask/ContextMenu.tsx b/plugins/scaffolder/src/components/OngoingTask/ContextMenu.tsx similarity index 100% rename from plugins/scaffolder/src/next/OngoingTask/ContextMenu.tsx rename to plugins/scaffolder/src/components/OngoingTask/ContextMenu.tsx diff --git a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.test.tsx b/plugins/scaffolder/src/components/OngoingTask/OngoingTask.test.tsx similarity index 100% rename from plugins/scaffolder/src/next/OngoingTask/OngoingTask.test.tsx rename to plugins/scaffolder/src/components/OngoingTask/OngoingTask.test.tsx diff --git a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx b/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx similarity index 99% rename from plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx rename to plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx index b483cd27cb..cc988599a0 100644 --- a/plugins/scaffolder/src/next/OngoingTask/OngoingTask.tsx +++ b/plugins/scaffolder/src/components/OngoingTask/OngoingTask.tsx @@ -51,6 +51,9 @@ const useStyles = makeStyles(theme => ({ }, })); +/** + * @public + */ export const OngoingTask = (props: { TemplateOutputsComponent?: React.ComponentType<{ output?: ScaffolderTaskOutput; diff --git a/plugins/scaffolder/src/next/OngoingTask/index.ts b/plugins/scaffolder/src/components/OngoingTask/index.ts similarity index 100% rename from plugins/scaffolder/src/next/OngoingTask/index.ts rename to plugins/scaffolder/src/components/OngoingTask/index.ts diff --git a/plugins/scaffolder/src/next/Router/Router.test.tsx b/plugins/scaffolder/src/components/Router/Router.test.tsx similarity index 91% rename from plugins/scaffolder/src/next/Router/Router.test.tsx rename to plugins/scaffolder/src/components/Router/Router.test.tsx index 3d52dd0dd0..8c301b55fb 100644 --- a/plugins/scaffolder/src/next/Router/Router.test.tsx +++ b/plugins/scaffolder/src/components/Router/Router.test.tsx @@ -14,8 +14,6 @@ * limitations under the License. */ import React from 'react'; -import { TemplateListPage } from '../TemplateListPage'; -import { TemplateWizardPage } from '../TemplateWizardPage'; import { Router } from './Router'; import { renderInTestApp } from '@backstage/test-utils'; import { @@ -27,13 +25,11 @@ import { createScaffolderLayout, ScaffolderLayouts, } from '@backstage/plugin-scaffolder-react'; +import { TemplateListPage, TemplateWizardPage } from '../../next'; -jest.mock('../TemplateListPage', () => ({ - TemplateListPage: jest.fn(() => null), -})); - -jest.mock('../TemplateWizardPage', () => ({ +jest.mock('../../next', () => ({ TemplateWizardPage: jest.fn(() => null), + TemplateListPage: jest.fn(() => null), })); describe('Router', () => { @@ -52,7 +48,7 @@ describe('Router', () => { const { getByText } = await renderInTestApp( <Router components={{ - TemplateListPageComponent: () => <>foobar</>, + EXPERIMENTAL_TemplateListPageComponent: () => <>foobar</>, }} />, { @@ -77,7 +73,7 @@ describe('Router', () => { const { getByText } = await renderInTestApp( <Router components={{ - TemplateWizardPageComponent: () => <>foobar</>, + EXPERIMENTAL_TemplateWizardPageComponent: () => <>foobar</>, }} />, { @@ -93,7 +89,7 @@ describe('Router', () => { await renderInTestApp( <Router - FormProps={{ + formProps={{ transformErrors: transformErrorsMock, noHtml5Validate: true, }} @@ -105,9 +101,9 @@ describe('Router', () => { const mock = TemplateWizardPage as jest.Mock; - const [{ FormProps }] = mock.mock.calls[0]; + const [{ formProps }] = mock.mock.calls[0]; - expect(FormProps).toEqual({ + expect(formProps).toEqual({ transformErrors: transformErrorsMock, noHtml5Validate: true, }); diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/components/Router/Router.tsx similarity index 74% rename from plugins/scaffolder/src/next/Router/Router.tsx rename to plugins/scaffolder/src/components/Router/Router.tsx index 2061cd1243..dede51d676 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/components/Router/Router.tsx @@ -15,16 +15,13 @@ */ import React, { PropsWithChildren } from 'react'; import { Routes, Route, useOutlet } from 'react-router-dom'; -import { TemplateListPage, TemplateListPageProps } from '../TemplateListPage'; + import { - TemplateWizardPage, - TemplateWizardPageProps, -} from '../TemplateWizardPage'; -import { - NextFieldExtensionOptions, + FieldExtensionOptions, FormProps, + ReviewStepProps, TemplateGroupFilter, -} from '@backstage/plugin-scaffolder-react/alpha'; +} from '@backstage/plugin-scaffolder-react'; import { ScaffolderTaskOutput, SecretsContextProvider, @@ -43,32 +40,45 @@ import { selectedTemplateRouteRef, } from '../../routes'; import { ErrorPage } from '@backstage/core-components'; -import { OngoingTask } from '../OngoingTask'; + import { ActionsPage } from '../../components/ActionsPage'; import { ListTasksPage } from '../../components/ListTasksPage'; -import { TemplateEditorPage } from '../TemplateEditorPage'; + +import { + TemplateListPageProps, + TemplateWizardPageProps, +} from '@backstage/plugin-scaffolder/alpha'; +import { TemplateListPage, TemplateWizardPage } from '../../next'; +import { OngoingTask } from '../OngoingTask'; +import { TemplateEditorPage } from '../../next/TemplateEditorPage'; /** * The Props for the Scaffolder Router * - * @alpha + * @public */ -export type NextRouterProps = { +export type RouterProps = { components?: { + ReviewStepComponent?: React.ComponentType<ReviewStepProps>; TemplateCardComponent?: React.ComponentType<{ template: TemplateEntityV1beta3; }>; TaskPageComponent?: React.ComponentType<PropsWithChildren<{}>>; - TemplateOutputsComponent?: React.ComponentType<{ + EXPERIMENTAL_TemplateOutputsComponent?: React.ComponentType<{ output?: ScaffolderTaskOutput; }>; - TemplateListPageComponent?: React.ComponentType<TemplateListPageProps>; - TemplateWizardPageComponent?: React.ComponentType<TemplateWizardPageProps>; + EXPERIMENTAL_TemplateListPageComponent?: React.ComponentType<TemplateListPageProps>; + EXPERIMENTAL_TemplateWizardPageComponent?: React.ComponentType<TemplateWizardPageProps>; }; groups?: TemplateGroupFilter[]; templateFilter?: (entity: TemplateEntityV1beta3) => boolean; - // todo(blam): rename this to formProps - FormProps?: FormProps; + headerOptions?: { + pageTitleOverride?: string; + title?: string; + subtitle?: string; + }; + defaultPreviewTemplate?: string; + formProps?: FormProps; contextMenu?: { /** Whether to show a link to the template editor */ editor?: boolean; @@ -82,21 +92,24 @@ export type NextRouterProps = { /** * The Scaffolder Router * - * @alpha + * @public */ -export const Router = (props: PropsWithChildren<NextRouterProps>) => { +export const Router = (props: PropsWithChildren<RouterProps>) => { const { components: { TemplateCardComponent, - TemplateOutputsComponent, TaskPageComponent = OngoingTask, - TemplateListPageComponent = TemplateListPage, - TemplateWizardPageComponent = TemplateWizardPage, + ReviewStepComponent, + EXPERIMENTAL_TemplateOutputsComponent: TemplateOutputsComponent, + EXPERIMENTAL_TemplateListPageComponent: + TemplateListPageComponent = TemplateListPage, + EXPERIMENTAL_TemplateWizardPageComponent: + TemplateWizardPageComponent = TemplateWizardPage, } = {}, } = props; const outlet = useOutlet() || props.children; const customFieldExtensions = - useCustomFieldExtensions<NextFieldExtensionOptions>(outlet); + useCustomFieldExtensions<FieldExtensionOptions>(outlet); const fieldExtensions = [ ...customFieldExtensions, @@ -106,7 +119,7 @@ export const Router = (props: PropsWithChildren<NextRouterProps>) => { customFieldExtension => customFieldExtension.name === name, ), ), - ] as NextFieldExtensionOptions[]; + ] as FieldExtensionOptions[]; const customLayouts = useCustomLayouts(outlet); @@ -130,7 +143,8 @@ export const Router = (props: PropsWithChildren<NextRouterProps>) => { <TemplateWizardPageComponent customFieldExtensions={fieldExtensions} layouts={customLayouts} - FormProps={props.FormProps} + components={{ ReviewStepComponent }} + formProps={props.formProps} /> </SecretsContextProvider> } diff --git a/plugins/scaffolder/src/next/Router/index.ts b/plugins/scaffolder/src/components/Router/index.ts similarity index 87% rename from plugins/scaffolder/src/next/Router/index.ts rename to plugins/scaffolder/src/components/Router/index.ts index dac1db7b3a..afe51fbdc9 100644 --- a/plugins/scaffolder/src/next/Router/index.ts +++ b/plugins/scaffolder/src/components/Router/index.ts @@ -13,5 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { Router } from './Router'; -export type { NextRouterProps } from './Router'; +export { Router, type RouterProps } from './Router'; diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.test.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.test.tsx deleted file mode 100644 index bf9cd8c464..0000000000 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.test.tsx +++ /dev/null @@ -1,58 +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 { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import React from 'react'; -import { TemplateEditorPage } from './TemplateEditorPage'; - -describe('TemplateEditorPage', () => { - it('renders without exploding', async () => { - await renderInTestApp(<TemplateEditorPage />); - - expect(screen.getByText('Load Template Directory')).toBeInTheDocument(); - expect(screen.getByText('Edit Template Form')).toBeInTheDocument(); - }); - - it('template directory loading should not be supported in Jest', async () => { - await renderInTestApp(<TemplateEditorPage />); - - expect( - screen.getByRole('button', { name: /Load Template Directory/ }), - ).toBeDisabled(); - }); - - it('should be able to continue to form preview', async () => { - await renderInTestApp( - <TestApiProvider - apis={[ - [ - catalogApiRef, - { getEntities: jest.fn().mockResolvedValue({ items: [] }) }, - ], - ]} - > - <TemplateEditorPage /> - </TestApiProvider>, - ); - - await userEvent.click(screen.getByText('Edit Template Form')); - - expect(screen.getByLabelText('Load Existing Template')).toBeInTheDocument(); - }); -}); diff --git a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts index 290650387e..7201c9c4b3 100644 --- a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts +++ b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; import { KubernetesValidatorFunctions } from '@backstage/catalog-model'; import { entityNamePickerValidation } from './validation'; diff --git a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts index d116bef228..9302e9abc1 100644 --- a/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts +++ b/plugins/scaffolder/src/components/fields/EntityNamePicker/validation.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; import { KubernetesValidatorFunctions } from '@backstage/catalog-model'; export const entityNamePickerValidation = ( diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx index cbc587a732..4329b2208b 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx @@ -18,11 +18,12 @@ import { CATALOG_FILTER_EXISTS } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { FieldProps } from '@rjsf/core'; + import { fireEvent, screen } from '@testing-library/react'; import React from 'react'; import { EntityPicker } from './EntityPicker'; import { EntityPickerProps } from './schema'; +import { ScaffolderRJSFFieldProps as FieldProps } from '@backstage/plugin-scaffolder-react'; const makeEntity = (kind: string, namespace: string, name: string): Entity => ({ apiVersion: 'scaffolder.backstage.io/v1beta3', @@ -39,7 +40,7 @@ describe('<EntityPicker />', () => { const rawErrors: string[] = []; const formData = undefined; - let props: FieldProps; + let props: FieldProps<string>; const catalogApi: jest.Mocked<CatalogApi> = { getLocationById: jest.fn(), @@ -76,7 +77,7 @@ describe('<EntityPicker />', () => { uiSchema, rawErrors, formData, - } as unknown as FieldProps<any>; + } as unknown as FieldProps; catalogApi.getEntities.mockResolvedValue({ items: entities }); }); diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx index 0f698919d5..0d45fe771c 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx @@ -123,11 +123,17 @@ export const EntityPicker = (props: EntityPickerProps) => { [onChange, formData, defaultKind, defaultNamespace, allowArbitraryValues], ); + // Since free solo can be enabled, attempt to parse as a full entity ref first, then fall + // back to the given value. + const selectedEntity = + entities?.find(e => stringifyEntityRef(e) === formData) ?? + (allowArbitraryValues && formData ? getLabel(formData) : ''); + useEffect(() => { - if (entities?.length === 1) { + if (entities?.length === 1 && selectedEntity === '') { onChange(stringifyEntityRef(entities[0])); } - }, [entities, onChange]); + }, [entities, onChange, selectedEntity]); return ( <FormControl @@ -138,12 +144,7 @@ export const EntityPicker = (props: EntityPickerProps) => { <Autocomplete disabled={entities?.length === 1} id={idSchema?.$id} - value={ - // Since free solo can be enabled, attempt to parse as a full entity ref first, then fall - // back to the given value. - entities?.find(e => stringifyEntityRef(e) === formData) ?? - (allowArbitraryValues && formData ? getLabel(formData) : '') - } + value={selectedEntity} loading={loading} onChange={onSelect} options={entities || []} diff --git a/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx b/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx index 099d6fa6ed..521c4029b3 100644 --- a/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/MyGroupsPicker/MyGroupsPicker.test.tsx @@ -17,7 +17,6 @@ import React from 'react'; import { render, waitFor } from '@testing-library/react'; import { CatalogApi } from '@backstage/catalog-client'; -import { FieldProps } from '@rjsf/core'; import { MyGroupsPicker } from './MyGroupsPicker'; import { TestApiProvider } from '@backstage/test-utils'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; @@ -29,6 +28,7 @@ import { identityApiRef, } from '@backstage/core-plugin-api'; import userEvent from '@testing-library/user-event'; +import { ScaffolderRJSFFieldProps as FieldProps } from '@backstage/plugin-scaffolder-react'; // Create a mock IdentityApi const mockIdentityApi: IdentityApi = { @@ -109,7 +109,7 @@ describe('<MyGroupsPicker />', () => { onChange, schema, required, - } as unknown as FieldProps<any>; + } as unknown as FieldProps<string>; render( <TestApiProvider @@ -181,7 +181,7 @@ describe('<MyGroupsPicker />', () => { onChange, schema, required, - } as unknown as FieldProps<any>; + } as unknown as FieldProps<string>; const { queryByText, getByRole } = render( <TestApiProvider @@ -238,7 +238,7 @@ describe('<MyGroupsPicker />', () => { onChange, schema, required, - } as unknown as FieldProps<any>; + } as unknown as FieldProps<string>; const { getByRole } = render( <TestApiProvider diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx index 1d843ea8a2..3c948b8261 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx @@ -18,7 +18,7 @@ import { type EntityFilterQuery } from '@backstage/catalog-client'; import { Entity } from '@backstage/catalog-model'; import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { FieldProps } from '@rjsf/core'; +import { ScaffolderRJSFFieldProps as FieldProps } from '@backstage/plugin-scaffolder-react'; import React from 'react'; import { OwnerPicker } from './OwnerPicker'; @@ -45,7 +45,7 @@ describe('<OwnerPicker />', () => { const rawErrors: string[] = []; const formData = undefined; - let props: FieldProps; + let props: FieldProps<string>; const catalogApi: jest.Mocked<CatalogApi> = { getLocationById: jest.fn(), diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx index 4b44a4fa3e..da86e6e4b8 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx @@ -15,7 +15,8 @@ */ import React from 'react'; import { RepoUrlPicker } from './RepoUrlPicker'; -import Form from '@rjsf/core'; +import { Form } from '@backstage/plugin-scaffolder-react/alpha'; +import validator from '@rjsf/validator-ajv8'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { scmIntegrationsApiRef, @@ -29,6 +30,7 @@ import { scaffolderApiRef, ScaffolderApi, useTemplateSecrets, + ScaffolderRJSFField, } from '@backstage/plugin-scaffolder-react'; import { act, fireEvent } from '@testing-library/react'; @@ -73,9 +75,12 @@ describe('RepoUrlPicker', () => { > <SecretsContextProvider> <Form + validator={validator} schema={{ type: 'string' }} uiSchema={{ 'ui:field': 'RepoUrlPicker' }} - fields={{ RepoUrlPicker: RepoUrlPicker }} + fields={{ + RepoUrlPicker: RepoUrlPicker as ScaffolderRJSFField<string>, + }} onSubmit={onSubmit} /> </SecretsContextProvider> @@ -109,12 +114,15 @@ describe('RepoUrlPicker', () => { > <SecretsContextProvider> <Form + validator={validator} schema={{ type: 'string' }} uiSchema={{ 'ui:field': 'RepoUrlPicker', 'ui:options': { allowedHosts: ['dev.azure.com'] }, }} - fields={{ RepoUrlPicker: RepoUrlPicker }} + fields={{ + RepoUrlPicker: RepoUrlPicker as ScaffolderRJSFField<string>, + }} /> </SecretsContextProvider> </TestApiProvider>, @@ -144,6 +152,7 @@ describe('RepoUrlPicker', () => { > <SecretsContextProvider> <Form + validator={validator} schema={{ type: 'string' }} uiSchema={{ 'ui:field': 'RepoUrlPicker', @@ -154,7 +163,9 @@ describe('RepoUrlPicker', () => { }, }, }} - fields={{ RepoUrlPicker: RepoUrlPicker }} + fields={{ + RepoUrlPicker: RepoUrlPicker as ScaffolderRJSFField<string>, + }} /> <SecretsComponent /> </SecretsContextProvider> @@ -206,6 +217,7 @@ describe('RepoUrlPicker', () => { > <SecretsContextProvider> <Form + validator={validator} schema={{ type: 'string' }} uiSchema={{ 'ui:field': 'RepoUrlPicker', @@ -216,7 +228,9 @@ describe('RepoUrlPicker', () => { }, }, }} - fields={{ RepoUrlPicker: RepoUrlPicker }} + fields={{ + RepoUrlPicker: RepoUrlPicker as ScaffolderRJSFField<string>, + }} /> <SecretsComponent /> </SecretsContextProvider> @@ -259,6 +273,7 @@ describe('RepoUrlPicker', () => { > <SecretsContextProvider> <Form + validator={validator} schema={{ type: 'string' }} uiSchema={{ 'ui:field': 'RepoUrlPicker', @@ -269,7 +284,9 @@ describe('RepoUrlPicker', () => { }, }, }} - fields={{ RepoUrlPicker: RepoUrlPicker }} + fields={{ + RepoUrlPicker: RepoUrlPicker as ScaffolderRJSFField<string>, + }} /> <SecretsComponent /> </SecretsContextProvider> diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx index 1393b1902e..f2d68b08f3 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.tsx @@ -54,7 +54,7 @@ export const RepoUrlPickerRepoName = (props: { native label="Repositories Available" onChange={selected => - String(Array.isArray(selected) ? selected[0] : selected) + onChange(String(Array.isArray(selected) ? selected[0] : selected)) } disabled={allowedRepos.length === 1} selected={repoName} diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts index 45e44b4072..b9c481957c 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts @@ -15,7 +15,7 @@ */ import { repoPickerValidation } from './validation'; -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/core-app-api'; import { ApiHolder } from '@backstage/core-plugin-api'; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts index 99847f9e3b..55ba92abdc 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { FieldValidation } from '@rjsf/core'; +import { FieldValidation } from '@rjsf/utils'; import { ApiHolder } from '@backstage/core-plugin-api'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; diff --git a/plugins/scaffolder/src/components/index.ts b/plugins/scaffolder/src/components/index.ts index a5c17b8ab0..fd8c11e2da 100644 --- a/plugins/scaffolder/src/components/index.ts +++ b/plugins/scaffolder/src/components/index.ts @@ -15,7 +15,12 @@ */ export * from './fields'; export type { RepoUrlPickerUiOptions } from './fields'; + export { TemplateTypePicker } from './TemplateTypePicker'; -export { TaskPage, type TaskPageProps } from './TaskPage'; + export type { RouterProps } from './Router'; -export type { ReviewStepProps } from './types'; +export { OngoingTask as TaskPage } from './OngoingTask'; + +export type { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; + +export type { TaskPageProps } from '../legacy/TaskPage'; diff --git a/plugins/scaffolder/src/components/types.ts b/plugins/scaffolder/src/components/types.ts index f5989a2ae1..b1e99a84e6 100644 --- a/plugins/scaffolder/src/components/types.ts +++ b/plugins/scaffolder/src/components/types.ts @@ -13,25 +13,3 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import { UiSchema } from '@rjsf/utils'; -import { JsonObject } from '@backstage/types'; - -/** - * The props for the Last Step in scaffolder template form. - * Which represents the summary of the input provided by the end user. - * - * @public - */ -export type ReviewStepProps = { - disableButtons: boolean; - formData: JsonObject; - handleBack: () => void; - handleReset: () => void; - handleCreate: () => void; - steps: { - uiSchema: UiSchema; - mergedSchema: JsonObject; - schema: JsonObject; - }[]; -}; diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/DescriptionField.tsx b/plugins/scaffolder/src/legacy/MultistepJsonForm/FieldOverrides/DescriptionField.tsx similarity index 95% rename from plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/DescriptionField.tsx rename to plugins/scaffolder/src/legacy/MultistepJsonForm/FieldOverrides/DescriptionField.tsx index 3c592860ef..eded38beee 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/DescriptionField.tsx +++ b/plugins/scaffolder/src/legacy/MultistepJsonForm/FieldOverrides/DescriptionField.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { MarkdownContent } from '@backstage/core-components'; -import { FieldProps } from '@rjsf/core'; +import { FieldProps } from '@rjsf/utils'; export const DescriptionField = ({ description }: FieldProps) => description && <MarkdownContent content={description} linkTarget="_blank" />; diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/index.ts b/plugins/scaffolder/src/legacy/MultistepJsonForm/FieldOverrides/index.ts similarity index 100% rename from plugins/scaffolder/src/components/MultistepJsonForm/FieldOverrides/index.ts rename to plugins/scaffolder/src/legacy/MultistepJsonForm/FieldOverrides/index.ts diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.test.tsx b/plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.test.tsx rename to plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.test.tsx diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.tsx similarity index 96% rename from plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx rename to plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.tsx index ec95bad0e5..312522bc88 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/legacy/MultistepJsonForm/MultistepJsonForm.tsx @@ -35,11 +35,14 @@ import React, { ComponentType, useState } from 'react'; import { transformSchemaToProps } from './schema'; import cloneDeep from 'lodash/cloneDeep'; import * as fieldOverrides from './FieldOverrides'; -import { ReviewStepProps } from '../types'; import { ReviewStep } from './ReviewStep'; +import validator from '@rjsf/validator-ajv8'; import { extractSchemaFromStep } from '@backstage/plugin-scaffolder-react/alpha'; import { selectedTemplateRouteRef } from '../../routes'; -import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { + LayoutOptions, + ReviewStepProps, +} from '@backstage/plugin-scaffolder-react'; const Form = withTheme(MuiTheme); @@ -178,6 +181,7 @@ export const MultistepJsonForm = (props: MultistepJsonFormProps) => { </StepLabel> <StepContent key={title}> <Form + validator={validator} showErrorList={false} fields={{ ...fieldOverrides, ...fields }} widgets={widgets} @@ -185,7 +189,7 @@ export const MultistepJsonForm = (props: MultistepJsonFormProps) => { formData={formData} formContext={{ formData }} onChange={onChange} - onSubmit={e => { + onSubmit={(e: IChangeEvent<any>) => { if (e.errors.length === 0) handleNext(); }} {...formProps} diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/ReviewStep.tsx b/plugins/scaffolder/src/legacy/MultistepJsonForm/ReviewStep.tsx similarity index 96% rename from plugins/scaffolder/src/components/MultistepJsonForm/ReviewStep.tsx rename to plugins/scaffolder/src/legacy/MultistepJsonForm/ReviewStep.tsx index 112b96bdf1..c3b244e921 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/ReviewStep.tsx +++ b/plugins/scaffolder/src/legacy/MultistepJsonForm/ReviewStep.tsx @@ -16,9 +16,9 @@ import { Box, Button, Paper, Typography } from '@material-ui/core'; import React from 'react'; import { Content, StructuredMetadataTable } from '@backstage/core-components'; -import { UiSchema } from '@rjsf/core'; +import { UiSchema } from '@rjsf/utils'; import { JsonObject } from '@backstage/types'; -import { ReviewStepProps } from '../types'; +import { ReviewStepProps } from '@backstage/plugin-scaffolder-react'; export function getReviewData( formData: Record<string, any>, diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/index.ts b/plugins/scaffolder/src/legacy/MultistepJsonForm/index.ts similarity index 100% rename from plugins/scaffolder/src/components/MultistepJsonForm/index.ts rename to plugins/scaffolder/src/legacy/MultistepJsonForm/index.ts diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts b/plugins/scaffolder/src/legacy/MultistepJsonForm/schema.test.ts similarity index 100% rename from plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts rename to plugins/scaffolder/src/legacy/MultistepJsonForm/schema.test.ts diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts b/plugins/scaffolder/src/legacy/MultistepJsonForm/schema.ts similarity index 95% rename from plugins/scaffolder/src/components/MultistepJsonForm/schema.ts rename to plugins/scaffolder/src/legacy/MultistepJsonForm/schema.ts index c3c90ae86a..e6221cb8d5 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts +++ b/plugins/scaffolder/src/legacy/MultistepJsonForm/schema.ts @@ -15,8 +15,9 @@ */ import { JsonObject } from '@backstage/types'; -import { FormProps, UiSchema } from '@rjsf/core'; +import { UiSchema } from '@rjsf/utils'; import type { LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { FormProps } from '@rjsf/core'; function isObject(value: unknown): value is JsonObject { return typeof value === 'object' && value !== null && !Array.isArray(value); @@ -120,8 +121,7 @@ export function transformSchemaToProps( )?.component; if (Layout) { - uiSchema['ui:ObjectFieldTemplate'] = - Layout as unknown as FormProps<any>['ObjectFieldTemplate']; + uiSchema['ui:ObjectFieldTemplate'] = Layout; } } diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/legacy/Router.tsx similarity index 91% rename from plugins/scaffolder/src/components/Router.tsx rename to plugins/scaffolder/src/legacy/Router.tsx index 3ceda359cc..ac183b9470 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/legacy/Router.tsx @@ -21,18 +21,17 @@ import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { ScaffolderPage } from './ScaffolderPage'; import { TemplatePage } from './TemplatePage'; import { TaskPage } from './TaskPage'; -import { ActionsPage } from './ActionsPage'; -import { TemplateEditorPage } from './TemplateEditorPage'; +import { ActionsPage } from '../components/ActionsPage'; import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../extensions/default'; import { useRouteRef, useRouteRefParams } from '@backstage/core-plugin-api'; +import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; import { - FieldExtensionOptions, + ReviewStepProps, SecretsContextProvider, useCustomFieldExtensions, useCustomLayouts, } from '@backstage/plugin-scaffolder-react'; -import { ListTasksPage } from './ListTasksPage'; -import { ReviewStepProps } from './types'; +import { ListTasksPage } from '../components/ListTasksPage'; import { actionsRouteRef, editRouteRef, @@ -41,12 +40,13 @@ import { scaffolderTaskRouteRef, selectedTemplateRouteRef, } from '../routes'; +import { TemplateEditorPage } from './TemplateEditorPage'; /** * The props for the entrypoint `ScaffolderPage` component the plugin. - * @public + * @alpha */ -export type RouterProps = { +export type LegacyRouterProps = { components?: { ReviewStepComponent?: ComponentType<ReviewStepProps>; TemplateCardComponent?: @@ -77,11 +77,11 @@ export type RouterProps = { }; /** - * The main entrypoint `Router` for the `ScaffolderPlugin`. + * The legacy router * - * @public + * @alpha */ -export const Router = (props: RouterProps) => { +export const LegacyRouter = (props: LegacyRouterProps) => { const { groups, templateFilter, @@ -95,7 +95,9 @@ export const Router = (props: RouterProps) => { const outlet = useOutlet(); const TaskPageElement = TaskPageComponent ?? TaskPage; - const customFieldExtensions = useCustomFieldExtensions(outlet); + const customFieldExtensions = + useCustomFieldExtensions<LegacyFieldExtensionOptions>(outlet); + const fieldExtensions = [ ...customFieldExtensions, ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter( @@ -104,7 +106,7 @@ export const Router = (props: RouterProps) => { customFieldExtension => customFieldExtension.name === name, ), ), - ] as FieldExtensionOptions[]; + ] as LegacyFieldExtensionOptions[]; const customLayouts = useCustomLayouts(outlet); diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPage.tsx similarity index 98% rename from plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx rename to plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPage.tsx index 40435573e9..54122eddf0 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPage.tsx @@ -34,11 +34,11 @@ import { } from '@backstage/plugin-catalog-react'; import React, { ComponentType } from 'react'; import { TemplateList } from '../TemplateList'; -import { TemplateTypePicker } from '../TemplateTypePicker'; import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha'; import { usePermission } from '@backstage/plugin-permission-react'; import { ScaffolderPageContextMenu } from './ScaffolderPageContextMenu'; import { registerComponentRouteRef } from '../../routes'; +import { TemplateTypePicker } from '../../components'; export type ScaffolderPageProps = { TemplateCardComponent?: diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.test.tsx b/plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPageContextMenu.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.test.tsx rename to plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPageContextMenu.test.tsx diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.tsx b/plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPageContextMenu.tsx similarity index 100% rename from plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.tsx rename to plugins/scaffolder/src/legacy/ScaffolderPage/ScaffolderPageContextMenu.tsx diff --git a/plugins/scaffolder/src/components/ScaffolderPage/index.ts b/plugins/scaffolder/src/legacy/ScaffolderPage/index.ts similarity index 100% rename from plugins/scaffolder/src/components/ScaffolderPage/index.ts rename to plugins/scaffolder/src/legacy/ScaffolderPage/index.ts diff --git a/plugins/scaffolder/src/components/TaskPage/IconLink.test.tsx b/plugins/scaffolder/src/legacy/TaskPage/IconLink.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/TaskPage/IconLink.test.tsx rename to plugins/scaffolder/src/legacy/TaskPage/IconLink.test.tsx diff --git a/plugins/scaffolder/src/components/TaskPage/IconLink.tsx b/plugins/scaffolder/src/legacy/TaskPage/IconLink.tsx similarity index 100% rename from plugins/scaffolder/src/components/TaskPage/IconLink.tsx rename to plugins/scaffolder/src/legacy/TaskPage/IconLink.tsx diff --git a/plugins/scaffolder/src/components/TaskPage/TaskErrors.tsx b/plugins/scaffolder/src/legacy/TaskPage/TaskErrors.tsx similarity index 100% rename from plugins/scaffolder/src/components/TaskPage/TaskErrors.tsx rename to plugins/scaffolder/src/legacy/TaskPage/TaskErrors.tsx diff --git a/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx b/plugins/scaffolder/src/legacy/TaskPage/TaskPage.tsx similarity index 99% rename from plugins/scaffolder/src/components/TaskPage/TaskPage.tsx rename to plugins/scaffolder/src/legacy/TaskPage/TaskPage.tsx index 78cdc5d935..846e5a861f 100644 --- a/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx +++ b/plugins/scaffolder/src/legacy/TaskPage/TaskPage.tsx @@ -236,8 +236,8 @@ const hasLinks = ({ links = [] }: ScaffolderTaskOutput): boolean => /** * TaskPageProps for constructing a TaskPage * @param loadingText - Optional loading text shown before a task begins executing. - * * @public + * @deprecated - this is a useless type that is no longer used. */ export type TaskPageProps = { loadingText?: string; @@ -246,7 +246,7 @@ export type TaskPageProps = { /** * TaskPage for showing the status of the taskId provided as a param * - * @public + * @alpha */ export const TaskPage = (props: TaskPageProps) => { const { loadingText } = props; diff --git a/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.test.tsx b/plugins/scaffolder/src/legacy/TaskPage/TaskPageLinks.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/TaskPage/TaskPageLinks.test.tsx rename to plugins/scaffolder/src/legacy/TaskPage/TaskPageLinks.test.tsx diff --git a/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx b/plugins/scaffolder/src/legacy/TaskPage/TaskPageLinks.tsx similarity index 100% rename from plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx rename to plugins/scaffolder/src/legacy/TaskPage/TaskPageLinks.tsx diff --git a/plugins/scaffolder/src/components/TaskPage/index.ts b/plugins/scaffolder/src/legacy/TaskPage/index.ts similarity index 100% rename from plugins/scaffolder/src/components/TaskPage/index.ts rename to plugins/scaffolder/src/legacy/TaskPage/index.ts diff --git a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder/src/legacy/TemplateCard/TemplateCard.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx rename to plugins/scaffolder/src/legacy/TemplateCard/TemplateCard.tsx diff --git a/plugins/scaffolder/src/components/TemplateCard/index.ts b/plugins/scaffolder/src/legacy/TemplateCard/index.ts similarity index 100% rename from plugins/scaffolder/src/components/TemplateCard/index.ts rename to plugins/scaffolder/src/legacy/TemplateCard/index.ts diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx similarity index 89% rename from plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx rename to plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx index 43b3b49bcf..9107ac67eb 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/CustomFieldExplorer.tsx @@ -28,16 +28,13 @@ import { Select, } from '@material-ui/core'; import CloseIcon from '@material-ui/icons/Close'; -import { withTheme } from '@rjsf/core'; -import { Theme as MuiTheme } from '@rjsf/material-ui'; import CodeMirror from '@uiw/react-codemirror'; import React, { useCallback, useMemo, useState } from 'react'; import yaml from 'yaml'; -import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; -import * as fieldOverrides from '../MultistepJsonForm/FieldOverrides'; +import { Form } from '@backstage/plugin-scaffolder-react/alpha'; import { TemplateEditorForm } from './TemplateEditorForm'; - -const Form = withTheme(MuiTheme); +import validator from '@rjsf/validator-ajv8'; +import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; const useStyles = makeStyles(theme => ({ root: { @@ -69,15 +66,15 @@ export const CustomFieldExplorer = ({ customFieldExtensions = [], onClose, }: { - customFieldExtensions?: FieldExtensionOptions<any, any>[]; + customFieldExtensions?: LegacyFieldExtensionOptions<any, any>[]; onClose?: () => void; }) => { const classes = useStyles(); const fieldOptions = customFieldExtensions.filter(field => !!field.schema); const [selectedField, setSelectedField] = useState(fieldOptions[0]); const [fieldFormState, setFieldFormState] = useState({}); - const [formState, setFormState] = useState({}); const [refreshKey, setRefreshKey] = useState(Date.now()); + const [formState, setFormState] = useState({}); const sampleFieldTemplate = useMemo( () => yaml.stringify({ @@ -104,18 +101,17 @@ export const CustomFieldExplorer = ({ }, [customFieldExtensions]); const handleSelectionChange = useCallback( - selection => { + (selection: LegacyFieldExtensionOptions) => { setSelectedField(selection); setFieldFormState({}); setFormState({}); }, - [setFieldFormState, setFormState, setSelectedField], + [setFieldFormState, setSelectedField, setFormState], ); const handleFieldConfigChange = useCallback( - state => { + (state: {}) => { setFieldFormState(state); - setFormState({}); // Force TemplateEditorForm to re-render since some fields // may not be responsive to ui:option changes setRefreshKey(Date.now()); @@ -134,7 +130,11 @@ export const CustomFieldExplorer = ({ value={selectedField} label="Choose Custom Field Extension" labelId="select-field-label" - onChange={e => handleSelectionChange(e.target.value)} + onChange={e => + handleSelectionChange( + e.target.value as LegacyFieldExtensionOptions, + ) + } > {fieldOptions.map((option, idx) => ( <MenuItem key={idx} value={option as any}> @@ -154,11 +154,12 @@ export const CustomFieldExplorer = ({ <CardContent> <Form showErrorList={false} - fields={{ ...fieldOverrides, ...fieldComponents }} + fields={{ ...fieldComponents }} noHtml5Validate formData={fieldFormState} formContext={{ fieldFormState }} onSubmit={e => handleFieldConfigChange(e.formData)} + validator={validator} schema={selectedField.schema?.uiOptions || {}} > <Button @@ -187,12 +188,12 @@ export const CustomFieldExplorer = ({ </CardContent> </Card> <TemplateEditorForm + data={formState} + onUpdate={setFormState} key={refreshKey} content={sampleFieldTemplate} contentIsSpec fieldExtensions={customFieldExtensions} - data={formState} - onUpdate={setFormState} setErrorText={() => null} /> </div> diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditor.tsx similarity index 79% rename from plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx rename to plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditor.tsx index e07434aff7..f6e7b38d7d 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditor.tsx @@ -15,17 +15,15 @@ */ import { makeStyles } from '@material-ui/core'; import React, { useState } from 'react'; -import type { - FieldExtensionOptions, - LayoutOptions, -} from '@backstage/plugin-scaffolder-react'; +import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; import { TemplateDirectoryAccess } from '../../lib/filesystem'; -import { DirectoryEditorProvider } from './DirectoryEditorContext'; -import { DryRunProvider } from './DryRunContext'; -import { DryRunResults } from './DryRunResults'; -import { TemplateEditorBrowser } from './TemplateEditorBrowser'; +import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { DirectoryEditorProvider } from '../../next/TemplateEditorPage/DirectoryEditorContext'; +import { DryRunProvider } from '../../next/TemplateEditorPage/DryRunContext'; +import { TemplateEditorBrowser } from '../../next/TemplateEditorPage/TemplateEditorBrowser'; +import { TemplateEditorTextArea } from '../../next/TemplateEditorPage/TemplateEditorTextArea'; import { TemplateEditorForm } from './TemplateEditorForm'; -import { TemplateEditorTextArea } from './TemplateEditorTextArea'; +import { DryRunResults } from '../../next/TemplateEditorPage/DryRunResults'; const useStyles = makeStyles({ // Reset and fix sizing to make sure scrolling behaves correctly @@ -59,7 +57,7 @@ const useStyles = makeStyles({ export const TemplateEditor = (props: { directory: TemplateDirectoryAccess; - fieldExtensions?: FieldExtensionOptions<any, any>[]; + fieldExtensions?: LegacyFieldExtensionOptions<any, any>[]; layouts?: LayoutOptions[]; onClose?: () => void; }) => { diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx similarity index 94% rename from plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx rename to plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx index 2a726110b8..df05efc921 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorForm.tsx @@ -19,15 +19,16 @@ import { makeStyles } from '@material-ui/core/styles'; import React, { Component, ReactNode, useMemo, useState } from 'react'; import useDebounce from 'react-use/lib/useDebounce'; import yaml from 'yaml'; -import type { - FieldExtensionOptions, +import { LayoutOptions, TemplateParameterSchema, } from '@backstage/plugin-scaffolder-react'; + +import { useDryRun } from '../../next/TemplateEditorPage/DryRunContext'; +import { useDirectoryEditor } from '../../next/TemplateEditorPage/DirectoryEditorContext'; import { MultistepJsonForm } from '../MultistepJsonForm'; import { createValidator } from '../TemplatePage'; -import { useDirectoryEditor } from './DirectoryEditorContext'; -import { useDryRun } from './DryRunContext'; +import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; const useStyles = makeStyles({ containerWrapper: { @@ -85,7 +86,7 @@ interface TemplateEditorFormProps { setErrorText: (errorText?: string) => void; onDryRun?: (data: JsonObject) => Promise<void>; - fieldExtensions?: FieldExtensionOptions<any, any>[]; + fieldExtensions?: LegacyFieldExtensionOptions<any, any>[]; layouts?: LayoutOptions[]; } @@ -191,7 +192,7 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { <ErrorBoundary invalidator={steps} setErrorText={setErrorText}> <MultistepJsonForm steps={steps} - fields={fields} + fields={fields as any} formData={data} onChange={e => onUpdate(e.formData)} onReset={() => onUpdate({})} diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorPage.tsx similarity index 90% rename from plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx rename to plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorPage.tsx index ebb763e145..127c73dcf5 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateEditorPage.tsx @@ -19,14 +19,12 @@ import { TemplateDirectoryAccess, WebFileSystemAccess, } from '../../lib/filesystem'; -import { CustomFieldExplorer } from './CustomFieldExplorer'; -import { TemplateEditorIntro } from './TemplateEditorIntro'; +import { type LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; +import { TemplateEditorIntro } from '../../next/TemplateEditorPage/TemplateEditorIntro'; import { TemplateEditor } from './TemplateEditor'; import { TemplateFormPreviewer } from './TemplateFormPreviewer'; -import { - type FieldExtensionOptions, - type LayoutOptions, -} from '@backstage/plugin-scaffolder-react'; +import { CustomFieldExplorer } from './CustomFieldExplorer'; type Selection = | { @@ -42,7 +40,7 @@ type Selection = interface TemplateEditorPageProps { defaultPreviewTemplate?: string; - customFieldExtensions?: FieldExtensionOptions<any, any>[]; + customFieldExtensions?: LegacyFieldExtensionOptions<any, any>[]; layouts?: LayoutOptions[]; } diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx similarity index 92% rename from plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx rename to plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx index 69433d5f51..9e92d12d93 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -32,12 +32,10 @@ import CloseIcon from '@material-ui/icons/Close'; import React, { useCallback, useState } from 'react'; import useAsync from 'react-use/lib/useAsync'; import yaml from 'yaml'; -import { - type FieldExtensionOptions, - type LayoutOptions, -} from '@backstage/plugin-scaffolder-react'; +import { LayoutOptions } from '@backstage/plugin-scaffolder-react'; +import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; +import { TemplateEditorTextArea } from '../../next/TemplateEditorPage/TemplateEditorTextArea'; import { TemplateEditorForm } from './TemplateEditorForm'; -import { TemplateEditorTextArea } from './TemplateEditorTextArea'; const EXAMPLE_TEMPLATE_PARAMS_YAML = `# Edit the template parameters below to see how they will render in the scaffolder form UI parameters: @@ -116,7 +114,7 @@ export const TemplateFormPreviewer = ({ layouts = [], }: { defaultPreviewTemplate?: string; - customFieldExtensions?: FieldExtensionOptions<any, any>[]; + customFieldExtensions?: LegacyFieldExtensionOptions<any, any>[]; onClose?: () => void; layouts?: LayoutOptions[]; }) => { @@ -164,7 +162,8 @@ export const TemplateFormPreviewer = ({ ); const handleSelectChange = useCallback( - selected => { + // TODO(Rugvip): Afaik this should be Entity, but didn't want to make runtime changes while fixing types + (selected: any) => { setSelectedTemplate(selected); setTemplateYaml(yaml.stringify(selected.spec)); }, @@ -194,7 +193,7 @@ export const TemplateFormPreviewer = ({ </Select> </FormControl> - <IconButton size="medium" onClick={onClose} aria-label="Close"> + <IconButton size="medium" onClick={onClose}> <CloseIcon /> </IconButton> </div> @@ -207,11 +206,11 @@ export const TemplateFormPreviewer = ({ </div> <div className={classes.preview}> <TemplateEditorForm + data={formState} + onUpdate={setFormState} content={templateYaml} contentIsSpec fieldExtensions={customFieldExtensions} - data={formState} - onUpdate={setFormState} setErrorText={setErrorText} layouts={layouts} /> diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/index.ts b/plugins/scaffolder/src/legacy/TemplateEditorPage/index.ts similarity index 93% rename from plugins/scaffolder/src/components/TemplateEditorPage/index.ts rename to plugins/scaffolder/src/legacy/TemplateEditorPage/index.ts index 7ec6bddb64..7de0d3c679 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/index.ts +++ b/plugins/scaffolder/src/legacy/TemplateEditorPage/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2022 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. @@ -13,5 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - export { TemplateEditorPage } from './TemplateEditorPage'; diff --git a/plugins/scaffolder/src/components/TemplateList/TemplateList.test.tsx b/plugins/scaffolder/src/legacy/TemplateList/TemplateList.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateList/TemplateList.test.tsx rename to plugins/scaffolder/src/legacy/TemplateList/TemplateList.test.tsx diff --git a/plugins/scaffolder/src/components/TemplateList/TemplateList.tsx b/plugins/scaffolder/src/legacy/TemplateList/TemplateList.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateList/TemplateList.tsx rename to plugins/scaffolder/src/legacy/TemplateList/TemplateList.tsx diff --git a/plugins/scaffolder/src/components/TemplateList/index.ts b/plugins/scaffolder/src/legacy/TemplateList/index.ts similarity index 100% rename from plugins/scaffolder/src/components/TemplateList/index.ts rename to plugins/scaffolder/src/legacy/TemplateList/index.ts diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx b/plugins/scaffolder/src/legacy/TemplatePage/TemplatePage.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx rename to plugins/scaffolder/src/legacy/TemplatePage/TemplatePage.test.tsx diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/legacy/TemplatePage/TemplatePage.tsx similarity index 96% rename from plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx rename to plugins/scaffolder/src/legacy/TemplatePage/TemplatePage.tsx index c615649f93..ffb754bae3 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/legacy/TemplatePage/TemplatePage.tsx @@ -20,10 +20,10 @@ import React, { ComponentType, useCallback, useState } from 'react'; import { Navigate, useNavigate } from 'react-router-dom'; import useAsync from 'react-use/lib/useAsync'; import { - type FieldExtensionOptions, type LayoutOptions, scaffolderApiRef, useTemplateSecrets, + ReviewStepProps, } from '@backstage/plugin-scaffolder-react'; import { MultistepJsonForm } from '../MultistepJsonForm'; import { createValidator } from './createValidator'; @@ -38,12 +38,12 @@ import { useRouteRefParams, } from '@backstage/core-plugin-api'; import { stringifyEntityRef } from '@backstage/catalog-model'; -import { ReviewStepProps } from '../types'; import { rootRouteRef, scaffolderTaskRouteRef, selectedTemplateRouteRef, } from '../../routes'; +import { LegacyFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; const useTemplateParameterSchema = (templateRef: string) => { const scaffolderApi = useApi(scaffolderApiRef); @@ -56,7 +56,7 @@ const useTemplateParameterSchema = (templateRef: string) => { type Props = { ReviewStepComponent?: ComponentType<ReviewStepProps>; - customFieldExtensions?: FieldExtensionOptions<any, any>[]; + customFieldExtensions?: LegacyFieldExtensionOptions<any, any>[]; layouts?: LayoutOptions[]; headerOptions?: { pageTitleOverride?: string; @@ -162,7 +162,7 @@ export const TemplatePage = ({ <MultistepJsonForm ReviewStepComponent={ReviewStepComponent} formData={formState} - fields={customFieldComponents} + fields={customFieldComponents as any} onChange={handleChange} onReset={handleFormReset} onFinish={handleCreate} diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts b/plugins/scaffolder/src/legacy/TemplatePage/createValidator.test.ts similarity index 69% rename from plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts rename to plugins/scaffolder/src/legacy/TemplatePage/createValidator.test.ts index 1858e40241..d6a5cd7499 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts +++ b/plugins/scaffolder/src/legacy/TemplatePage/createValidator.test.ts @@ -15,9 +15,9 @@ */ import { createValidator } from './createValidator'; -import { CustomFieldValidator } from '@backstage/plugin-scaffolder-react'; +import { LegacyCustomFieldValidator } from '@backstage/plugin-scaffolder-react/alpha'; import { ApiHolder } from '@backstage/core-plugin-api'; -import { FieldValidation, FormValidation } from '@rjsf/core'; +import { FieldValidation, FormValidation } from '@rjsf/utils'; type CustomLinkType = { url: string; @@ -26,49 +26,51 @@ type CustomLinkType = { }; describe('createValidator', () => { - const validators: Record<string, undefined | CustomFieldValidator<unknown>> = - { - CustomPicker: ( - value: unknown, - fieldValidation: FieldValidation, - _context: { apiHolder: ApiHolder }, - ) => { - if (!value || !(value as { value?: unknown }).value) { - fieldValidation.addError('Error !'); - } - }, - CustomLink: ( - values: unknown, - fieldValidation: FieldValidation, - _context: { apiHolder: ApiHolder }, - ) => { - const input = values as CustomLinkType[]; - for (const item of input) { - const validGitlabUrlRegex = - /gitlab\.(?:stg\.)?spotify\.com\?owner=.*&repo=.*/; + const validators: Record< + string, + undefined | LegacyCustomFieldValidator<unknown> + > = { + CustomPicker: ( + value: unknown, + fieldValidation: FieldValidation, + _context: { apiHolder: ApiHolder }, + ) => { + if (!value || !(value as { value?: unknown }).value) { + fieldValidation.addError('Error !'); + } + }, + CustomLink: ( + values: unknown, + fieldValidation: FieldValidation, + _context: { apiHolder: ApiHolder }, + ) => { + const input = values as CustomLinkType[]; + for (const item of input) { + const validGitlabUrlRegex = + /gitlab\.(?:stg\.)?spotify\.com\?owner=.*&repo=.*/; - if (!item || !validGitlabUrlRegex.test(item.url)) { - fieldValidation.addError( - `Make sure to put in a valid gitlab clone url.`, - ); - } + if (!item || !validGitlabUrlRegex.test(item.url)) { + fieldValidation.addError( + `Make sure to put in a valid gitlab clone url.`, + ); } - }, - TagPicker: ( - values: unknown, - fieldValidation: FieldValidation, - _context: { apiHolder: ApiHolder }, - ) => { - const input = values as string[]; - for (const item of input) { - if (!/^[a-z0-9-]+$/.test(item)) { - fieldValidation.addError( - 'A tag name can only contain lowercase letters, numeric characters or dashes', - ); - } + } + }, + TagPicker: ( + values: unknown, + fieldValidation: FieldValidation, + _context: { apiHolder: ApiHolder }, + ) => { + const input = values as string[]; + for (const item of input) { + if (!/^[a-z0-9-]+$/.test(item)) { + fieldValidation.addError( + 'A tag name can only contain lowercase letters, numeric characters or dashes', + ); } - }, - }; + } + }, + }; const apiHolderMock: jest.Mocked<ApiHolder> = { get: jest.fn().mockImplementation(() => { @@ -109,7 +111,7 @@ describe('createValidator', () => { /* THEN */ expect(result).not.toBeNull(); - expect(result.p1.addError).toHaveBeenCalledTimes(1); + expect(result.p1?.addError).toHaveBeenCalledTimes(1); }); it('should call validator for array property from a custom field extension', () => { @@ -144,7 +146,7 @@ describe('createValidator', () => { /* THEN */ expect(result).not.toBeNull(); - expect(result.tags.addError).toHaveBeenCalledTimes(1); + expect(result.tags?.addError).toHaveBeenCalledTimes(1); }); it('should call validator for array object property from a custom field extension', () => { @@ -193,6 +195,6 @@ describe('createValidator', () => { /* THEN */ expect(result).not.toBeNull(); - expect(result.links.addError).toHaveBeenCalledTimes(1); + expect(result.links?.addError).toHaveBeenCalledTimes(1); }); }); diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts b/plugins/scaffolder/src/legacy/TemplatePage/createValidator.ts similarity index 91% rename from plugins/scaffolder/src/components/TemplatePage/createValidator.ts rename to plugins/scaffolder/src/legacy/TemplatePage/createValidator.ts index 8bfe8c8313..ae0b834fe9 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts +++ b/plugins/scaffolder/src/legacy/TemplatePage/createValidator.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -import { CustomFieldValidator } from '@backstage/plugin-scaffolder-react'; -import { FormValidation } from '@rjsf/core'; +import { LegacyCustomFieldValidator } from '@backstage/plugin-scaffolder-react/alpha'; +import { FieldValidation, FormValidation } from '@rjsf/utils'; import { JsonObject, JsonValue } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; @@ -29,7 +29,7 @@ function isArray(obj: unknown): obj is JsonObject { export const createValidator = ( rootSchema: JsonObject, - validators: Record<string, undefined | CustomFieldValidator<unknown>>, + validators: Record<string, undefined | LegacyCustomFieldValidator<unknown>>, context: { apiHolder: ApiHolder; }, @@ -56,7 +56,7 @@ export const createValidator = ( if (fieldName && typeof validators[fieldName] === 'function') { validators[fieldName]!( propData as JsonObject[], - propValidation, + propValidation as FieldValidation, context, ); } diff --git a/plugins/scaffolder/src/components/TemplatePage/index.ts b/plugins/scaffolder/src/legacy/TemplatePage/index.ts similarity index 100% rename from plugins/scaffolder/src/components/TemplatePage/index.ts rename to plugins/scaffolder/src/legacy/TemplatePage/index.ts diff --git a/plugins/scaffolder/src/legacy/index.ts b/plugins/scaffolder/src/legacy/index.ts new file mode 100644 index 0000000000..2393be0f69 --- /dev/null +++ b/plugins/scaffolder/src/legacy/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 { LegacyRouter, type LegacyRouterProps } from './Router'; +export { LegacyScaffolderPage } from '../plugin'; diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx index bf5ffe97ea..a6c06ea20a 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/CustomFieldExplorer.tsx @@ -31,12 +31,10 @@ import CloseIcon from '@material-ui/icons/Close'; import CodeMirror from '@uiw/react-codemirror'; import React, { useCallback, useMemo, useState } from 'react'; import yaml from 'yaml'; -import { - NextFieldExtensionOptions, - Form, -} from '@backstage/plugin-scaffolder-react/alpha'; +import { Form } from '@backstage/plugin-scaffolder-react/alpha'; import { TemplateEditorForm } from './TemplateEditorForm'; import validator from '@rjsf/validator-ajv8'; +import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; const useStyles = makeStyles(theme => ({ root: { @@ -68,7 +66,7 @@ export const CustomFieldExplorer = ({ customFieldExtensions = [], onClose, }: { - customFieldExtensions?: NextFieldExtensionOptions<any, any>[]; + customFieldExtensions?: FieldExtensionOptions<any, any>[]; onClose?: () => void; }) => { const classes = useStyles(); @@ -102,7 +100,7 @@ export const CustomFieldExplorer = ({ }, [customFieldExtensions]); const handleSelectionChange = useCallback( - selection => { + (selection: FieldExtensionOptions) => { setSelectedField(selection); setFieldFormState({}); }, @@ -110,7 +108,7 @@ export const CustomFieldExplorer = ({ ); const handleFieldConfigChange = useCallback( - state => { + (state: {}) => { setFieldFormState(state); // Force TemplateEditorForm to re-render since some fields // may not be responsive to ui:option changes @@ -130,7 +128,9 @@ export const CustomFieldExplorer = ({ value={selectedField} label="Choose Custom Field Extension" labelId="select-field-label" - onChange={e => handleSelectionChange(e.target.value)} + onChange={e => + handleSelectionChange(e.target.value as FieldExtensionOptions) + } > {fieldOptions.map((option, idx) => ( <MenuItem key={idx} value={option as any}> diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DirectoryEditorContext.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/DirectoryEditorContext.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/DirectoryEditorContext.tsx diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunContext.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/DryRunContext.test.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.test.tsx diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunContext.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/DryRunContext.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/DryRunContext.tsx diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResults.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResults.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResults.tsx diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsSplitView.tsx diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx similarity index 92% rename from plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx index c2d8d3a2a4..c5c391907e 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx @@ -16,7 +16,7 @@ import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { screen } from '@testing-library/react'; +import { screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React, { ReactNode, useEffect } from 'react'; import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; @@ -91,9 +91,13 @@ describe('DryRunResultsView', () => { expect(screen.queryByText('Foo Link')).not.toBeInTheDocument(); await userEvent.click(screen.getByText('Log')); - expect(screen.getByText('Foo Message')).toBeInTheDocument(); + await waitFor(() => { + expect(screen.getByText('Foo Message')).toBeInTheDocument(); + }); await userEvent.click(screen.getByText('Output')); - expect(screen.getByText('Foo Link')).toBeInTheDocument(); + await waitFor(() => { + expect(screen.getByText('Foo Link')).toBeInTheDocument(); + }); }); }); diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx similarity index 96% rename from plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx index 9c56039808..68ed6f906f 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx @@ -24,11 +24,11 @@ import Tab from '@material-ui/core/Tab'; import Tabs from '@material-ui/core/Tabs'; import CodeMirror from '@uiw/react-codemirror'; import React, { useEffect, useMemo, useState } from 'react'; -import { TaskStatusStepper } from '../../TaskPage/TaskPage'; -import { TaskPageLinks } from '../../TaskPage/TaskPageLinks'; import { useDryRun } from '../DryRunContext'; -import { FileBrowser } from '../../FileBrowser'; import { DryRunResultsSplitView } from './DryRunResultsSplitView'; +import { FileBrowser } from '../../../components/FileBrowser'; +import { TaskPageLinks } from '../../../legacy/TaskPage/TaskPageLinks'; +import { TaskStatusStepper } from '../../../legacy/TaskPage/TaskPage'; const useStyles = makeStyles({ root: { diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/index.ts b/plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/index.ts rename to plugins/scaffolder/src/next/TemplateEditorPage/DryRunResults/index.ts diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx index 16067e8095..a348f5e513 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditor.tsx @@ -16,14 +16,14 @@ import { makeStyles } from '@material-ui/core'; import React, { useState } from 'react'; import type { LayoutOptions } from '@backstage/plugin-scaffolder-react'; -import { NextFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; +import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; import { TemplateDirectoryAccess } from '../../lib/filesystem'; -import { DirectoryEditorProvider } from '../../components/TemplateEditorPage/DirectoryEditorContext'; -import { DryRunProvider } from '../../components/TemplateEditorPage/DryRunContext'; -import { DryRunResults } from '../../components/TemplateEditorPage/DryRunResults'; -import { TemplateEditorBrowser } from '../../components/TemplateEditorPage/TemplateEditorBrowser'; +import { DirectoryEditorProvider } from './DirectoryEditorContext'; +import { TemplateEditorBrowser } from './TemplateEditorBrowser'; +import { DryRunProvider } from './DryRunContext'; +import { TemplateEditorTextArea } from './TemplateEditorTextArea'; import { TemplateEditorForm } from './TemplateEditorForm'; -import { TemplateEditorTextArea } from '../../components/TemplateEditorPage/TemplateEditorTextArea'; +import { DryRunResults } from './DryRunResults'; const useStyles = makeStyles({ // Reset and fix sizing to make sure scrolling behaves correctly @@ -57,7 +57,7 @@ const useStyles = makeStyles({ export const TemplateEditor = (props: { directory: TemplateDirectoryAccess; - fieldExtensions?: NextFieldExtensionOptions<any, any>[]; + fieldExtensions?: FieldExtensionOptions<any, any>[]; layouts?: LayoutOptions[]; onClose?: () => void; }) => { diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorBrowser.test.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorBrowser.test.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.test.tsx diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorBrowser.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx similarity index 98% rename from plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorBrowser.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx index 177ad11c2b..996da98d4a 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorBrowser.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorBrowser.tsx @@ -18,8 +18,8 @@ import CloseIcon from '@material-ui/icons/Close'; import RefreshIcon from '@material-ui/icons/Refresh'; import SaveIcon from '@material-ui/icons/Save'; import React from 'react'; -import { FileBrowser } from '../FileBrowser'; import { useDirectoryEditor } from './DirectoryEditorContext'; +import { FileBrowser } from '../../components/FileBrowser'; const useStyles = makeStyles(theme => ({ button: { diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx index 898487e200..4b5a00b7ba 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorForm.tsx @@ -16,19 +16,20 @@ import { useApiHolder } from '@backstage/core-plugin-api'; import { JsonObject, JsonValue } from '@backstage/types'; import { makeStyles } from '@material-ui/core/styles'; -import React, { Component, ReactNode, useState } from 'react'; +import React, { Component, ReactNode, useMemo, useState } from 'react'; import useDebounce from 'react-use/lib/useDebounce'; import yaml from 'yaml'; import { LayoutOptions, TemplateParameterSchema, + FieldExtensionOptions, } from '@backstage/plugin-scaffolder-react'; import { - NextFieldExtensionOptions, Stepper, + createAsyncValidators, } from '@backstage/plugin-scaffolder-react/alpha'; -import { useDryRun } from '../../components/TemplateEditorPage/DryRunContext'; -import { useDirectoryEditor } from '../../components/TemplateEditorPage/DirectoryEditorContext'; +import { useDryRun } from './DryRunContext'; +import { useDirectoryEditor } from './DirectoryEditorContext'; const useStyles = makeStyles({ containerWrapper: { @@ -82,8 +83,9 @@ interface TemplateEditorFormProps { /** Setting this to true will cause the content to be parsed as if it is the template entity spec */ contentIsSpec?: boolean; setErrorText: (errorText?: string) => void; + onDryRun?: (data: JsonObject) => Promise<void>; - fieldExtensions?: NextFieldExtensionOptions<any, any>[]; + fieldExtensions?: FieldExtensionOptions<any, any>[]; layouts?: LayoutOptions[]; } @@ -106,6 +108,12 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { const [steps, setSteps] = useState<TemplateParameterSchema['steps']>(); + const fields = useMemo(() => { + return Object.fromEntries( + fieldExtensions.map(({ name, component }) => [name, component]), + ); + }, [fieldExtensions]); + useDebounce( () => { try { @@ -113,7 +121,10 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { setSteps(undefined); return; } - const parsed: JsonValue = yaml.parse(content); + const parsed: JsonValue = yaml + .parseAllDocuments(content) + .filter(c => c) + .map(c => c.toJSON())[0]; if (!isJsonObject(parsed)) { setSteps(undefined); @@ -140,6 +151,10 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { return; } + const fieldValidators = Object.fromEntries( + fieldExtensions.map(({ name, validation }) => [name, validation]), + ); + setErrorText(); setSteps( parameters.flatMap(param => @@ -148,6 +163,9 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { { title: String(param.title), schema: param, + validate: createAsyncValidators(param, fieldValidators, { + apiHolder, + }), }, ] : [], @@ -172,11 +190,11 @@ export function TemplateEditorForm(props: TemplateEditorFormProps) { <Stepper manifest={{ steps, title: 'Template Editor' }} extensions={fieldExtensions} - onCreate={async data => { - await onDryRun?.(data); + components={fields} + onCreate={async options => { + await onDryRun?.(options); }} layouts={layouts} - components={{ createButtonText: onDryRun && 'Try It' }} /> </ErrorBoundary> </div> @@ -197,7 +215,7 @@ export function TemplateEditorFormDirectoryEditorDryRun( const directoryEditor = useDirectoryEditor(); const { selectedFile } = directoryEditor; - const handleDryRun = async (values: JsonObject) => { + const handleDryRun = async (data: JsonObject) => { if (!selectedFile) { return; } @@ -205,7 +223,7 @@ export function TemplateEditorFormDirectoryEditorDryRun( try { await dryRun.execute({ templateContent: selectedFile.content, - values, + values: data, files: directoryEditor.files, }); setErrorText(); diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorIntro.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorIntro.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorIntro.tsx diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx index 9863e99c73..aab693e590 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorPage.tsx @@ -22,9 +22,11 @@ import { import { CustomFieldExplorer } from './CustomFieldExplorer'; import { TemplateEditor } from './TemplateEditor'; import { TemplateFormPreviewer } from './TemplateFormPreviewer'; -import { type LayoutOptions } from '@backstage/plugin-scaffolder-react'; -import { NextFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; -import { TemplateEditorIntro } from '../../components/TemplateEditorPage/TemplateEditorIntro'; +import { + FieldExtensionOptions, + type LayoutOptions, +} from '@backstage/plugin-scaffolder-react'; +import { TemplateEditorIntro } from './TemplateEditorIntro'; type Selection = | { @@ -40,7 +42,7 @@ type Selection = interface TemplateEditorPageProps { defaultPreviewTemplate?: string; - customFieldExtensions?: NextFieldExtensionOptions<any, any>[]; + customFieldExtensions?: FieldExtensionOptions<any, any>[]; layouts?: LayoutOptions[]; } diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorTextArea.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx similarity index 100% rename from plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorTextArea.tsx rename to plugins/scaffolder/src/next/TemplateEditorPage/TemplateEditorTextArea.tsx diff --git a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx index 2aa1cc764d..c253bc0a5f 100644 --- a/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx +++ b/plugins/scaffolder/src/next/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -32,10 +32,12 @@ import CloseIcon from '@material-ui/icons/Close'; import React, { useCallback, useState } from 'react'; import useAsync from 'react-use/lib/useAsync'; import yaml from 'yaml'; -import { type LayoutOptions } from '@backstage/plugin-scaffolder-react'; -import { NextFieldExtensionOptions } from '@backstage/plugin-scaffolder-react/alpha'; +import { + LayoutOptions, + FieldExtensionOptions, +} from '@backstage/plugin-scaffolder-react'; import { TemplateEditorForm } from './TemplateEditorForm'; -import { TemplateEditorTextArea } from '../../components/TemplateEditorPage/TemplateEditorTextArea'; +import { TemplateEditorTextArea } from './TemplateEditorTextArea'; const EXAMPLE_TEMPLATE_PARAMS_YAML = `# Edit the template parameters below to see how they will render in the scaffolder form UI parameters: @@ -114,7 +116,7 @@ export const TemplateFormPreviewer = ({ layouts = [], }: { defaultPreviewTemplate?: string; - customFieldExtensions?: NextFieldExtensionOptions<any, any>[]; + customFieldExtensions?: FieldExtensionOptions<any, any>[]; onClose?: () => void; layouts?: LayoutOptions[]; }) => { @@ -161,7 +163,8 @@ export const TemplateFormPreviewer = ({ ); const handleSelectChange = useCallback( - selected => { + // TODO(Rugvip): Afaik this should be Entity, but didn't want to make runtime changes while fixing types + (selected: any) => { setSelectedTemplate(selected); setTemplateYaml(yaml.stringify(selected.spec)); }, diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx index 863d3009e1..44390bc03c 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx @@ -38,7 +38,6 @@ import { import { ScaffolderPageContextMenu, TemplateCategoryPicker, - TemplateGroupFilter, TemplateGroups, } from '@backstage/plugin-scaffolder-react/alpha'; @@ -52,6 +51,7 @@ import { viewTechDocRouteRef, } from '../../routes'; import { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model'; +import { TemplateGroupFilter } from '@backstage/plugin-scaffolder-react'; /** * @alpha diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index a7133ae8c7..3b14f2c07f 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -26,12 +26,11 @@ import { scaffolderApiRef, useTemplateSecrets, type LayoutOptions, -} from '@backstage/plugin-scaffolder-react'; -import { FormProps, - Workflow, - NextFieldExtensionOptions, -} from '@backstage/plugin-scaffolder-react/alpha'; + FieldExtensionOptions, + ReviewStepProps, +} from '@backstage/plugin-scaffolder-react'; +import { Workflow } from '@backstage/plugin-scaffolder-react/alpha'; import { JsonValue } from '@backstage/types'; import { Header, Page } from '@backstage/core-components'; @@ -45,9 +44,12 @@ import { * @alpha */ export type TemplateWizardPageProps = { - customFieldExtensions: NextFieldExtensionOptions<any, any>[]; + customFieldExtensions: FieldExtensionOptions<any, any>[]; + components?: { + ReviewStepComponent?: React.ComponentType<ReviewStepProps>; + }; layouts?: LayoutOptions[]; - FormProps?: FormProps; + formProps?: FormProps; }; export const TemplateWizardPage = (props: TemplateWizardPageProps) => { @@ -90,9 +92,10 @@ export const TemplateWizardPage = (props: TemplateWizardPageProps) => { namespace={namespace} templateName={templateName} onCreate={onCreate} + components={props.components} onError={onError} extensions={props.customFieldExtensions} - FormProps={props.FormProps} + formProps={props.formProps} layouts={props.layouts} /> </Page> diff --git a/plugins/scaffolder/src/next/index.ts b/plugins/scaffolder/src/next/index.ts index 6cef3eaa03..2ae1b7b6c7 100644 --- a/plugins/scaffolder/src/next/index.ts +++ b/plugins/scaffolder/src/next/index.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * from './Router'; export * from './TemplateListPage'; export * from './TemplateWizardPage'; export * from './types'; diff --git a/plugins/scaffolder/src/next/types.ts b/plugins/scaffolder/src/next/types.ts index c2ee473d54..80e01042f2 100644 --- a/plugins/scaffolder/src/next/types.ts +++ b/plugins/scaffolder/src/next/types.ts @@ -20,7 +20,7 @@ * It exists already in the `scaffolder-react` plugin, so you may have to update both files. */ -import type { FormProps as SchemaFormProps } from '@rjsf/core-v5'; +import type { FormProps as SchemaFormProps } from '@rjsf/core'; /** * Any `@rjsf/core` form properties that are publicly exposed to the `NextScaffolderPage` diff --git a/plugins/scaffolder/src/plugin.tsx b/plugins/scaffolder/src/plugin.tsx index ad9e70d843..fdde81695d 100644 --- a/plugins/scaffolder/src/plugin.tsx +++ b/plugins/scaffolder/src/plugin.tsx @@ -217,10 +217,10 @@ export const EntityTagsPickerFieldExtension = scaffolderPlugin.provide( * @alpha * The Router and main entrypoint to the Alpha Scaffolder plugin. */ -export const NextScaffolderPage = scaffolderPlugin.provide( +export const LegacyScaffolderPage = scaffolderPlugin.provide( createRoutableExtension({ - name: 'NextScaffolderPage', - component: () => import('./next/Router').then(m => m.Router), + name: 'LegacyScaffolderPage', + component: () => import('./legacy/Router').then(m => m.LegacyRouter), mountPoint: rootRouteRef, }), ); diff --git a/plugins/search-backend-module-catalog/CHANGELOG.md b/plugins/search-backend-module-catalog/CHANGELOG.md index 402b501695..c65b3a119c 100644 --- a/plugins/search-backend-module-catalog/CHANGELOG.md +++ b/plugins/search-backend-module-catalog/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-search-backend-module-catalog +## 0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## 0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 0.1.9-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-catalog/package.json b/plugins/search-backend-module-catalog/package.json index 4963708861..4bcdf8f53b 100644 --- a/plugins/search-backend-module-catalog/package.json +++ b/plugins/search-backend-module-catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-catalog", "description": "A module for the search backend that exports catalog modules", - "version": "0.1.9-next.1", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-elasticsearch/CHANGELOG.md b/plugins/search-backend-module-elasticsearch/CHANGELOG.md index 0e92e7c3db..94727e88a2 100644 --- a/plugins/search-backend-module-elasticsearch/CHANGELOG.md +++ b/plugins/search-backend-module-elasticsearch/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-search-backend-module-elasticsearch +## 1.3.9 + +### Patch Changes + +- 3963d0b885: Ensure that all relevant config fields are properly marked as secret +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/plugin-search-common@1.2.7 + +## 1.3.9-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/integration-aws-node@0.1.7-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 1.3.8-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 36d66e827b..ef15b13290 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-elasticsearch", "description": "A module for the search backend that implements search using ElasticSearch", - "version": "1.3.8-next.1", + "version": "1.3.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-explore/CHANGELOG.md b/plugins/search-backend-module-explore/CHANGELOG.md index c26bf84328..f4b64f07c8 100644 --- a/plugins/search-backend-module-explore/CHANGELOG.md +++ b/plugins/search-backend-module-explore/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-search-backend-module-explore +## 0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/config@1.1.1 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7 + +## 0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-explore-common@0.0.2 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 0.1.9-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-explore/package.json b/plugins/search-backend-module-explore/package.json index f70d70dd73..41a390d773 100644 --- a/plugins/search-backend-module-explore/package.json +++ b/plugins/search-backend-module-explore/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-explore", "description": "A module for the search backend that exports explore modules", - "version": "0.1.9-next.1", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-pg/CHANGELOG.md b/plugins/search-backend-module-pg/CHANGELOG.md index 10453b9500..3f8d5adeb7 100644 --- a/plugins/search-backend-module-pg/CHANGELOG.md +++ b/plugins/search-backend-module-pg/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-search-backend-module-pg +## 0.5.15 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## 0.5.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 0.5.14-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index ad9f9e0a3b..2bdea9b391 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-pg", "description": "A module for the search backend that implements search using PostgreSQL", - "version": "0.5.14-next.1", + "version": "0.5.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-module-techdocs/CHANGELOG.md b/plugins/search-backend-module-techdocs/CHANGELOG.md index 5364e493c6..fa8997a990 100644 --- a/plugins/search-backend-module-techdocs/CHANGELOG.md +++ b/plugins/search-backend-module-techdocs/CHANGELOG.md @@ -1,5 +1,41 @@ # @backstage/plugin-search-backend-module-techdocs +## 0.1.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/plugin-techdocs-node@1.9.0 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## 0.1.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-techdocs-node@1.9.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 0.1.9-next.1 ### Patch Changes diff --git a/plugins/search-backend-module-techdocs/package.json b/plugins/search-backend-module-techdocs/package.json index 54e9b86afa..aa888a3d8a 100644 --- a/plugins/search-backend-module-techdocs/package.json +++ b/plugins/search-backend-module-techdocs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-module-techdocs", "description": "A module for the search backend that exports techdocs modules", - "version": "0.1.9-next.1", + "version": "0.1.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend-node/CHANGELOG.md b/plugins/search-backend-node/CHANGELOG.md index 880615383a..c2767e6463 100644 --- a/plugins/search-backend-node/CHANGELOG.md +++ b/plugins/search-backend-node/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-search-backend-node +## 1.2.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## 1.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 1.2.9-next.1 ### Patch Changes diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index 587b98cd61..78d693466d 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend-node", "description": "A library for Backstage backend plugins that want to interact with the search backend plugin", - "version": "1.2.9-next.1", + "version": "1.2.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend/CHANGELOG.md b/plugins/search-backend/CHANGELOG.md index a1cae58b98..94f8c5d605 100644 --- a/plugins/search-backend/CHANGELOG.md +++ b/plugins/search-backend/CHANGELOG.md @@ -1,5 +1,40 @@ # @backstage/plugin-search-backend +## 1.4.6 + +### Patch Changes + +- 16be6f9473: Set the default length limit to search query to 100. To override it, define `search.maxTermLength` in the config file. +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/errors@1.2.3 + - @backstage/backend-openapi-utils@0.0.5 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-node@1.2.10 + - @backstage/plugin-permission-node@0.7.17 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## 1.4.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-openapi-utils@0.0.5-next.0 + - @backstage/plugin-permission-node@0.7.17-next.2 + - @backstage/plugin-search-backend-node@1.2.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 1.4.5-next.1 ### Patch Changes diff --git a/plugins/search-backend/config.d.ts b/plugins/search-backend/config.d.ts index 3dbdf78dfe..25ae59d273 100644 --- a/plugins/search-backend/config.d.ts +++ b/plugins/search-backend/config.d.ts @@ -22,6 +22,11 @@ export interface Config { */ maxPageLimit?: number; + /** + * Sets the maximum term length for the search string. Defaults to 100. + */ + maxTermLength?: number; + /** * Options related to the search integration with the Backstage permissions system */ diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index 10c09a0178..cd3c16efe2 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-backend", "description": "The Backstage backend plugin that provides your backstage app with search", - "version": "1.4.5-next.1", + "version": "1.4.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/search-backend/src/service/router.test.ts b/plugins/search-backend/src/service/router.test.ts index 7ec8603307..73523f2b62 100644 --- a/plugins/search-backend/src/service/router.test.ts +++ b/plugins/search-backend/src/service/router.test.ts @@ -60,7 +60,7 @@ describe('createRouter', () => { }, config: new ConfigReader({ permissions: { enabled: false }, - search: { maxPageLimit: 200 }, + search: { maxPageLimit: 200, maxTermLength: 20 }, }), permissions: mockPermissionEvaluator, logger, @@ -162,6 +162,19 @@ describe('createRouter', () => { }); }); + it('should reject term length over configured max', async () => { + const response = await request(app).get( + `/query?term=HelloWorld1234567890!`, + ); + + expect(response.status).toEqual(400); + expect(response.body).toMatchObject({ + error: { + message: /The term length "21" is greater than "20"/i, + }, + }); + }); + it('removes backend-only properties from search documents', async () => { mockSearchEngine.query.mockResolvedValue({ results: [ diff --git a/plugins/search-backend/src/service/router.ts b/plugins/search-backend/src/service/router.ts index dca632dfaf..876cb5d103 100644 --- a/plugins/search-backend/src/service/router.ts +++ b/plugins/search-backend/src/service/router.ts @@ -63,6 +63,7 @@ export type RouterOptions = { }; const defaultMaxPageLimit = 100; +const defaultMaxTermLength = 100; const allowedLocationProtocols = ['http:', 'https:']; /** @@ -77,8 +78,19 @@ export async function createRouter( const maxPageLimit = config.getOptionalNumber('search.maxPageLimit') ?? defaultMaxPageLimit; + const maxTermLength = + config.getOptionalNumber('search.maxTermLength') ?? defaultMaxTermLength; + const requestSchema = z.object({ - term: z.string().default(''), + term: z + .string() + .refine( + term => term.length <= maxTermLength, + term => ({ + message: `The term length "${term.length}" is greater than "${maxTermLength}"`, + }), + ) + .default(''), filters: jsonObjectSchema.optional(), types: z .array(z.string().refine(type => Object.keys(types).includes(type))) diff --git a/plugins/search-backend/src/service/standaloneServer.ts b/plugins/search-backend/src/service/standaloneServer.ts index 3f1fdcb34e..9e4294d39f 100644 --- a/plugins/search-backend/src/service/standaloneServer.ts +++ b/plugins/search-backend/src/service/standaloneServer.ts @@ -18,7 +18,7 @@ import { createServiceBuilder, loadBackendConfig, ServerTokenManager, - SingleHostDiscovery, + HostDiscovery, } from '@backstage/backend-common'; import { Server } from 'http'; import { Logger } from 'winston'; @@ -42,7 +42,7 @@ export async function startStandaloneServer( const config = await loadBackendConfig({ logger, argv: process.argv }); const searchEngine = new LunrSearchEngine({ logger }); const indexBuilder = new IndexBuilder({ logger, searchEngine }); - const discovery = SingleHostDiscovery.fromConfig(config); + const discovery = HostDiscovery.fromConfig(config); const tokenManager = ServerTokenManager.fromConfig(config, { logger, }); diff --git a/plugins/search-common/CHANGELOG.md b/plugins/search-common/CHANGELOG.md index 0e7f901614..bfb7959327 100644 --- a/plugins/search-common/CHANGELOG.md +++ b/plugins/search-common/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-search-common +## 1.2.7 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9 + +## 1.2.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/types@1.1.1 + - @backstage/plugin-permission-common@0.7.9-next.0 + ## 1.2.6 ### Patch Changes diff --git a/plugins/search-common/package.json b/plugins/search-common/package.json index b59df94990..3fe45d84d2 100644 --- a/plugins/search-common/package.json +++ b/plugins/search-common/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search-common", "description": "Common functionalities for Search, to be shared between various search-enabled plugins", - "version": "1.2.6", + "version": "1.2.7", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/plugins/search-react/CHANGELOG.md b/plugins/search-react/CHANGELOG.md index 1cb3a0e329..91ec2e4421 100644 --- a/plugins/search-react/CHANGELOG.md +++ b/plugins/search-react/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-search-react +## 1.7.1 + +### Patch Changes + +- 06432f900c: Updated `/alpha` exports to use new `attachTo` option. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: The filter options passed to `SearchResultGroupLayout` are now always explicitly rendered as strings by default. +- 703a4ffc5b: Create `createSearchResultListItem` alpha version that only supports declarative integration. +- Updated dependencies + - @backstage/frontend-app-api@0.2.0 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## 1.7.1-next.2 + +### Patch Changes + +- 06432f900c: Updated `/alpha` exports to use new `attachTo` option. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/frontend-app-api@0.2.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 1.7.1-next.1 ### Patch Changes diff --git a/plugins/search-react/alpha-api-report.md b/plugins/search-react/alpha-api-report.md index d62a0f1f0e..9c1248b536 100644 --- a/plugins/search-react/alpha-api-report.md +++ b/plugins/search-react/alpha-api-report.md @@ -48,7 +48,10 @@ export type SearchResultItemExtensionOptions< }, > = { id: string; - at?: string; + attachTo?: { + id: string; + input: string; + }; configSchema?: PortableSchema<TConfig>; component: (options: { config: TConfig; diff --git a/plugins/search-react/package.json b/plugins/search-react/package.json index 3591e75e94..c2c181f657 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.1-next.1", + "version": "1.7.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -62,18 +62,17 @@ "react-use": "^17.3.2" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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" }, "files": [ diff --git a/plugins/search-react/src/alpha.test.tsx b/plugins/search-react/src/alpha.test.tsx index b61a400832..5222e4dad5 100644 --- a/plugins/search-react/src/alpha.test.tsx +++ b/plugins/search-react/src/alpha.test.tsx @@ -58,7 +58,7 @@ describe('createSearchResultListItemExtension', () => { const TechDocsSearchResultItemExtension = createSearchResultListItemExtension({ id: 'techdocs', - at: 'plugin.search.page/items', + attachTo: { id: 'plugin.search.page', input: 'items' }, configSchema: createSchemaFromZod(z => z.object({ noTrack: z.boolean().default(true), @@ -79,7 +79,7 @@ describe('createSearchResultListItemExtension', () => { const ExploreSearchResultItemExtension = createSearchResultListItemExtension({ id: 'explore', - at: 'plugin.search.page/items', + attachTo: { id: 'plugin.search.page', input: 'items' }, predicate: result => result.type === 'explore', component: async () => ExploreSearchResultItemComponent, }); @@ -168,7 +168,7 @@ describe('createSearchResultListItemExtension', () => { }); const app = createApp({ - plugins: [SearchPlugin], + features: [SearchPlugin], configLoader: async () => new MockConfigApi({ app: { diff --git a/plugins/search-react/src/alpha.tsx b/plugins/search-react/src/alpha.tsx index 5b44a7bbb5..366112c95e 100644 --- a/plugins/search-react/src/alpha.tsx +++ b/plugins/search-react/src/alpha.tsx @@ -65,7 +65,7 @@ export type SearchResultItemExtensionOptions< /** * The extension attachment point (e.g., search modal or page). */ - at?: string; + attachTo?: { id: string; input: string }; /** * Optional extension config schema. */ @@ -97,7 +97,7 @@ export function createSearchResultListItemExtension< ) as PortableSchema<TConfig>); return createExtension({ id: `plugin.search.result.item.${options.id}`, - at: options.at ?? 'plugin.search.page/items', + attachTo: options.attachTo ?? { id: 'plugin.search.page', input: 'items' }, configSchema, output: { item: searchResultItemExtensionData, diff --git a/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx b/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx index ce3c285852..d9b29584f8 100644 --- a/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx +++ b/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx @@ -318,7 +318,7 @@ describe('SearchBar', () => { </TestApiProvider>, ); - const textbox = screen.getByLabelText('Search'); + const textbox = screen.getByLabelText<HTMLInputElement>('Search'); let value = 'value'; await user.type(textbox, value); @@ -339,6 +339,8 @@ describe('SearchBar', () => { value = 'new value'; await user.clear(textbox); + await waitFor(() => expect(textbox.value).toBe('')); + // make sure new term is captured await user.type(textbox, value); await waitFor(() => { diff --git a/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx b/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx index 765d2a26d1..abf5e828f6 100644 --- a/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx +++ b/plugins/search-react/src/components/SearchFilter/SearchFilter.Autocomplete.test.tsx @@ -29,7 +29,7 @@ const SearchContextFilterSpy = ({ name }: { name: string }) => { const value = filters[name]; return ( <span data-testid={`${name}-filter-spy`}> - {Array.isArray(value) ? value.join(',') : value} + {Array.isArray(value) ? value.join(',') : value?.toString()} </span> ); }; @@ -364,7 +364,7 @@ describe('SearchFilter.Autocomplete', () => { }); // Blur the field and only one tag should be shown with a +1. - input.blur(); + await userEvent.tab(); expect( screen.queryByRole('button', { name: values[0] }), ).not.toBeInTheDocument(); diff --git a/plugins/search-react/src/components/SearchFilter/hooks.test.tsx b/plugins/search-react/src/components/SearchFilter/hooks.test.tsx index 5135cd4ae6..884512963f 100644 --- a/plugins/search-react/src/components/SearchFilter/hooks.test.tsx +++ b/plugins/search-react/src/components/SearchFilter/hooks.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { ApiProvider } from '@backstage/core-app-api'; import { MockConfigApi, TestApiRegistry } from '@backstage/test-utils'; -import { renderHook } from '@testing-library/react-hooks'; +import { act, renderHook, waitFor } from '@testing-library/react'; import { searchApiRef } from '../../api'; import { SearchContextProvider, useSearch } from '../../context'; @@ -67,7 +67,7 @@ describe('SearchFilter.hooks', () => { it('should set non-empty string value', async () => { const expectedFilter = 'someField'; const expectedValue = 'someValue'; - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => { useDefaultFilterValue(expectedFilter, expectedValue); return useSearch(); @@ -77,15 +77,15 @@ describe('SearchFilter.hooks', () => { }, ); - await waitForNextUpdate(); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should set non-empty array value', async () => { const expectedFilter = 'someField'; const expectedValue = ['someValue', 'anotherValue']; - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => { useDefaultFilterValue(expectedFilter, expectedValue); return useSearch(); @@ -95,134 +95,139 @@ describe('SearchFilter.hooks', () => { }, ); - await waitForNextUpdate(); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not set undefined value', async () => { const expectedFilter = 'someField'; const expectedValue = 'notEmpty'; - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => { useDefaultFilterValue(expectedFilter, undefined); return useSearch(); }, { - wrapper, - initialProps: { - overrides: { - filters: { - [expectedFilter]: expectedValue, + wrapper: ({ children }) => + wrapper({ + children, + overrides: { + filters: { + [expectedFilter]: expectedValue, + }, }, - }, - }, + }), }, ); - await waitForNextUpdate(); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not set null value', async () => { const expectedFilter = 'someField'; const expectedValue = 'notEmpty'; - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => { useDefaultFilterValue(expectedFilter, null); return useSearch(); }, { - wrapper, - initialProps: { - overrides: { - filters: { - [expectedFilter]: expectedValue, + wrapper: ({ children }) => + wrapper({ + children, + overrides: { + filters: { + [expectedFilter]: expectedValue, + }, }, - }, - }, + }), }, ); - await waitForNextUpdate(); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not set empty string value', async () => { const expectedFilter = 'someField'; const expectedValue = 'notEmpty'; - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => { useDefaultFilterValue(expectedFilter, ''); return useSearch(); }, { - wrapper, - initialProps: { - overrides: { - filters: { - [expectedFilter]: expectedValue, + wrapper: ({ children }) => + wrapper({ + children, + overrides: { + filters: { + [expectedFilter]: expectedValue, + }, }, - }, - }, + }), }, ); - await waitForNextUpdate(); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not set empty array value', async () => { const expectedFilter = 'someField'; const expectedValue = ['not', 'empty']; - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => { useDefaultFilterValue(expectedFilter, []); return useSearch(); }, { - wrapper, - initialProps: { - overrides: { - filters: { - [expectedFilter]: expectedValue, + wrapper: ({ children }) => + wrapper({ + children, + overrides: { + filters: { + [expectedFilter]: expectedValue, + }, }, - }, - }, + }), }, ); - await waitForNextUpdate(); - - expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + await waitFor(() => { + expect(result.current.filters[expectedFilter]).toEqual(expectedValue); + }); }); it('should not affect unrelated filters', async () => { const expectedFilter = 'someField'; const expectedValue = 'someValue'; - const { result, waitForNextUpdate } = renderHook( + const { result } = renderHook( () => { useDefaultFilterValue(expectedFilter, expectedValue); return useSearch(); }, { - wrapper, - initialProps: { - overrides: { - filters: { - unrelatedField: 'unrelatedValue', + wrapper: ({ children }) => + wrapper({ + children, + overrides: { + filters: { + unrelatedField: 'unrelatedValue', + }, }, - }, - }, + }), }, ); - await waitForNextUpdate(); - - expect(result.current.filters.unrelatedField).toEqual('unrelatedValue'); + await waitFor(() => { + expect(result.current.filters.unrelatedField).toEqual('unrelatedValue'); + }); }); }); @@ -240,14 +245,15 @@ describe('SearchFilter.hooks', () => { it('should return resolved values of provided async function', async () => { const expectedValues = ['value1', 'value2']; const asyncFn = () => Promise.resolve(expectedValues); - const { result, waitForNextUpdate } = renderHook(() => + const { result } = renderHook(() => useAsyncFilterValues(asyncFn, '', undefined, 1000), ); expect(result.current.loading).toEqual(true); - jest.runAllTimers(); - await waitForNextUpdate(); + await act(async () => { + jest.runAllTimers(); + }); expect(result.current.loading).toEqual(false); expect(result.current.value).toEqual(expectedValues); @@ -261,11 +267,15 @@ describe('SearchFilter.hooks', () => { expect(asyncFn).not.toHaveBeenCalled(); // Advance timers by 600ms - jest.advanceTimersByTime(600); + await act(async () => { + jest.advanceTimersByTime(600); + }); expect(asyncFn).not.toHaveBeenCalled(); // Another 600ms to exceed the 1000ms debounce - jest.advanceTimersByTime(600); + await act(async () => { + jest.advanceTimersByTime(600); + }); expect(asyncFn).toHaveBeenCalled(); }); @@ -273,21 +283,23 @@ describe('SearchFilter.hooks', () => { const asyncFn = jest .fn() .mockImplementation((x: string) => Promise.resolve([x])); - const { rerender, waitForNextUpdate } = renderHook( + const { rerender } = renderHook( (props: { inputValue: string } = { inputValue: '' }) => useAsyncFilterValues(asyncFn, props.inputValue, undefined, 1000), ); expect(asyncFn).not.toHaveBeenCalled(); - jest.runAllTimers(); - await waitForNextUpdate(); + await act(async () => { + jest.runAllTimers(); + }); expect(asyncFn).toHaveBeenCalledTimes(1); expect(asyncFn).toHaveBeenCalledWith(''); // Re-render with different input value. rerender({ inputValue: 'somethingElse' }); - jest.runAllTimers(); - await waitForNextUpdate(); + await act(async () => { + jest.runAllTimers(); + }); expect(asyncFn).toHaveBeenCalledTimes(2); expect(asyncFn).toHaveBeenLastCalledWith('somethingElse'); }); @@ -295,15 +307,16 @@ describe('SearchFilter.hooks', () => { it('should not call provided method more than once when re-rendered with same input', async () => { const expectedValues = ['value1', 'value2']; const asyncFn = jest.fn().mockResolvedValue(expectedValues); - const { rerender, waitForNextUpdate } = renderHook( + const { rerender } = renderHook( (props: { inputValue: string } = { inputValue: '' }) => useAsyncFilterValues(asyncFn, props.inputValue, undefined, 1000), ); expect(asyncFn).not.toHaveBeenCalled(); - jest.runAllTimers(); - await waitForNextUpdate(); + await act(async () => { + jest.runAllTimers(); + }); expect(asyncFn).toHaveBeenCalledTimes(1); // Re-render multiple times with the same input. diff --git a/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.tsx b/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.tsx index 2a3ae1e24c..ea1817193c 100644 --- a/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.tsx +++ b/plugins/search-react/src/components/SearchResultGroup/SearchResultGroup.tsx @@ -193,7 +193,7 @@ export const SearchResultGroupTextFilterField = ( contentEditable suppressContentEditableWarning > - {value} + {value?.toString()} </Typography> </SearchResultGroupFilterFieldLayout> ); @@ -377,7 +377,7 @@ export function SearchResultGroupLayout<FilterOption>( filterOptions, renderFilterOption = filterOption => ( <MenuItem key={String(filterOption)} value={String(filterOption)}> - {filterOption} + {String(filterOption)} </MenuItem> ), filterFields, diff --git a/plugins/search-react/src/context/SearchContext.test.tsx b/plugins/search-react/src/context/SearchContext.test.tsx index df71a848b0..5aa217553f 100644 --- a/plugins/search-react/src/context/SearchContext.test.tsx +++ b/plugins/search-react/src/context/SearchContext.test.tsx @@ -15,8 +15,13 @@ */ import { configApiRef } from '@backstage/core-plugin-api'; -import { render, screen, waitFor } from '@testing-library/react'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { + render, + screen, + waitFor, + act, + renderHook, +} from '@testing-library/react'; import { MockConfigApi, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { @@ -70,10 +75,8 @@ describe('SearchContext', () => { }); it('Throws error when no context is set', () => { - const { result } = renderHook(() => useSearch()); - - expect(result.error).toEqual( - Error('useSearch must be used within a SearchContextProvider'), + expect(() => renderHook(() => useSearch())).toThrow( + 'useSearch must be used within a SearchContextProvider', ); }); @@ -82,203 +85,188 @@ describe('SearchContext', () => { expect(hook.result.current).toEqual(false); - const { result, waitForNextUpdate } = renderHook( - () => useSearchContextCheck(), - { - wrapper, - initialProps: { - initialState, - }, - }, - ); + const { result } = renderHook(() => useSearchContextCheck(), { + wrapper: ({ children }) => wrapper({ children, initialState }), + }); - await waitForNextUpdate(); - - expect(result.current).toEqual(true); + await waitFor(() => { + expect(result.current).toEqual(true); + }); }); describe('Uses initial state values', () => { it('Uses default initial state values', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { + const { result } = renderHook(() => useSearch(), { wrapper, }); - await waitForNextUpdate(); - - expect(result.current).toEqual( - expect.objectContaining({ - term: '', - types: [], - filters: {}, - pageLimit: undefined, - pageCursor: undefined, - }), - ); + await waitFor(() => { + expect(result.current).toEqual( + expect.objectContaining({ + term: '', + types: [], + filters: {}, + pageLimit: undefined, + pageCursor: undefined, + }), + ); + }); }); it('Uses provided initial state values', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); - - expect(result.current).toEqual(expect.objectContaining(initialState)); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); }); it('Uses page limit provided via config api', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - config: { - search: { - query: { - pageLimit: 100, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => + wrapper({ + children, + initialState, + config: { + search: { + query: { + pageLimit: 100, + }, }, }, - }, - }, + }), }); - await waitForNextUpdate(); - - expect(result.current).toEqual( - expect.objectContaining({ ...initialState, pageLimit: 100 }), - ); + await waitFor(() => { + expect(result.current).toEqual( + expect.objectContaining({ ...initialState, pageLimit: 100 }), + ); + }); }); }); describe('Resets cursor', () => { it('When term is cleared', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState: { - ...initialState, - term: 'first term', - pageCursor: 'SOMEPAGE', - }, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => + wrapper({ + children, + initialState: { + ...initialState, + term: 'first term', + pageCursor: 'SOMEPAGE', + }, + }), }); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.term).toEqual('first term'); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + }); - expect(result.current.term).toEqual('first term'); - expect(result.current.pageCursor).toEqual('SOMEPAGE'); - - act(() => { + await act(async () => { result.current.setTerm(''); }); - await waitForNextUpdate(); - expect(result.current.pageCursor).toBeUndefined(); }); it('When term is set (and different from previous)', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState: { - ...initialState, - term: 'first term', - pageCursor: 'SOMEPAGE', - }, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => + wrapper({ + children, + initialState: { + ...initialState, + term: 'first term', + pageCursor: 'SOMEPAGE', + }, + }), }); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.term).toEqual('first term'); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + }); - expect(result.current.term).toEqual('first term'); - expect(result.current.pageCursor).toEqual('SOMEPAGE'); - - act(() => { + await act(async () => { result.current.setTerm('second term'); }); - await waitForNextUpdate(); - expect(result.current.pageCursor).toBeUndefined(); }); it('When filters are cleared', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState: { - ...initialState, - term: 'first term', - filters: { foo: 'bar' }, - pageCursor: 'SOMEPAGE', - }, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => + wrapper({ + children, + initialState: { + ...initialState, + term: 'first term', + filters: { foo: 'bar' }, + pageCursor: 'SOMEPAGE', + }, + }), }); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.filters).toEqual({ foo: 'bar' }); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + }); - expect(result.current.filters).toEqual({ foo: 'bar' }); - expect(result.current.pageCursor).toEqual('SOMEPAGE'); - - act(() => { + await act(async () => { result.current.setFilters({}); }); - await waitForNextUpdate(); - expect(result.current.pageCursor).toBeUndefined(); }); it('When filters are set (and different from previous)', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState: { - ...initialState, - term: 'first term', - filters: { foo: 'bar' }, - pageCursor: 'SOMEPAGE', - }, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => + wrapper({ + children, + initialState: { + ...initialState, + term: 'first term', + filters: { foo: 'bar' }, + pageCursor: 'SOMEPAGE', + }, + }), }); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current.filters).toEqual({ foo: 'bar' }); + expect(result.current.pageCursor).toEqual('SOMEPAGE'); + }); - expect(result.current.filters).toEqual({ foo: 'bar' }); - expect(result.current.pageCursor).toEqual('SOMEPAGE'); - - act(() => { + await act(async () => { result.current.setFilters({ foo: 'test' }); }); - await waitForNextUpdate(); - expect(result.current.pageCursor).toBeUndefined(); }); }); describe('Performs search (and sets results)', () => { it('When term is set', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const term = 'term'; - act(() => { + await act(async () => { result.current.setTerm(term); }); - await waitForNextUpdate(); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ term, types: ['*'], @@ -287,23 +275,20 @@ describe('SearchContext', () => { }); it('When types is set', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const types = ['type']; - act(() => { + await act(async () => { result.current.setTypes(types); }); - await waitForNextUpdate(); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ types, term: '', @@ -312,23 +297,20 @@ describe('SearchContext', () => { }); it('When filters are set', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const filters = { filter: 'filter' }; - act(() => { + await act(async () => { result.current.setFilters(filters); }); - await waitForNextUpdate(); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ filters, term: '', @@ -337,23 +319,20 @@ describe('SearchContext', () => { }); it('When page limit is set', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const pageLimit = 30; - act(() => { + await act(async () => { result.current.setPageLimit(pageLimit); }); - await waitForNextUpdate(); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ pageLimit, term: '', @@ -363,23 +342,20 @@ describe('SearchContext', () => { }); it('When page cursor is set', async () => { - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); const pageCursor = 'SOMEPAGE'; - act(() => { + await act(async () => { result.current.setPageCursor(pageCursor); }); - await waitForNextUpdate(); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ pageCursor, term: '', @@ -394,24 +370,21 @@ describe('SearchContext', () => { nextPageCursor: 'NEXT', }); - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); expect(result.current.fetchNextPage).toBeDefined(); expect(result.current.fetchPreviousPage).toBeUndefined(); - act(() => { + await act(async () => { result.current.fetchNextPage!(); }); - await waitForNextUpdate(); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ term: '', types: ['*'], @@ -426,24 +399,21 @@ describe('SearchContext', () => { previousPageCursor: 'PREVIOUS', }); - const { result, waitForNextUpdate } = renderHook(() => useSearch(), { - wrapper, - initialProps: { - initialState, - }, + const { result } = renderHook(() => useSearch(), { + wrapper: ({ children }) => wrapper({ children, initialState }), }); - await waitForNextUpdate(); + await waitFor(() => { + expect(result.current).toEqual(expect.objectContaining(initialState)); + }); expect(result.current.fetchNextPage).toBeUndefined(); expect(result.current.fetchPreviousPage).toBeDefined(); - act(() => { + await act(async () => { result.current.fetchPreviousPage!(); }); - await waitForNextUpdate(); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ term: '', types: ['*'], diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 714e4ef1de..ff8d87c347 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,45 @@ # @backstage/plugin-search +## 1.4.1 + +### Patch Changes + +- e5a2956dd2: Create an experimental search plugin that is compatible with the declarative integration system, it is exported from `/alpha` subpath. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 0296f272b4: Minor internal code cleanup. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/version-bridge@1.0.6 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## 1.4.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/version-bridge@1.0.5 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 1.4.1-next.1 ### Patch Changes diff --git a/plugins/search/alpha-api-report.md b/plugins/search/alpha-api-report.md index 5799ff5cd6..99f3d07b57 100644 --- a/plugins/search/alpha-api-report.md +++ b/plugins/search/alpha-api-report.md @@ -5,9 +5,15 @@ ```ts import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; +import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin< + { + root: RouteRef<undefined>; + }, + {} +>; export default _default; // @alpha (undocumented) diff --git a/plugins/search/package.json b/plugins/search/package.json index 6067d0004c..23abaefa1d 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.1-next.1", + "version": "1.4.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -66,8 +66,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -75,10 +75,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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", "history": "^5.0.0", "msw": "^1.0.0" diff --git a/plugins/search/src/alpha.tsx b/plugins/search/src/alpha.tsx index 6d74c85d49..14e7067dfa 100644 --- a/plugins/search/src/alpha.tsx +++ b/plugins/search/src/alpha.tsx @@ -28,7 +28,6 @@ import { useSidebarPinState, } from '@backstage/core-components'; import { - createRouteRef, useApi, DiscoveryApi, IdentityApi, @@ -64,9 +63,11 @@ import { SearchResult } from '@backstage/plugin-search-common'; import { searchApiRef } from '@backstage/plugin-search-react'; import { searchResultItemExtensionData } from '@backstage/plugin-search-react/alpha'; +import { rootRouteRef } from './plugin'; import { SearchClient } from './apis'; import { SearchType } from './components/SearchType'; import { UrlUpdater } from './components/SearchPage/SearchPage'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; /** @alpha */ export const SearchApi = createApiExtension({ @@ -95,12 +96,10 @@ const useSearchPageStyles = makeStyles((theme: Theme) => ({ }, })); -const searchRouteRef = createRouteRef({ id: 'plugin.search.page' }); - /** @alpha */ export const SearchPage = createPageExtension({ id: 'plugin.search.page', - routeRef: searchRouteRef, + routeRef: convertLegacyRouteRef(rootRouteRef), configSchema: createSchemaFromZod(z => z.object({ path: z.string().default('/search'), @@ -198,22 +197,24 @@ export const SearchPage = createPageExtension({ <Grid item xs> <SearchPagination /> <SearchResults> - {({ results }) => - results.map((result, index) => { - const { noTrack } = config; - const { document, ...rest } = result; - const SearchResultListItem = - getResultItemComponent(result); - return ( - <SearchResultListItem - {...rest} - key={index} - result={document} - noTrack={noTrack} - /> - ); - }) - } + {({ results }) => ( + <> + {results.map((result, index) => { + const { noTrack } = config; + const { document, ...rest } = result; + const SearchResultListItem = + getResultItemComponent(result); + return ( + <SearchResultListItem + {...rest} + key={index} + result={document} + noTrack={noTrack} + /> + ); + })} + </> + )} </SearchResults> <SearchResultPager /> </Grid> @@ -235,13 +236,16 @@ export const SearchPage = createPageExtension({ /** @alpha */ export const SearchNavItem = createNavItemExtension({ id: 'plugin.search.nav.index', - routeRef: searchRouteRef, + routeRef: convertLegacyRouteRef(rootRouteRef), title: 'Search', icon: SearchIcon, }); /** @alpha */ export default createPlugin({ - id: 'plugin.search', + id: 'search', extensions: [SearchApi, SearchPage, SearchNavItem], + routes: { + root: convertLegacyRouteRef(rootRouteRef), + }, }); diff --git a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.tsx b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.tsx index 47ee15c7f3..19dfd8190d 100644 --- a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.tsx +++ b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.tsx @@ -57,18 +57,11 @@ export const HomePageSearchBar = (props: HomePageSearchBarProps) => { handleSearch({ query: ref.current?.value ?? '' }); }, [handleSearch]); - const handleChange = useCallback( - value => { - setQuery(value); - }, - [setQuery], - ); - return ( <SearchBarBase value={query} onSubmit={handleSubmit} - onChange={handleChange} + onChange={setQuery} inputProps={{ ref }} InputProps={{ ...props.InputProps, diff --git a/plugins/search/src/components/SearchModal/useSearchModal.test.tsx b/plugins/search/src/components/SearchModal/useSearchModal.test.tsx index e21f864ac2..a78f9b92af 100644 --- a/plugins/search/src/components/SearchModal/useSearchModal.test.tsx +++ b/plugins/search/src/components/SearchModal/useSearchModal.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook } from '@testing-library/react'; import { useSearchModal } from './useSearchModal'; import { BrowserRouter, Router } from 'react-router-dom'; import { createMemoryHistory } from 'history'; diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index 0e2a3d446c..77895eb2f1 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-sentry +## 0.5.10 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 0.5.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + ## 0.5.10-next.1 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index b6f502baee..3856270628 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.10-next.1", + "version": "0.5.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -50,8 +50,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -59,9 +59,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/luxon": "^3.0.0", "cross-fetch": "^3.1.5", diff --git a/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.tsx b/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.tsx index 60ee6b7dbf..8f336c629b 100644 --- a/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.tsx +++ b/plugins/sentry/src/components/SentryIssuesTable/SentryIssuesTable.tsx @@ -74,12 +74,15 @@ const SentryIssuesTable = (props: SentryIssuesTableProps) => { const { sentryIssues, statsFor, tableOptions } = props; const [selected, setSelected] = useState(ONE_DAY_IN_MILLIS); - const filterByDate = useCallback((issue, selectedFilter) => { - return ( - DateTime.fromISO(issue.lastSeen) > - DateTime.now().minus(Duration.fromMillis(selectedFilter)) - ); - }, []); + const filterByDate = useCallback( + (issue: SentryIssue, selectedFilter: number) => { + return ( + DateTime.fromISO(issue.lastSeen) > + DateTime.now().minus(Duration.fromMillis(selectedFilter)) + ); + }, + [], + ); const [filteredIssues, setFilteredIssues] = useState( sentryIssues.filter(i => filterByDate(i, selected)), ); diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index 29eb3eefc5..6774c7eaf2 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-shortcuts +## 0.3.15 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + +## 0.3.15-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/types@1.1.1 + ## 0.3.15-next.1 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index b3f3d53858..c38125d561 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.15-next.1", + "version": "0.3.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -44,8 +44,8 @@ "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -53,9 +53,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/zen-observable": "^0.8.2", "msw": "^1.0.0" diff --git a/plugins/sonarqube-backend/CHANGELOG.md b/plugins/sonarqube-backend/CHANGELOG.md index d5f8999191..caf2a677c1 100644 --- a/plugins/sonarqube-backend/CHANGELOG.md +++ b/plugins/sonarqube-backend/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-sonarqube-backend +## 0.2.8 + +### Patch Changes + +- a5d592d0ad: Added support for the [new backend system](https://backstage.io/docs/backend-system/) +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/config@1.1.1 + +## 0.2.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.2.7-next.1 ### Patch Changes diff --git a/plugins/sonarqube-backend/package.json b/plugins/sonarqube-backend/package.json index 1ff45c2ac9..63592380db 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.7-next.1", + "version": "0.2.8", "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 5fea1d2e9e..af370f6d1a 100644 --- a/plugins/sonarqube-react/CHANGELOG.md +++ b/plugins/sonarqube-react/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-sonarqube-react +## 0.1.9 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/catalog-model@1.4.3 + +## 0.1.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + ## 0.1.9-next.0 ### Patch Changes diff --git a/plugins/sonarqube-react/package.json b/plugins/sonarqube-react/package.json index 6e1adb42f9..c643df3702 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.9-next.0", + "version": "0.1.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,8 +45,8 @@ "@backstage/core-plugin-api": "workspace:^" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index d951104286..3ed88667a9 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-sonarqube +## 0.7.6 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + - @backstage/plugin-sonarqube-react@0.1.9 + +## 0.7.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-sonarqube-react@0.1.9-next.1 + ## 0.7.6-next.1 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index b68c28b76b..00d6c494db 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.7.6-next.1", + "version": "0.7.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -53,8 +53,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -62,9 +62,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index 1117cfee3e..4b1ac632d1 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-splunk-on-call +## 0.4.14 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/theme@0.4.3 + +## 0.4.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/theme@0.4.3-next.0 + ## 0.4.14-next.1 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index b677f6f425..e07a08254f 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.14-next.1", + "version": "0.4.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -48,8 +48,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -57,9 +57,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/luxon": "^3.0.0", "msw": "^1.0.0" diff --git a/plugins/splunk-on-call/src/components/Incident/Incidents.test.tsx b/plugins/splunk-on-call/src/components/Incident/Incidents.test.tsx index 665dd3281c..9b8d5feb97 100644 --- a/plugins/splunk-on-call/src/components/Incident/Incidents.test.tsx +++ b/plugins/splunk-on-call/src/components/Incident/Incidents.test.tsx @@ -34,8 +34,12 @@ const apis = TestApiRegistry.from( ); describe('Incidents', () => { + beforeEach(() => { + jest.useFakeTimers(); + }); afterEach(() => { jest.resetAllMocks(); + jest.useRealTimers(); }); it('Renders an empty state when there are no incidents', async () => { @@ -47,13 +51,10 @@ describe('Incidents', () => { <Incidents readOnly={false} refreshIncidents={false} team="test" /> </ApiProvider>, ); - await waitFor(() => !screen.queryByTestId('progress')); - await waitFor( - () => - expect( - screen.getByText('Nice! No incidents found!'), - ).toBeInTheDocument(), - { timeout: 2000 }, + jest.advanceTimersByTime(2000); + await waitFor(() => expect(screen.queryByTestId('progress')).toBe(null)); + await waitFor(() => + expect(screen.getByText('Nice! No incidents found!')).toBeInTheDocument(), ); }); @@ -66,15 +67,14 @@ describe('Incidents', () => { <Incidents readOnly={false} team="test" refreshIncidents={false} /> </ApiProvider>, ); - await waitFor(() => !screen.queryByTestId('progress')); - await waitFor( - () => - expect( - screen.getByText('user', { - exact: false, - }), - ).toBeInTheDocument(), - { timeout: 2000 }, + jest.advanceTimersByTime(2000); + await waitFor(() => expect(screen.queryByTestId('progress')).toBe(null)); + await waitFor(() => + expect( + screen.getByText('user', { + exact: false, + }), + ).toBeInTheDocument(), ); expect(screen.getByText('test-incident')).toBeInTheDocument(); expect(screen.getByTitle('Acknowledged')).toBeInTheDocument(); @@ -93,15 +93,14 @@ describe('Incidents', () => { <Incidents readOnly team="test" refreshIncidents={false} /> </ApiProvider>, ); - await waitFor(() => !screen.queryByTestId('progress')); - await waitFor( - () => - expect( - screen.getByText('user', { - exact: false, - }), - ).toBeInTheDocument(), - { timeout: 2000 }, + jest.advanceTimersByTime(2000); + await waitFor(() => expect(screen.queryByTestId('progress')).toBe(null)); + await waitFor(() => + expect( + screen.getByText('user', { + exact: false, + }), + ).toBeInTheDocument(), ); expect(screen.getByText('test-incident')).toBeInTheDocument(); expect(screen.getByLabelText('Status warning')).toBeInTheDocument(); @@ -127,15 +126,14 @@ describe('Incidents', () => { <Incidents readOnly={false} team="test" refreshIncidents={false} /> </ApiProvider>, ); - await waitFor(() => !screen.queryByTestId('progress')); - await waitFor( - () => - expect( - screen.getByText( - 'Error encountered while fetching information. Error occurred', - ), - ).toBeInTheDocument(), - { timeout: 2000 }, + jest.advanceTimersByTime(2000); + await waitFor(() => expect(screen.queryByTestId('progress')).toBe(null)); + await waitFor(() => + expect( + screen.getByText( + 'Error encountered while fetching information. Error occurred', + ), + ).toBeInTheDocument(), ); }); }); diff --git a/plugins/stack-overflow-backend/CHANGELOG.md b/plugins/stack-overflow-backend/CHANGELOG.md index 149dd6913f..bb83becff1 100644 --- a/plugins/stack-overflow-backend/CHANGELOG.md +++ b/plugins/stack-overflow-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-stack-overflow-backend +## 0.2.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## 0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 0.2.9-next.1 ### Patch Changes diff --git a/plugins/stack-overflow-backend/package.json b/plugins/stack-overflow-backend/package.json index 57c8d6bcfc..320d35d3b6 100644 --- a/plugins/stack-overflow-backend/package.json +++ b/plugins/stack-overflow-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-stack-overflow-backend", - "version": "0.2.9-next.1", + "version": "0.2.10", "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 d0866a9211..7ff52c4364 100644 --- a/plugins/stack-overflow/CHANGELOG.md +++ b/plugins/stack-overflow/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-stack-overflow +## 0.1.21 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-home-react@0.1.4 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## 0.1.21-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-home-react@0.1.4-next.2 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 0.1.21-next.1 ### Patch Changes diff --git a/plugins/stack-overflow/package.json b/plugins/stack-overflow/package.json index eef133b305..f60800d1f9 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.21-next.1", + "version": "0.1.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -38,7 +38,7 @@ "@backstage/theme": "workspace:^", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", - "@testing-library/jest-dom": "^5.10.1", + "@testing-library/jest-dom": "^6.0.0", "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", "lodash": "^4.17.21", @@ -46,8 +46,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -55,8 +55,8 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/react": "^12.1.3", + "@testing-library/dom": "^9.0.0", + "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/stackstorm/CHANGELOG.md b/plugins/stackstorm/CHANGELOG.md index 6734c7dd27..d831792629 100644 --- a/plugins/stackstorm/CHANGELOG.md +++ b/plugins/stackstorm/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-stackstorm +## 0.1.7 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.1.7-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.1.7-next.1 ### Patch Changes diff --git a/plugins/stackstorm/package.json b/plugins/stackstorm/package.json index bd945feb36..76f9958812 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.7-next.1", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -54,9 +54,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md index f8f70f1c0c..f319b515ec 100644 --- a/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md +++ b/plugins/tech-insights-backend-module-jsonfc/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-tech-insights-backend-module-jsonfc +## 0.1.38 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/plugin-tech-insights-node@0.4.12 + - @backstage/config@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## 0.1.38-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-tech-insights-node@0.4.12-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.1.37-next.1 ### Patch Changes diff --git a/plugins/tech-insights-backend-module-jsonfc/package.json b/plugins/tech-insights-backend-module-jsonfc/package.json index bd7b2c2226..17fa4702e3 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.37-next.1", + "version": "0.1.38", "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 cbafe8f3b5..fcd5520d29 100644 --- a/plugins/tech-insights-backend/CHANGELOG.md +++ b/plugins/tech-insights-backend/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-tech-insights-backend +## 0.5.20 + +### Patch Changes + +- cc7dddfa7f: Increase the maximum allowed length of an entity filter for tech insights fact schemas. +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-tech-insights-node@0.4.12 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## 0.5.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/plugin-tech-insights-node@0.4.12-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.5.19-next.1 ### Patch Changes diff --git a/plugins/tech-insights-backend/package.json b/plugins/tech-insights-backend/package.json index a89907fd62..1dda0595f5 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.19-next.1", + "version": "0.5.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.test.ts b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.test.ts index fe3c050e69..5473b28c62 100644 --- a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.test.ts +++ b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.test.ts @@ -64,15 +64,15 @@ const testFactRetriever: FactRetriever = { ]; }), }; + const defaultCadence = '1 * * * *'; + describe('FactRetrieverEngine', () => { let engine: FactRetrieverEngine; type FactSchemaAssertionCallback = ( factSchemaDefinition: FactSchemaDefinition, ) => void; - jest.setTimeout(15000); - type FactInsertionAssertionCallback = ({ facts, id, diff --git a/plugins/tech-insights-node/CHANGELOG.md b/plugins/tech-insights-node/CHANGELOG.md index 549c427075..37117bc0d8 100644 --- a/plugins/tech-insights-node/CHANGELOG.md +++ b/plugins/tech-insights-node/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-tech-insights-node +## 0.4.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/config@1.1.1 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## 0.4.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/config@1.1.1-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.4.11-next.1 ### Patch Changes diff --git a/plugins/tech-insights-node/package.json b/plugins/tech-insights-node/package.json index 980acd1a4b..23863a774d 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.11-next.1", + "version": "0.4.12", "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 053f9d97ed..83644ecdab 100644 --- a/plugins/tech-insights/CHANGELOG.md +++ b/plugins/tech-insights/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/plugin-tech-insights +## 0.3.17 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 21f409d776: Export `ScorecardInfo` and `ScorecardsList` components to be able to use manually queried check results directly. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + +## 0.3.17-next.2 + +### Patch Changes + +- 21f409d776: Export `ScorecardInfo` and `ScorecardsList` components to be able to use manually queried check results directly. +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/types@1.1.1 + - @backstage/plugin-tech-insights-common@0.2.12 + ## 0.3.17-next.1 ### Patch Changes diff --git a/plugins/tech-insights/package.json b/plugins/tech-insights/package.json index 142a24cb9b..7735fb3719 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.17-next.1", + "version": "0.3.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -45,8 +45,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -54,9 +54,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index a7684ba5c8..276c50be04 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,30 @@ # @backstage/plugin-tech-radar +## 0.6.9 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- c09d2fa1d6: Added experimental support for the declarative integration. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/theme@0.4.3 + +## 0.6.9-next.2 + +### Patch Changes + +- 0b55f773a7: Removed some unused dependencies +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/theme@0.4.3-next.0 + ## 0.6.9-next.1 ### Patch Changes diff --git a/plugins/tech-radar/alpha-api-report.md b/plugins/tech-radar/alpha-api-report.md index c54f692982..da8f12cf0e 100644 --- a/plugins/tech-radar/alpha-api-report.md +++ b/plugins/tech-radar/alpha-api-report.md @@ -5,9 +5,15 @@ ```ts import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; +import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin< + { + root: RouteRef<undefined>; + }, + {} +>; export default _default; // @alpha (undocumented) diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index e99565bb67..82fd7ca147 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.9-next.1", + "version": "0.6.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -56,12 +56,11 @@ "@types/react": "^16.13.1 || ^17.0.0", "color": "^4.0.1", "d3-force": "^3.0.0", - "prop-types": "^15.7.2", "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -69,9 +68,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/color": "^3.0.1", "@types/d3-force": "^3.0.0", diff --git a/plugins/tech-radar/src/alpha.tsx b/plugins/tech-radar/src/alpha.tsx index 6a2ec882ba..78230c0337 100644 --- a/plugins/tech-radar/src/alpha.tsx +++ b/plugins/tech-radar/src/alpha.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { createApiFactory, createRouteRef } from '@backstage/core-plugin-api'; +import { createApiFactory } from '@backstage/core-plugin-api'; import { createApiExtension, createPageExtension, @@ -24,14 +24,14 @@ import { import React from 'react'; import { techRadarApiRef } from './api'; import { SampleTechRadarApi } from './sample'; - -const techRadarRouteRef = createRouteRef({ id: 'plugin.techradar.page' }); +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; +import { rootRouteRef } from './plugin'; /** @alpha */ export const TechRadarPage = createPageExtension({ id: 'plugin.techradar.page', defaultPath: '/tech-radar', - routeRef: techRadarRouteRef, + routeRef: convertLegacyRouteRef(rootRouteRef), configSchema: createSchemaFromZod(z => z.object({ title: z.string().default('Tech Radar'), @@ -59,4 +59,7 @@ const sampleTechRadarApi = createApiExtension({ export default createPlugin({ id: 'tech-radar', extensions: [TechRadarPage, sampleTechRadarApi], + routes: { + root: convertLegacyRouteRef(rootRouteRef), + }, }); diff --git a/plugins/tech-radar/src/plugin.ts b/plugins/tech-radar/src/plugin.ts index 7f042a1b6f..3a8e0a5f2d 100644 --- a/plugins/tech-radar/src/plugin.ts +++ b/plugins/tech-radar/src/plugin.ts @@ -23,7 +23,7 @@ import { createApiFactory, } from '@backstage/core-plugin-api'; -const rootRouteRef = createRouteRef({ +export const rootRouteRef = createRouteRef({ id: 'tech-radar', }); diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index ea84b35661..e215d3d842 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.22 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog@1.14.0 + - @backstage/test-utils@1.4.4 + - @backstage/core-app-api@1.11.0 + - @backstage/plugin-techdocs@1.8.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + +## 1.0.22-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/plugin-techdocs@1.7.1-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/plugin-catalog@1.14.0-next.2 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/test-utils@1.4.4-next.2 + - @backstage/plugin-techdocs-react@1.1.12-next.2 + ## 1.0.22-next.1 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index 3a0f83ad6f..b65cc1d2b1 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.22-next.1", + "version": "1.0.22", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -46,22 +46,21 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", - "@testing-library/react": "^12.1.3", + "@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": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/dev-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@testing-library/dom": "^9.0.0", + "@testing-library/jest-dom": "^6.0.0", "@testing-library/user-event": "^14.0.0", "msw": "^1.0.0" }, diff --git a/plugins/techdocs-addons-test-utils/src/test-utils.tsx b/plugins/techdocs-addons-test-utils/src/test-utils.tsx index 1a921437b1..865e8c0d3b 100644 --- a/plugins/techdocs-addons-test-utils/src/test-utils.tsx +++ b/plugins/techdocs-addons-test-utils/src/test-utils.tsx @@ -19,7 +19,6 @@ import React, { ReactElement } from 'react'; // Shadow DOM support for the simple and complete DOM testing utilities // https://github.com/testing-library/dom-testing-library/issues/742#issuecomment-674987855 import { screen } from 'testing-library__dom'; -import { renderToStaticMarkup } from 'react-dom/server'; import { Route } from 'react-router-dom'; import { act, render } from '@testing-library/react'; @@ -39,6 +38,13 @@ import { catalogPlugin } from '@backstage/plugin-catalog'; import { searchApiRef } from '@backstage/plugin-search-react'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; +// Since React 18 react-dom/server eagerly uses TextEncoder, so lazy load and make it available globally first +if (!global.TextEncoder) { + global.TextEncoder = require('util').TextEncoder; +} +const { renderToStaticMarkup } = + require('react-dom/server') as typeof import('react-dom/server'); + const techdocsApi = { getTechDocsMetadata: jest.fn(), getEntityMetadata: jest.fn(), diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 2723867071..ad2b8f67ed 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,59 @@ # @backstage/plugin-techdocs-backend +## 1.8.0 + +### Minor Changes + +- 344cfbcfbc: Allow prepared directory clean up for custom preparers + + When using custom preparer for TechDocs, the `preparedDir` might + end up taking disk space. This requires all custom preparers to + implement a new method `shouldCleanPreparedDirectory` which indicates + whether the prepared directory should be cleaned after generation. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-techdocs-node@1.9.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/plugin-search-backend-module-techdocs@0.1.10 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + - @backstage/plugin-catalog-common@1.0.17 + - @backstage/plugin-permission-common@0.7.9 + - @backstage/plugin-search-common@1.2.7 + +## 1.8.0-next.2 + +### Minor Changes + +- 344cfbcfbc: Allow prepared directory clean up for custom preparers + + When using custom preparer for TechDocs, the `preparedDir` might + end up taking disk space. This requires all custom preparers to + implement a new method `shouldCleanPreparedDirectory` which indicates + whether the prepared directory should be cleaned after generation. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-techdocs-node@1.9.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.1.10-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-catalog-common@1.0.17-next.0 + - @backstage/plugin-permission-common@0.7.9-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 1.7.2-next.1 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index 821457e518..c3e2ee0708 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.7.2-next.1", + "version": "1.8.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", diff --git a/plugins/techdocs-backend/src/service/standaloneServer.ts b/plugins/techdocs-backend/src/service/standaloneServer.ts index 7e7e8b24f8..ce981633ca 100644 --- a/plugins/techdocs-backend/src/service/standaloneServer.ts +++ b/plugins/techdocs-backend/src/service/standaloneServer.ts @@ -18,7 +18,7 @@ import { CacheManager, createServiceBuilder, DockerContainerRunner, - SingleHostDiscovery, + HostDiscovery, UrlReader, } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; @@ -51,7 +51,7 @@ export async function startStandaloneServer( }, }, }); - const discovery = SingleHostDiscovery.fromConfig(config); + const discovery = HostDiscovery.fromConfig(config); const mockUrlReader: jest.Mocked<UrlReader> = { readUrl: jest.fn(), readTree: jest.fn(), diff --git a/plugins/techdocs-module-addons-contrib/CHANGELOG.md b/plugins/techdocs-module-addons-contrib/CHANGELOG.md index 3b4c893faa..37b6a46b20 100644 --- a/plugins/techdocs-module-addons-contrib/CHANGELOG.md +++ b/plugins/techdocs-module-addons-contrib/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-techdocs-module-addons-contrib +## 1.1.1 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + +## 1.1.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/integration@1.7.1-next.1 + - @backstage/theme@0.4.3-next.0 + - @backstage/plugin-techdocs-react@1.1.12-next.2 + ## 1.1.1-next.1 ### Patch Changes diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 53ccd6c244..cf92b0c969 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.1-next.1", + "version": "1.1.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -49,8 +49,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -59,9 +59,9 @@ "@backstage/dev-utils": "workspace:^", "@backstage/plugin-techdocs-addons-test-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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" diff --git a/plugins/techdocs-node/CHANGELOG.md b/plugins/techdocs-node/CHANGELOG.md index a385a83136..2576313037 100644 --- a/plugins/techdocs-node/CHANGELOG.md +++ b/plugins/techdocs-node/CHANGELOG.md @@ -1,5 +1,53 @@ # @backstage/plugin-techdocs-node +## 1.9.0 + +### Minor Changes + +- 344cfbcfbc: Allow prepared directory clean up for custom preparers + + When using custom preparer for TechDocs, the `preparedDir` might + end up taking disk space. This requires all custom preparers to + implement a new method `shouldCleanPreparedDirectory` which indicates + whether the prepared directory should be cleaned after generation. + +- d06b30b050: Add possibility to use a mkdocs config file with a different name than `mkdocs.<yaml|yml> with the serve command using the `--mkdocs-config-file-name` argument + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + - @backstage/integration-aws-node@0.1.7 + - @backstage/plugin-search-common@1.2.7 + +## 1.9.0-next.2 + +### Minor Changes + +- 344cfbcfbc: Allow prepared directory clean up for custom preparers + + When using custom preparer for TechDocs, the `preparedDir` might + end up taking disk space. This requires all custom preparers to + implement a new method `shouldCleanPreparedDirectory` which indicates + whether the prepared directory should be cleaned after generation. + +- d06b30b050: Add possibility to use a mkdocs config file with a different name than `mkdocs.<yaml|yml> with the serve command using the `--mkdocs-config-file-name` argument + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/integration-aws-node@0.1.7-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + ## 1.8.2-next.1 ### Patch Changes diff --git a/plugins/techdocs-node/api-report.md b/plugins/techdocs-node/api-report.md index 11a9ecaa84..656db6ae36 100644 --- a/plugins/techdocs-node/api-report.md +++ b/plugins/techdocs-node/api-report.md @@ -89,9 +89,10 @@ export const getLocationForEntity: ( // @public @deprecated (undocumented) export const getMkDocsYml: ( inputDir: string, - siteOptions?: + options?: | { name?: string | undefined; + mkdocsConfigFileName?: string | undefined; } | undefined, ) => Promise<{ @@ -103,8 +104,9 @@ export const getMkDocsYml: ( // @public export const getMkdocsYml: ( inputDir: string, - siteOptions?: { + options?: { name?: string; + mkdocsConfigFileName?: string; }, ) => Promise<{ path: string; diff --git a/plugins/techdocs-node/package.json b/plugins/techdocs-node/package.json index 56bb4f86a4..712693f6af 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.8.2-next.1", + "version": "1.9.0", "main": "src/index.ts", "types": "src/index.ts", "publishConfig": { diff --git a/plugins/techdocs-node/src/stages/generate/helpers.test.ts b/plugins/techdocs-node/src/stages/generate/helpers.test.ts index 22940e9ce8..738bb6fc46 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.test.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.test.ts @@ -540,7 +540,7 @@ describe('helpers', () => { }); describe('getMkdocsYml', () => { - const siteOptions = { + const defaultOptions = { name: mockEntity.metadata.title, }; @@ -550,7 +550,7 @@ describe('helpers', () => { path: mkdocsPath, content, configIsTemporary, - } = await getMkdocsYml(mockDir.path, siteOptions); + } = await getMkdocsYml(mockDir.path, defaultOptions); expect(mkdocsPath).toBe(mockDir.resolve('mkdocs.yml')); expect(content).toBe(mkdocsYml.toString()); @@ -563,14 +563,14 @@ describe('helpers', () => { path: mkdocsPath, content, configIsTemporary, - } = await getMkdocsYml(mockDir.path, siteOptions); + } = await getMkdocsYml(mockDir.path, defaultOptions); expect(mkdocsPath).toBe(mockDir.resolve('mkdocs.yaml')); expect(content).toBe(mkdocsYml.toString()); expect(configIsTemporary).toBe(false); }); it('returns expected contents when default file is present', async () => { - const defaultSiteOptions = { + const options = { name: 'Default Test site name', }; const mockPathExists = jest.spyOn(fs, 'pathExists'); @@ -580,21 +580,49 @@ describe('helpers', () => { path: mkdocsPath, content, configIsTemporary, - } = await getMkdocsYml(mockDir.path, defaultSiteOptions); + } = await getMkdocsYml(mockDir.path, options); expect(mkdocsPath).toBe(mockDir.resolve('mkdocs.yml')); expect(content.split(/[\r\n]+/g)).toEqual( mkdocsDefaultYml.toString().split(/[\r\n]+/g), ); expect(configIsTemporary).toBe(true); + mockPathExists.mockRestore(); }); it('throws when neither .yml nor .yaml nor default file is present', async () => { const invalidInputDir = resolvePath(__filename); - await expect(getMkdocsYml(invalidInputDir, siteOptions)).rejects.toThrow( + await expect( + getMkdocsYml(invalidInputDir, defaultOptions), + ).rejects.toThrow( /Could not read MkDocs YAML config file mkdocs.yml or mkdocs.yaml or default for validation/, ); }); + + it('returns expected content when custom file is specified', async () => { + const options = { mkdocsConfigFileName: 'another-name.yaml' }; + mockDir.setContent({ 'another-name.yaml': mkdocsYml }); + + const { + path: mkdocsPath, + content, + configIsTemporary, + } = await getMkdocsYml(mockDir.path, options); + + expect(mkdocsPath).toBe(mockDir.resolve('another-name.yaml')); + + expect(content).toBe(mkdocsYml.toString()); + expect(configIsTemporary).toBe(false); + }); + + it('throws when specifying a specific mkdocs config file that does not exist', async () => { + const options = { mkdocsConfigFileName: 'another-name.yaml' }; + mockDir.setContent({ 'mkdocs.yml': mkdocsDefaultYml }); + + await expect(getMkdocsYml(mockDir.path, options)).rejects.toThrow( + /The specified file .* does not exist/, + ); + }); }); describe('validateMkdocsYaml', () => { diff --git a/plugins/techdocs-node/src/stages/generate/helpers.ts b/plugins/techdocs-node/src/stages/generate/helpers.ts index e16293f906..1450a4afba 100644 --- a/plugins/techdocs-node/src/stages/generate/helpers.ts +++ b/plugins/techdocs-node/src/stages/generate/helpers.ts @@ -185,21 +185,35 @@ export const generateMkdocsYml = async ( }; /** - * Finds and loads the contents of either an mkdocs.yml or mkdocs.yaml file, - * depending on which is present (MkDocs supports both as of v1.2.2). + * Finds and loads the contents of an mkdocs.yml, mkdocs.yaml file, a file + * with a specified name or an ad-hoc created file with minimal config. * @public * * @param inputDir - base dir to be searched for either an mkdocs.yml or mkdocs.yaml file. - * @param siteOptions - options for the site: `name` property will be used in mkdocs.yml for the - * required `site_name` property, default value is "Documentation Site" + * @param options - name: default mkdocs site_name to be used with a ad hoc file default value is "Documentation Site" + * mkdocsConfigFileName (optional): a non-default file name to be used as the config */ export const getMkdocsYml = async ( inputDir: string, - siteOptions?: { name?: string }, + options?: { name?: string; mkdocsConfigFileName?: string }, ): Promise<{ path: string; content: string; configIsTemporary: boolean }> => { let mkdocsYmlPath: string; let mkdocsYmlFileString: string; try { + if (options?.mkdocsConfigFileName) { + mkdocsYmlPath = path.join(inputDir, options.mkdocsConfigFileName); + if (!(await fs.pathExists(mkdocsYmlPath))) { + throw new Error(`The specified file ${mkdocsYmlPath} does not exist`); + } + + mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8'); + return { + path: mkdocsYmlPath, + content: mkdocsYmlFileString, + configIsTemporary: false, + }; + } + mkdocsYmlPath = path.join(inputDir, 'mkdocs.yaml'); if (await fs.pathExists(mkdocsYmlPath)) { mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8'); @@ -221,7 +235,7 @@ export const getMkdocsYml = async ( } // No mkdocs file, generate it - await generateMkdocsYml(inputDir, siteOptions); + await generateMkdocsYml(inputDir, options); mkdocsYmlFileString = await fs.readFile(mkdocsYmlPath, 'utf8'); } catch (error) { throw new ForwardedError( diff --git a/plugins/techdocs-react/CHANGELOG.md b/plugins/techdocs-react/CHANGELOG.md index 3e502df15d..42edbad969 100644 --- a/plugins/techdocs-react/CHANGELOG.md +++ b/plugins/techdocs-react/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-techdocs-react +## 1.1.12 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/version-bridge@1.0.6 + - @backstage/config@1.1.1 + +## 1.1.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/version-bridge@1.0.5 + ## 1.1.12-next.1 ### Patch Changes diff --git a/plugins/techdocs-react/package.json b/plugins/techdocs-react/package.json index 64df90080d..79d2b3cc17 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.12-next.1", + "version": "1.1.12", "publishConfig": { "access": "public", "main": "dist/index.esm.js", @@ -49,17 +49,16 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", "@backstage/theme": "workspace:^", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.0.0" + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^14.0.0" }, "files": [ "alpha", diff --git a/plugins/techdocs-react/src/context.test.tsx b/plugins/techdocs-react/src/context.test.tsx index 4800204f36..bcab445729 100644 --- a/plugins/techdocs-react/src/context.test.tsx +++ b/plugins/techdocs-react/src/context.test.tsx @@ -14,12 +14,16 @@ * limitations under the License. */ import React from 'react'; -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act, waitFor } from '@testing-library/react'; import { ThemeProvider } from '@material-ui/core'; import { lightTheme } from '@backstage/theme'; -import { MockAnalyticsApi, TestApiProvider } from '@backstage/test-utils'; +import { + MockAnalyticsApi, + MockConfigApi, + TestApiProvider, +} from '@backstage/test-utils'; import { Entity, CompoundEntityRef } from '@backstage/catalog-model'; import { analyticsApiRef, @@ -30,6 +34,7 @@ import { import { techdocsApiRef } from './api'; import { useTechDocsReaderPage, TechDocsReaderPageProvider } from './context'; import { TechDocsMetadata } from './types'; +import { JsonObject } from '@backstage/config'; const mockShadowRoot = () => { const div = document.createElement('div'); @@ -60,10 +65,6 @@ const techdocsApiMock = { getTechDocsMetadata: jest.fn().mockResolvedValue(mockTechDocsMetadata), }; -const configApiMock = { - getOptionalBoolean: jest.fn().mockReturnValue(undefined), -}; - const analyticsApiMock = new MockAnalyticsApi(); const wrapper = ({ @@ -72,16 +73,18 @@ const wrapper = ({ name: mockEntityMetadata.metadata.name, namespace: mockEntityMetadata.metadata.namespace!!, }, + config, children, }: { entityRef?: CompoundEntityRef; + config?: JsonObject; children: React.ReactNode; }) => ( <ThemeProvider theme={lightTheme}> <TestApiProvider apis={[ [analyticsApiRef, analyticsApiMock], - [configApiRef, configApiMock], + [configApiRef, new MockConfigApi(config ?? {})], [techdocsApiRef, techdocsApiMock], ]} > @@ -98,47 +101,32 @@ describe('useTechDocsReaderPage', () => { }); it('should set title', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useTechDocsReaderPage(), - { wrapper }, - ); + const { result } = renderHook(() => useTechDocsReaderPage(), { wrapper }); expect(result.current.title).toBe(''); - act(() => result.current.setTitle('test site title')); - - await waitForNextUpdate(); + await act(async () => result.current.setTitle('test site title')); expect(result.current.title).toBe('test site title'); }); it('should set subtitle', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useTechDocsReaderPage(), - { wrapper }, - ); + const { result } = renderHook(() => useTechDocsReaderPage(), { wrapper }); expect(result.current.subtitle).toBe(''); - act(() => result.current.setSubtitle('test site subtitle')); - - await waitForNextUpdate(); + await act(async () => result.current.setSubtitle('test site subtitle')); expect(result.current.subtitle).toBe('test site subtitle'); }); it('should set shadow root', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useTechDocsReaderPage(), - { wrapper }, - ); + const { result } = renderHook(() => useTechDocsReaderPage(), { wrapper }); // mock shadowroot const shadowRoot = mockShadowRoot(); - act(() => result.current.setShadowRoot(shadowRoot)); - - await waitForNextUpdate(); + await act(async () => result.current.setShadowRoot(shadowRoot)); expect(result.current.shadowRoot?.innerHTML).toBe( '<h1>Shadow DOM Mock</h1>', @@ -152,37 +140,42 @@ describe('useTechDocsReaderPage', () => { namespace: mockEntityMetadata.metadata.namespace?.toLocaleLowerCase(), }; const { result } = renderHook(() => useTechDocsReaderPage(), { wrapper }); - - expect(result.current.entityRef).toStrictEqual(lowercaseEntityRef); + await waitFor(() => { + expect(result.current.entityRef).toStrictEqual(lowercaseEntityRef); + }); }); it('entityRef is not modified when legacyUseCaseSensitiveTripletPaths is true', async () => { - configApiMock.getOptionalBoolean.mockReturnValueOnce(true); const caseSensitiveEntityRef = { kind: mockEntityMetadata.kind, name: mockEntityMetadata.metadata.name, namespace: mockEntityMetadata.metadata.namespace!!, }; - const { result } = renderHook(() => useTechDocsReaderPage(), { wrapper }); - - expect(result.current.entityRef).toStrictEqual(caseSensitiveEntityRef); + const { result } = renderHook(() => useTechDocsReaderPage(), { + wrapper: ({ children }) => + wrapper({ + children, + config: { techdocs: { legacyUseCaseSensitiveTripletPaths: true } }, + }), + }); + await waitFor(() => { + expect(result.current.entityRef).toStrictEqual(caseSensitiveEntityRef); + }); }); it('entityRef provided as analytics context', async () => { - const { waitForNextUpdate } = renderHook( - () => useAnalytics().captureEvent('action', 'subject'), - { wrapper }, - ); - - await waitForNextUpdate(); - - expect(analyticsApiMock.getEvents()[0]).toMatchObject({ - action: 'action', - subject: 'subject', - context: { - entityRef: 'component:default/test', - }, + renderHook(() => useAnalytics().captureEvent('action', 'subject'), { + wrapper, + }); + await waitFor(() => { + expect(analyticsApiMock.getEvents()[0]).toMatchObject({ + action: 'action', + subject: 'subject', + context: { + entityRef: 'component:default/test', + }, + }); }); }); }); diff --git a/plugins/techdocs-react/src/hooks.test.ts b/plugins/techdocs-react/src/hooks.test.ts index 2aa53b32d5..0cd55fa10f 100644 --- a/plugins/techdocs-react/src/hooks.test.ts +++ b/plugins/techdocs-react/src/hooks.test.ts @@ -19,7 +19,7 @@ import { useShadowRootElements, useShadowRootSelection, } from './hooks'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { fireEvent, waitFor } from '@testing-library/react'; const fireSelectionChangeEvent = (window: Window) => { diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index c407d11028..4db98ea055 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,55 @@ # @backstage/plugin-techdocs +## 1.8.0 + +### Minor Changes + +- 27740caa2d: Added experimental support for declarative integration via the `/alpha` subpath. + +### Patch Changes + +- 4918f65ab2: Create an experimental `TechDocsSearchResultItemExtension` for declarative integration with Backstage; it can be accessed via the `/alpha` import. +- 3605370af6: Improved `DocsTable` to display pagination controls dynamically, appearing only when needed. +- 0296f272b4: The `spec.lifecycle' field in entities will now always be rendered as a string. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- 9468a67b92: Added support for React 18. The new `createRoot` API from `react-dom/client` will now be used if present. +- df449a7a31: Add kind column by default to TechDocsTable +- Updated dependencies + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/integration-react@1.1.20 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/plugin-search-react@1.7.1 + - @backstage/plugin-techdocs-react@1.1.12 + - @backstage/theme@0.4.3 + - @backstage/config@1.1.1 + - @backstage/plugin-search-common@1.2.7 + +## 1.7.1-next.2 + +### Patch Changes + +- 3605370af6: Improved `DocsTable` to display pagination controls dynamically, appearing only when needed. +- Updated dependencies + - @backstage/frontend-plugin-api@0.2.0-next.2 + - @backstage/integration-react@1.1.20-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/plugin-search-react@1.7.1-next.2 + - @backstage/theme@0.4.3-next.0 + - @backstage/config@1.1.1-next.0 + - @backstage/plugin-search-common@1.2.7-next.0 + - @backstage/plugin-techdocs-react@1.1.12-next.2 + ## 1.7.1-next.1 ### Patch Changes diff --git a/plugins/techdocs/alpha-api-report.md b/plugins/techdocs/alpha-api-report.md index 30d208865c..2b3a934e34 100644 --- a/plugins/techdocs/alpha-api-report.md +++ b/plugins/techdocs/alpha-api-report.md @@ -5,9 +5,20 @@ ```ts import { BackstagePlugin } from '@backstage/frontend-plugin-api'; import { Extension } from '@backstage/frontend-plugin-api'; +import { RouteRef } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) -const _default: BackstagePlugin; +const _default: BackstagePlugin< + { + root: RouteRef<undefined>; + docRoot: RouteRef<{ + name: string; + kind: string; + namespace: string; + }>; + }, + {} +>; export default _default; // @alpha (undocumented) diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index e7251a4eb2..3df7399521 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.7.1-next.1", + "version": "1.8.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -74,8 +74,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -84,10 +84,9 @@ "@backstage/dev-utils": "workspace:^", "@backstage/plugin-techdocs-module-addons-contrib": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", - "@testing-library/react-hooks": "^8.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/dompurify": "^2.2.2", "@types/event-source-polyfill": "^1.0.0", diff --git a/plugins/techdocs/src/alpha.tsx b/plugins/techdocs/src/alpha.tsx index bea4b7ab34..f4d4da6e93 100644 --- a/plugins/techdocs/src/alpha.tsx +++ b/plugins/techdocs/src/alpha.tsx @@ -18,8 +18,33 @@ import React from 'react'; import { createPlugin, createSchemaFromZod, + createApiExtension, + createPageExtension, } from '@backstage/frontend-plugin-api'; import { createSearchResultListItemExtension } from '@backstage/plugin-search-react/alpha'; +import { + configApiRef, + createApiFactory, + createRouteRef, + discoveryApiRef, + fetchApiRef, + identityApiRef, +} from '@backstage/core-plugin-api'; +import { + techdocsApiRef, + techdocsStorageApiRef, +} from '@backstage/plugin-techdocs-react'; +import { TechDocsClient, TechDocsStorageClient } from './client'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; + +const rootRouteRef = createRouteRef({ + id: 'plugin.techdocs.indexPage', +}); + +const rootDocsRouteRef = createRouteRef({ + id: 'plugin.techdocs.readerPage', + params: ['namespace', 'kind', 'name'], +}); /** @alpha */ export const TechDocsSearchResultListItemExtension = @@ -44,8 +69,93 @@ export const TechDocsSearchResultListItemExtension = }, }); +/** + * Responsible for rendering the provided router element + * + * @alpha + */ +const TechDocsIndexPage = createPageExtension({ + id: 'plugin.techdocs.indexPage', + defaultPath: '/docs', + routeRef: convertLegacyRouteRef(rootRouteRef), + loader: () => + import('./home/components/TechDocsIndexPage').then(m => ( + <m.TechDocsIndexPage /> + )), +}); + +/** + * Component responsible for composing a TechDocs reader page experience + * + * @alpha + */ +const TechDocsReaderPage = createPageExtension({ + id: 'plugin.techdocs.readerPage', + loader: () => + import('./reader/components/TechDocsReaderPage').then(m => ( + <m.TechDocsReaderPage /> + )), + routeRef: convertLegacyRouteRef(rootDocsRouteRef), + defaultPath: '/docs/:namespace/:kind/:name/*', +}); + +/** @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, + }), + }); + }, +}); + +/** @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, + }), + }); + }, +}); + /** @alpha */ export default createPlugin({ id: 'techdocs', - extensions: [TechDocsSearchResultListItemExtension], + extensions: [ + TechDocsIndexPage, + TechDocsReaderPage, + techDocsClient, + techDocsStorage, + TechDocsSearchResultListItemExtension, + ], + routes: { + root: convertLegacyRouteRef(rootRouteRef), + docRoot: convertLegacyRouteRef(rootDocsRouteRef), + }, }); diff --git a/plugins/techdocs/src/reader/components/TechDocsBuildLogs.test.tsx b/plugins/techdocs/src/reader/components/TechDocsBuildLogs.test.tsx index afdac63a99..34aaf76394 100644 --- a/plugins/techdocs/src/reader/components/TechDocsBuildLogs.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsBuildLogs.test.tsx @@ -20,6 +20,7 @@ import { TechDocsBuildLogs, TechDocsBuildLogsDrawerContent, } from './TechDocsBuildLogs'; +import { userEvent } from '@testing-library/user-event'; // The <AutoSizer> inside <LogViewer> needs mocking to render in jsdom jest.mock('react-virtualized-auto-sizer', () => ({ @@ -38,7 +39,7 @@ describe('<TechDocsBuildLogs />', () => { it('should open drawer', async () => { const rendered = await renderInTestApp(<TechDocsBuildLogs buildLog={[]} />); - rendered.getByText(/Show Build Logs/i).click(); + await userEvent.click(rendered.getByText(/Show Build Logs/i)); expect(rendered.getByText(/Build Details/i)).toBeInTheDocument(); }); }); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx index e11b7b6e81..f732afd31d 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ import React from 'react'; -import { act } from '@testing-library/react'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; @@ -150,31 +149,25 @@ describe('<TechDocsReaderPage />', () => { }); it('should render a techdocs reader page with children', async () => { - await act(async () => { - const rendered = await renderInTestApp( - <Wrapper> - <TechDocsReaderPage - entityRef={{ - name: 'test-name', - namespace: 'test-namespace', - kind: 'test', - }} - > - techdocs reader page - </TechDocsReaderPage> - </Wrapper>, - { - mountedRoutes, - }, - ); - expect( - rendered.container.querySelector('header'), - ).not.toBeInTheDocument(); - expect( - rendered.container.querySelector('article'), - ).not.toBeInTheDocument(); - expect(rendered.getByText('techdocs reader page')).toBeInTheDocument(); - }); + const rendered = await renderInTestApp( + <Wrapper> + <TechDocsReaderPage + entityRef={{ + name: 'test-name', + namespace: 'test-namespace', + kind: 'test', + }} + > + techdocs reader page + </TechDocsReaderPage> + </Wrapper>, + { + mountedRoutes, + }, + ); + expect(rendered.container.querySelector('header')).not.toBeInTheDocument(); + expect(rendered.container.querySelector('article')).not.toBeInTheDocument(); + expect(rendered.getByText('techdocs reader page')).toBeInTheDocument(); }); it('should render techdocs reader page with addons', async () => { @@ -183,56 +176,52 @@ describe('<TechDocsReaderPage />', () => { const namespace = 'test-namespace'; const kind = 'test'; - await act(async () => { - const rendered = await renderInTestApp( - <Wrapper> - <FlatRoutes> - <Route - path="/docs/:namespace/:kind/:name/*" - element={<TechDocsReaderPage />} - > - <TechDocsAddons> - <ReportIssue /> - </TechDocsAddons> - </Route> - </FlatRoutes> - </Wrapper>, - { - mountedRoutes, - routeEntries: ['/docs/test-namespace/test/test-name'], - }, - ); + const rendered = await renderInTestApp( + <Wrapper> + <FlatRoutes> + <Route + path="/docs/:namespace/:kind/:name/*" + element={<TechDocsReaderPage />} + > + <TechDocsAddons> + <ReportIssue /> + </TechDocsAddons> + </Route> + </FlatRoutes> + </Wrapper>, + { + mountedRoutes, + routeEntries: ['/docs/test-namespace/test/test-name'], + }, + ); - expect( - rendered.getByText(`PageMock: ${namespace}#${kind}#${name}`), - ).toBeInTheDocument(); - }); + expect( + rendered.getByText(`PageMock: ${namespace}#${kind}#${name}`), + ).toBeInTheDocument(); }); it('should render techdocs reader page with addons and page', async () => { (Page as jest.Mock).mockImplementation(PageMock); - await act(async () => { - const rendered = await renderInTestApp( - <Wrapper> - <FlatRoutes> - <Route - path="/docs/:namespace/:kind/:name/*" - element={<TechDocsReaderPage />} - > - <p>the page</p> - <TechDocsAddons> - <ReportIssue /> - </TechDocsAddons> - </Route> - </FlatRoutes> - </Wrapper>, - { - mountedRoutes, - routeEntries: ['/docs/test-namespace/test/test-name'], - }, - ); + const rendered = await renderInTestApp( + <Wrapper> + <FlatRoutes> + <Route + path="/docs/:namespace/:kind/:name/*" + element={<TechDocsReaderPage />} + > + <p>the page</p> + <TechDocsAddons> + <ReportIssue /> + </TechDocsAddons> + </Route> + </FlatRoutes> + </Wrapper>, + { + mountedRoutes, + routeEntries: ['/docs/test-namespace/test/test-name'], + }, + ); - expect(rendered.getByText('the page')).toBeInTheDocument(); - }); + expect(rendered.getByText('the page')).toBeInTheDocument(); }); }); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx index 2380724960..670653ce6b 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/context.test.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook, waitFor } from '@testing-library/react'; import { ThemeProvider } from '@material-ui/core'; @@ -95,16 +95,13 @@ describe('context', () => { }); it('should return expected entity values', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useEntityMetadata(), - { wrapper }, - ); + const { result } = renderHook(() => useEntityMetadata(), { wrapper }); - await waitForNextUpdate(); - - expect(result.current.value).toBeDefined(); - expect(result.current.error).toBeUndefined(); - expect(result.current.value).toMatchObject(mockEntityMetadata); + await waitFor(() => { + expect(result.current.value).toBeDefined(); + expect(result.current.error).toBeUndefined(); + expect(result.current.value).toMatchObject(mockEntityMetadata); + }); }); }); @@ -116,16 +113,13 @@ describe('context', () => { }); it('should return expected techdocs metadata values', async () => { - const { result, waitForNextUpdate } = renderHook( - () => useTechDocsMetadata(), - { wrapper }, - ); + const { result } = renderHook(() => useTechDocsMetadata(), { wrapper }); - await waitForNextUpdate(); - - expect(result.current.value).toBeDefined(); - expect(result.current.error).toBeUndefined(); - expect(result.current.value).toMatchObject(mockTechDocsMetadata); + await waitFor(() => { + expect(result.current.value).toBeDefined(); + expect(result.current.error).toBeUndefined(); + expect(result.current.value).toMatchObject(mockTechDocsMetadata); + }); }); }); }); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx index 3e5a4c73c3..32fbe21714 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { act, waitFor } from '@testing-library/react'; +import { waitFor } from '@testing-library/react'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { @@ -90,18 +90,16 @@ describe('<TechDocsReaderPageContent />', () => { useTechDocsReaderDom.mockReturnValue(document.createElement('html')); useReaderState.mockReturnValue({ state: 'cached' }); - await act(async () => { - const rendered = await renderInTestApp( - <Wrapper> - <TechDocsReaderPageContent withSearch={false} /> - </Wrapper>, - ); + const rendered = await renderInTestApp( + <Wrapper> + <TechDocsReaderPageContent withSearch={false} /> + </Wrapper>, + ); - await waitFor(() => { - expect( - rendered.getByTestId('techdocs-native-shadowroot'), - ).toBeInTheDocument(); - }); + await waitFor(() => { + expect( + rendered.getByTestId('techdocs-native-shadowroot'), + ).toBeInTheDocument(); }); }); @@ -110,21 +108,19 @@ describe('<TechDocsReaderPageContent />', () => { useTechDocsReaderDom.mockReturnValue(document.createElement('html')); useReaderState.mockReturnValue({ state: 'cached' }); - await act(async () => { - const rendered = await renderInTestApp( - <Wrapper> - <TechDocsReaderPageContent withSearch={false} /> - </Wrapper>, - ); + const rendered = await renderInTestApp( + <Wrapper> + <TechDocsReaderPageContent withSearch={false} /> + </Wrapper>, + ); - await waitFor(() => { - expect( - rendered.queryByTestId('techdocs-native-shadowroot'), - ).not.toBeInTheDocument(); - expect( - rendered.getByText('ERROR 404: PAGE NOT FOUND'), - ).toBeInTheDocument(); - }); + await waitFor(() => { + expect( + rendered.queryByTestId('techdocs-native-shadowroot'), + ).not.toBeInTheDocument(); + expect( + rendered.getByText('ERROR 404: PAGE NOT FOUND'), + ).toBeInTheDocument(); }); }); @@ -134,21 +130,19 @@ describe('<TechDocsReaderPageContent />', () => { useTechDocsReaderDom.mockReturnValue(undefined); useReaderState.mockReturnValue({ state: 'CONTENT_NOT_FOUND' }); - await act(async () => { - const rendered = await renderInTestApp( - <Wrapper> - <TechDocsReaderPageContent withSearch={false} /> - </Wrapper>, - ); + const rendered = await renderInTestApp( + <Wrapper> + <TechDocsReaderPageContent withSearch={false} /> + </Wrapper>, + ); - await waitFor(() => { - expect( - rendered.queryByTestId('techdocs-native-shadowroot'), - ).not.toBeInTheDocument(); - expect( - rendered.getByText('ERROR 404: Documentation not found'), - ).toBeInTheDocument(); - }); + await waitFor(() => { + expect( + rendered.queryByTestId('techdocs-native-shadowroot'), + ).not.toBeInTheDocument(); + expect( + rendered.getByText('ERROR 404: Documentation not found'), + ).toBeInTheDocument(); }); }); }); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx index a3e03b7cf0..d2956ce919 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx @@ -14,7 +14,6 @@ * limitations under the License. */ import React from 'react'; -import { act, waitFor } from '@testing-library/react'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; @@ -80,112 +79,77 @@ describe('<TechDocsReaderPageHeader />', () => { getEntityMetadata.mockResolvedValue(mockEntityMetadata); getTechDocsMetadata.mockResolvedValue(mockTechDocsMetadata); - await act(async () => { - const rendered = await renderInTestApp( - <Wrapper> - <TechDocsReaderPageHeader /> - </Wrapper>, - { - mountedRoutes: { - '/catalog/:namespace/:kind/:name/*': entityRouteRef, - '/docs': rootRouteRef, - }, + const rendered = await renderInTestApp( + <Wrapper> + <TechDocsReaderPageHeader /> + </Wrapper>, + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name/*': entityRouteRef, + '/docs': rootRouteRef, }, - ); + }, + ); - expect(rendered.container.innerHTML).toContain('header'); + expect(rendered.container.innerHTML).toContain('header'); - await waitFor(() => { - expect(rendered.getAllByText('test-site-name')).toHaveLength(2); - }); + expect(rendered.getAllByText('test-site-name')).toHaveLength(2); + expect(rendered.getByText('test-site-desc')).toBeDefined(); - expect(rendered.getByText('test-site-desc')).toBeDefined(); - }); + expect( + rendered.getByRole('link', { name: 'test:test-namespace/test-name' }), + ).toHaveAttribute('href', '/catalog/test-namespace/test/test-name'); }); it('should render a techdocs page header even if metadata is not loaded', async () => { - await act(async () => { - const rendered = await renderInTestApp( - <Wrapper> - <TechDocsReaderPageHeader /> - </Wrapper>, - { - mountedRoutes: { - '/catalog/:namespace/:kind/:name/*': entityRouteRef, - '/docs': rootRouteRef, - }, + const rendered = await renderInTestApp( + <Wrapper> + <TechDocsReaderPageHeader /> + </Wrapper>, + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name/*': entityRouteRef, + '/docs': rootRouteRef, }, - ); + }, + ); - expect(rendered.container.innerHTML).toContain('header'); - }); + expect(rendered.container.innerHTML).toContain('header'); }); it('should not render a techdocs page header if entity metadata is missing', async () => { getEntityMetadata.mockResolvedValue(undefined); - await act(async () => { - const rendered = await renderInTestApp( - <Wrapper> - <TechDocsReaderPageHeader /> - </Wrapper>, - { - mountedRoutes: { - '/catalog/:namespace/:kind/:name/*': entityRouteRef, - '/docs': rootRouteRef, - }, + const rendered = await renderInTestApp( + <Wrapper> + <TechDocsReaderPageHeader /> + </Wrapper>, + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name/*': entityRouteRef, + '/docs': rootRouteRef, }, - ); + }, + ); - await waitFor(() => { - expect(rendered.container.innerHTML).not.toContain('header'); - }); - }); + expect(rendered.container.innerHTML).not.toContain('header'); }); it('should not render a techdocs page header if techdocs metadata is missing', async () => { getTechDocsMetadata.mockResolvedValue(undefined); - await act(async () => { - const rendered = await renderInTestApp( - <Wrapper> - <TechDocsReaderPageHeader /> - </Wrapper>, - { - mountedRoutes: { - '/catalog/:namespace/:kind/:name/*': entityRouteRef, - '/docs': rootRouteRef, - }, + const rendered = await renderInTestApp( + <Wrapper> + <TechDocsReaderPageHeader /> + </Wrapper>, + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name/*': entityRouteRef, + '/docs': rootRouteRef, }, - ); + }, + ); - await waitFor(() => { - expect(rendered.container.innerHTML).not.toContain('header'); - }); - }); - }); - - it('should render a link back to the component page', async () => { - getTechDocsMetadata.mockResolvedValue(mockTechDocsMetadata); - - await act(async () => { - const rendered = await renderInTestApp( - <Wrapper> - <TechDocsReaderPageHeader /> - </Wrapper>, - { - mountedRoutes: { - '/catalog/:namespace/:kind/:name/*': entityRouteRef, - '/docs': rootRouteRef, - }, - }, - ); - - await waitFor(() => { - expect( - rendered.getByRole('link', { name: 'test:test-namespace/test-name' }), - ).toHaveAttribute('href', '/catalog/test-namespace/test/test-name'); - }); - }); + expect(rendered.container.innerHTML).not.toContain('header'); }); }); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx index f7b4f2eff2..d84c5c5347 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx @@ -133,7 +133,9 @@ export const TechDocsReaderPageHeader = ( } /> )} - {lifecycle ? <HeaderLabel label="Lifecycle" value={lifecycle} /> : null} + {lifecycle ? ( + <HeaderLabel label="Lifecycle" value={String(lifecycle)} /> + ) : null} {locationMetadata && locationMetadata.type !== 'dir' && locationMetadata.type !== 'file' ? ( diff --git a/plugins/techdocs/src/reader/components/useReaderState.test.tsx b/plugins/techdocs/src/reader/components/useReaderState.test.tsx index 5f3e2d9662..60898ab288 100644 --- a/plugins/techdocs/src/reader/components/useReaderState.test.tsx +++ b/plugins/techdocs/src/reader/components/useReaderState.test.tsx @@ -16,7 +16,7 @@ import { NotFoundError } from '@backstage/errors'; import { TestApiProvider } from '@backstage/test-utils'; -import { act, renderHook } from '@testing-library/react-hooks'; +import { act, renderHook, waitFor } from '@testing-library/react'; import React from 'react'; import { techdocsStorageApiRef } from '../../api'; import { @@ -284,24 +284,22 @@ describe('useReaderState', () => { return 'cached'; }); - await act(async () => { - const { result, waitForValueToChange } = await renderHook( - () => useReaderState('Component', 'default', 'backstage', '/example'), - { wrapper: Wrapper }, - ); + const { result } = renderHook( + () => useReaderState('Component', 'default', 'backstage', '/example'), + { wrapper: Wrapper }, + ); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: undefined, - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - await waitForValueToChange(() => result.current.state); + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: undefined, + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + await waitFor(() => { expect(result.current).toEqual({ state: 'CONTENT_FRESH', path: '/example', @@ -311,20 +309,20 @@ describe('useReaderState', () => { buildLog: [], contentReload: expect.any(Function), }); - - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( - { kind: 'Component', namespace: 'default', name: 'backstage' }, - '/example', - ); - expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( - { - kind: 'Component', - namespace: 'default', - name: 'backstage', - }, - expect.any(Function), - ); }); + + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( + { kind: 'Component', namespace: 'default', name: 'backstage' }, + '/example', + ); + expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( + { + kind: 'Component', + namespace: 'default', + name: 'backstage', + }, + expect.any(Function), + ); }); it('should reload initially missing content', async () => { @@ -336,6 +334,7 @@ describe('useReaderState', () => { }); techdocsStorageApi.syncEntityDocs.mockImplementation( async (_, logHandler) => { + await 'a tick'; logHandler?.call(this, 'Line 1'); logHandler?.call(this, 'Line 2'); await new Promise(resolve => setTimeout(resolve, 1100)); @@ -343,38 +342,39 @@ describe('useReaderState', () => { }, ); - await act(async () => { - const { result, waitForValueToChange } = await renderHook( - () => useReaderState('Component', 'default', 'backstage', '/example'), - { wrapper: Wrapper }, - ); + const { result } = renderHook( + () => useReaderState('Component', 'default', 'backstage', '/example'), + { wrapper: Wrapper }, + ); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: undefined, - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: undefined, + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); - await waitForValueToChange(() => result.current.state, { + await waitFor( + () => { + expect(result.current).toEqual({ + state: 'INITIAL_BUILD', + path: '/example', + content: undefined, + contentErrorMessage: 'NotFoundError: Page Not Found', + syncErrorMessage: undefined, + buildLog: ['Line 1', 'Line 2'], + contentReload: expect.any(Function), + }); + }, + { timeout: 2000, - }); - - expect(result.current).toEqual({ - state: 'INITIAL_BUILD', - path: '/example', - content: undefined, - contentErrorMessage: 'NotFoundError: Page Not Found', - syncErrorMessage: undefined, - buildLog: ['Line 1', 'Line 2'], - contentReload: expect.any(Function), - }); - - await waitForValueToChange(() => result.current.state); + }, + ); + await waitFor(() => { expect(result.current).toEqual({ state: 'CHECKING', path: '/example', @@ -384,9 +384,9 @@ describe('useReaderState', () => { buildLog: [], contentReload: expect.any(Function), }); + }); - await waitForValueToChange(() => result.current.state); - + await waitFor(() => { expect(result.current).toEqual({ state: 'CONTENT_FRESH', path: '/example', @@ -396,22 +396,22 @@ describe('useReaderState', () => { buildLog: [], contentReload: expect.any(Function), }); - - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2); - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( - { kind: 'Component', namespace: 'default', name: 'backstage' }, - '/example', - ); - expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledTimes(1); - expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( - { - kind: 'Component', - namespace: 'default', - name: 'backstage', - }, - expect.any(Function), - ); }); + + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2); + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( + { kind: 'Component', namespace: 'default', name: 'backstage' }, + '/example', + ); + expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledTimes(1); + expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( + { + kind: 'Component', + namespace: 'default', + name: 'backstage', + }, + expect.any(Function), + ); }); it('should handle stale content', async () => { @@ -423,6 +423,7 @@ describe('useReaderState', () => { }); techdocsStorageApi.syncEntityDocs.mockImplementation( async (_, logHandler) => { + await 'a tick'; logHandler?.call(this, 'Line 1'); logHandler?.call(this, 'Line 2'); await new Promise(resolve => setTimeout(resolve, 1100)); @@ -430,24 +431,23 @@ describe('useReaderState', () => { }, ); - await act(async () => { - const { result, waitForValueToChange } = await renderHook( - () => useReaderState('Component', 'default', 'backstage', '/example'), - { wrapper: Wrapper }, - ); + const { result } = renderHook( + () => useReaderState('Component', 'default', 'backstage', '/example'), + { wrapper: Wrapper }, + ); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: undefined, - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: undefined, + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); - // the content is returned but the sync is in progress - await waitForValueToChange(() => result.current.state); + // the content is returned but the sync is in progress + await waitFor(() => { expect(result.current).toEqual({ state: 'CONTENT_FRESH', path: '/example', @@ -457,9 +457,10 @@ describe('useReaderState', () => { buildLog: ['Line 1', 'Line 2'], contentReload: expect.any(Function), }); + }); - // the sync takes longer than 1 seconds so the refreshing state starts - await waitForValueToChange(() => result.current.state); + // the sync takes longer than 1 seconds so the refreshing state starts + await waitFor(() => { expect(result.current).toEqual({ state: 'CONTENT_STALE_REFRESHING', path: '/example', @@ -469,9 +470,10 @@ describe('useReaderState', () => { buildLog: ['Line 1', 'Line 2'], contentReload: expect.any(Function), }); + }); - // the content is updated but not yet displayed - await waitForValueToChange(() => result.current.state); + // the content is updated but not yet displayed + await waitFor(() => { expect(result.current).toEqual({ state: 'CONTENT_STALE_READY', path: '/example', @@ -481,12 +483,15 @@ describe('useReaderState', () => { buildLog: ['Line 1', 'Line 2'], contentReload: expect.any(Function), }); + }); - // reload the content + // reload the content + await act(async () => { result.current.contentReload(); + }); - // the new content refresh is triggered - await waitForValueToChange(() => result.current.state); + // the new content refresh is triggered + await waitFor(() => { expect(result.current).toEqual({ state: 'CHECKING', path: '/example', @@ -496,35 +501,39 @@ describe('useReaderState', () => { buildLog: [], contentReload: expect.any(Function), }); - - // the new content is loaded - await waitForValueToChange(() => result.current.state, { - timeout: 2000, - }); - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/example', - content: 'my new content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); - - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2); - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( - { kind: 'Component', namespace: 'default', name: 'backstage' }, - '/example', - ); - expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( - { - kind: 'Component', - namespace: 'default', - name: 'backstage', - }, - expect.any(Function), - ); }); + + // the new content is loaded + await waitFor( + () => { + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/example', + content: 'my new content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + }, + { + timeout: 2000, + }, + ); + + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledTimes(2); + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( + { kind: 'Component', namespace: 'default', name: 'backstage' }, + '/example', + ); + expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( + { + kind: 'Component', + namespace: 'default', + name: 'backstage', + }, + expect.any(Function), + ); }); it('should handle navigation', async () => { @@ -537,25 +546,24 @@ describe('useReaderState', () => { .mockRejectedValueOnce(new NotFoundError('Some error description')); techdocsStorageApi.syncEntityDocs.mockResolvedValue('cached'); - await act(async () => { - const { result, waitForValueToChange, rerender } = await renderHook( - ({ path }: { path: string }) => - useReaderState('Component', 'default', 'backstage', path), - { initialProps: { path: '/example' }, wrapper: Wrapper as any }, - ); + const { result, rerender } = renderHook( + ({ path }: { path: string }) => + useReaderState('Component', 'default', 'backstage', path), + { initialProps: { path: '/example' }, wrapper: Wrapper as any }, + ); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: undefined, - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: undefined, + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); - // show the content - await waitForValueToChange(() => result.current.state); + // show the content + await waitFor(() => { expect(result.current).toEqual({ state: 'CONTENT_FRESH', path: '/example', @@ -565,11 +573,12 @@ describe('useReaderState', () => { buildLog: [], contentReload: expect.any(Function), }); + }); - // navigate - rerender({ path: '/new' }); + // navigate + rerender({ path: '/new' }); - await waitForValueToChange(() => result.current.state); + await waitFor(() => { expect(result.current).toEqual({ state: 'CHECKING', path: '/example', @@ -579,24 +588,29 @@ describe('useReaderState', () => { buildLog: [], contentReload: expect.any(Function), }); + }); - await waitForValueToChange(() => result.current.state, { + await waitFor( + () => { + expect(result.current).toEqual({ + state: 'CONTENT_FRESH', + path: '/new', + content: 'my new content', + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); + }, + { timeout: 2000, - }); - expect(result.current).toEqual({ - state: 'CONTENT_FRESH', - path: '/new', - content: 'my new content', - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); + }, + ); - // navigate - rerender({ path: '/missing' }); + // navigate + rerender({ path: '/missing' }); - await waitForValueToChange(() => result.current.state); + await waitFor(() => { expect(result.current).toEqual({ state: 'CONTENT_NOT_FOUND', path: '/missing', @@ -606,24 +620,24 @@ describe('useReaderState', () => { buildLog: [], contentReload: expect.any(Function), }); - - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( - { kind: 'Component', namespace: 'default', name: 'backstage' }, - '/example', - ); - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( - { kind: 'Component', namespace: 'default', name: 'backstage' }, - '/new', - ); - expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( - { - kind: 'Component', - namespace: 'default', - name: 'backstage', - }, - expect.any(Function), - ); }); + + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( + { kind: 'Component', namespace: 'default', name: 'backstage' }, + '/example', + ); + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( + { kind: 'Component', namespace: 'default', name: 'backstage' }, + '/new', + ); + expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( + { + kind: 'Component', + namespace: 'default', + name: 'backstage', + }, + expect.any(Function), + ); }); it('should handle content error', async () => { @@ -632,24 +646,23 @@ describe('useReaderState', () => { ); techdocsStorageApi.syncEntityDocs.mockResolvedValue('cached'); - await act(async () => { - const { result, waitForValueToChange } = await renderHook( - () => useReaderState('Component', 'default', 'backstage', '/example'), - { wrapper: Wrapper }, - ); + const { result } = renderHook( + () => useReaderState('Component', 'default', 'backstage', '/example'), + { wrapper: Wrapper }, + ); - expect(result.current).toEqual({ - state: 'CHECKING', - path: '/example', - content: undefined, - contentErrorMessage: undefined, - syncErrorMessage: undefined, - buildLog: [], - contentReload: expect.any(Function), - }); + expect(result.current).toEqual({ + state: 'CHECKING', + path: '/example', + content: undefined, + contentErrorMessage: undefined, + syncErrorMessage: undefined, + buildLog: [], + contentReload: expect.any(Function), + }); - // the content loading threw an error - await waitForValueToChange(() => result.current.state); + // the content loading threw an error + await waitFor(() => { expect(result.current).toEqual({ state: 'CONTENT_NOT_FOUND', path: '/example', @@ -659,20 +672,20 @@ describe('useReaderState', () => { buildLog: [], contentReload: expect.any(Function), }); - - expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( - { kind: 'Component', namespace: 'default', name: 'backstage' }, - '/example', - ); - expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( - { - kind: 'Component', - namespace: 'default', - name: 'backstage', - }, - expect.any(Function), - ); }); + + expect(techdocsStorageApi.getEntityDocs).toHaveBeenCalledWith( + { kind: 'Component', namespace: 'default', name: 'backstage' }, + '/example', + ); + expect(techdocsStorageApi.syncEntityDocs).toHaveBeenCalledWith( + { + kind: 'Component', + namespace: 'default', + name: 'backstage', + }, + expect.any(Function), + ); }); }); }); diff --git a/plugins/techdocs/src/reader/transformers/addGitFeedbackLink.ts b/plugins/techdocs/src/reader/transformers/addGitFeedbackLink.ts index 9239573bd1..58876cd806 100644 --- a/plugins/techdocs/src/reader/transformers/addGitFeedbackLink.ts +++ b/plugins/techdocs/src/reader/transformers/addGitFeedbackLink.ts @@ -21,8 +21,8 @@ import { } from '@backstage/integration'; import FeedbackOutlinedIcon from '@material-ui/icons/FeedbackOutlined'; import React from 'react'; -import ReactDOM from 'react-dom'; import parseGitUrl from 'git-url-parse'; +import { renderReactElement } from './renderReactElement'; // requires repo export const addGitFeedbackLink = ( @@ -75,7 +75,7 @@ export const addGitFeedbackLink = ( default: return dom; } - ReactDOM.render(React.createElement(FeedbackOutlinedIcon), feedbackLink); + renderReactElement(React.createElement(FeedbackOutlinedIcon), feedbackLink); feedbackLink.style.paddingLeft = '5px'; feedbackLink.title = 'Leave feedback for this page'; feedbackLink.id = 'git-feedback-link'; diff --git a/plugins/techdocs/src/reader/transformers/addSidebarToggle.ts b/plugins/techdocs/src/reader/transformers/addSidebarToggle.ts index 789c9179d5..352e396abf 100644 --- a/plugins/techdocs/src/reader/transformers/addSidebarToggle.ts +++ b/plugins/techdocs/src/reader/transformers/addSidebarToggle.ts @@ -17,7 +17,7 @@ import type { Transformer } from './transformer'; import MenuIcon from '@material-ui/icons/Menu'; import React from 'react'; -import ReactDOM from 'react-dom'; +import { renderReactElement } from './renderReactElement'; export const addSidebarToggle = (): Transformer => { return dom => { @@ -33,7 +33,7 @@ export const addSidebarToggle = (): Transformer => { } const toggleSidebar = mkdocsToggleSidebar.cloneNode() as HTMLLabelElement; - ReactDOM.render(React.createElement(MenuIcon), toggleSidebar); + renderReactElement(React.createElement(MenuIcon), toggleSidebar); toggleSidebar.id = 'toggle-sidebar'; toggleSidebar.title = 'Toggle Sidebar'; toggleSidebar.classList.add('md-content__button'); diff --git a/plugins/techdocs/src/reader/transformers/copyToClipboard.test.ts b/plugins/techdocs/src/reader/transformers/copyToClipboard.test.ts index cac7f76a0e..604957d5cd 100644 --- a/plugins/techdocs/src/reader/transformers/copyToClipboard.test.ts +++ b/plugins/techdocs/src/reader/transformers/copyToClipboard.test.ts @@ -17,7 +17,7 @@ import { createTestShadowDom } from '../../test-utils'; import { copyToClipboard } from './copyToClipboard'; import { lightTheme } from '@backstage/theme'; -import { waitFor } from '@testing-library/react'; +import { act, waitFor } from '@testing-library/react'; import useCopyToClipboard from 'react-use/lib/useCopyToClipboard'; const clipboardSpy = jest.fn(); @@ -43,8 +43,11 @@ describe('copyToClipboard', () => { spy.mockReturnValue([{}, copy]); const expectedClipboard = 'function foo() {return "bar";}'; - const shadowDom = await createTestShadowDom( - ` + + let shadowDom: ShadowRoot; + await act(async () => { + shadowDom = await createTestShadowDom( + ` <!DOCTYPE html> <html> <body> @@ -52,13 +55,20 @@ describe('copyToClipboard', () => { </body> </html> `, - { - preTransformers: [], - postTransformers: [copyToClipboard(lightTheme)], - }, - ); + { + preTransformers: [], + postTransformers: [copyToClipboard(lightTheme)], + }, + ); + }); - shadowDom.querySelector('button')?.click(); + await waitFor(() => { + expect(shadowDom.querySelector('button')).not.toBe(null); + }); + + await act(async () => { + shadowDom.querySelector('button')!.click(); + }); await waitFor(() => { const tooltip = document.querySelector('[role="tooltip"]'); diff --git a/plugins/techdocs/src/reader/transformers/copyToClipboard.tsx b/plugins/techdocs/src/reader/transformers/copyToClipboard.tsx index 28a6c789b6..1fd9d179a3 100644 --- a/plugins/techdocs/src/reader/transformers/copyToClipboard.tsx +++ b/plugins/techdocs/src/reader/transformers/copyToClipboard.tsx @@ -15,7 +15,7 @@ */ import React, { useState, useCallback } from 'react'; -import ReactDom from 'react-dom'; +import { renderReactElement } from './renderReactElement'; import { withStyles, Theme, @@ -91,7 +91,7 @@ export const copyToClipboard = (theme: Theme): Transformer => { const text = code.textContent || ''; const container = document.createElement('div'); code?.parentElement?.prepend(container); - ReactDom.render( + renderReactElement( <ThemeProvider theme={theme}> <CopyToClipboardButton text={text} /> </ThemeProvider>, diff --git a/plugins/techdocs/src/reader/transformers/html/transformer.test.tsx b/plugins/techdocs/src/reader/transformers/html/transformer.test.tsx index 2b1f427be3..ed5fbba085 100644 --- a/plugins/techdocs/src/reader/transformers/html/transformer.test.tsx +++ b/plugins/techdocs/src/reader/transformers/html/transformer.test.tsx @@ -15,7 +15,7 @@ */ import React, { FC, PropsWithChildren } from 'react'; -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { ConfigReader } from '@backstage/core-app-api'; import { ConfigApi, configApiRef } from '@backstage/core-plugin-api'; diff --git a/plugins/techdocs/src/reader/transformers/renderReactElement.ts b/plugins/techdocs/src/reader/transformers/renderReactElement.ts new file mode 100644 index 0000000000..f9b45065f1 --- /dev/null +++ b/plugins/techdocs/src/reader/transformers/renderReactElement.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. + */ + +let ReactDOM: typeof import('react-dom') | typeof import('react-dom/client'); +if (process.env.HAS_REACT_DOM_CLIENT) { + ReactDOM = require('react-dom/client'); +} else { + ReactDOM = require('react-dom'); +} + +/** @internal */ +export function renderReactElement(element: JSX.Element, root: HTMLElement) { + if ('createRoot' in ReactDOM) { + ReactDOM.createRoot(root).render(element); + } else { + ReactDOM.render(element, root); + } +} diff --git a/plugins/techdocs/src/reader/transformers/styles/transformer.test.ts b/plugins/techdocs/src/reader/transformers/styles/transformer.test.ts index 84ba16d6e6..90244e96ad 100644 --- a/plugins/techdocs/src/reader/transformers/styles/transformer.test.ts +++ b/plugins/techdocs/src/reader/transformers/styles/transformer.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderHook } from '@testing-library/react-hooks'; +import { renderHook } from '@testing-library/react'; import { useStylesTransformer } from './transformer'; describe('Transformers > Styles', () => { diff --git a/plugins/todo-backend/CHANGELOG.md b/plugins/todo-backend/CHANGELOG.md index 4cbf70e538..6edbe92aa7 100644 --- a/plugins/todo-backend/CHANGELOG.md +++ b/plugins/todo-backend/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-todo-backend +## 0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/integration@1.7.1 + - @backstage/plugin-catalog-node@1.4.7 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-openapi-utils@0.0.5 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/catalog-client@1.4.5 + - @backstage/config@1.1.1 + +## 0.3.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/integration@1.7.1-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-openapi-utils@0.0.5-next.0 + - @backstage/plugin-catalog-node@1.4.7-next.2 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/catalog-client@1.4.5-next.0 + - @backstage/config@1.1.1-next.0 + ## 0.3.3-next.1 ### Patch Changes diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index c741984f2d..d3296b70f0 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.3-next.1", + "version": "0.3.4", "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 68efd13892..b30c9d259e 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-todo +## 0.2.28 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.2.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.2.28-next.1 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index b255744e12..ec27528d72 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.28-next.1", + "version": "0.2.28", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -44,8 +44,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -53,9 +53,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/user-settings-backend/CHANGELOG.md b/plugins/user-settings-backend/CHANGELOG.md index 0dedc9dbce..53e8a6f30f 100644 --- a/plugins/user-settings-backend/CHANGELOG.md +++ b/plugins/user-settings-backend/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-user-settings-backend +## 0.2.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8 + - @backstage/plugin-auth-node@0.4.0 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/backend-plugin-api@0.6.6 + - @backstage/types@1.1.1 + +## 0.2.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/plugin-auth-node@0.4.0-next.2 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-plugin-api@0.6.6-next.2 + - @backstage/types@1.1.1 + ## 0.2.3-next.1 ### Patch Changes diff --git a/plugins/user-settings-backend/package.json b/plugins/user-settings-backend/package.json index a8e8a711ae..c72f349301 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.3-next.1", + "version": "0.2.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,6 +33,7 @@ "@backstage/backend-common": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", "@backstage/catalog-model": "workspace:^", + "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/types": "workspace:^", diff --git a/plugins/user-settings-backend/src/service/standaloneServer.ts b/plugins/user-settings-backend/src/service/standaloneServer.ts index 6dd8c7f72d..48a640636f 100644 --- a/plugins/user-settings-backend/src/service/standaloneServer.ts +++ b/plugins/user-settings-backend/src/service/standaloneServer.ts @@ -14,10 +14,13 @@ * limitations under the License. */ -import { createServiceBuilder, useHotMemoize } from '@backstage/backend-common'; +import { + createServiceBuilder, + DatabaseManager, +} from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; import { IdentityApi } from '@backstage/plugin-auth-node'; import { Server } from 'http'; -import Knex from 'knex'; import { Logger } from 'winston'; import { DatabaseUserSettingsStore } from '../database/DatabaseUserSettingsStore'; import { createRouterInternal } from './router'; @@ -33,13 +36,14 @@ export async function startStandaloneServer( ): Promise<Server> { const logger = options.logger.child({ service: 'storage-backend' }); - const database = useHotMemoize(module, () => { - return Knex({ - client: 'better-sqlite3', - connection: ':memory:', - useNullAsDefault: true, - }); - }); + const manager = DatabaseManager.fromConfig( + new ConfigReader({ + backend: { + database: { client: 'better-sqlite3', connection: ':memory:' }, + }, + }), + ); + const database = manager.forPlugin('user-settings'); logger.debug('Starting application server...'); @@ -58,9 +62,7 @@ export async function startStandaloneServer( }; const router = await createRouterInternal({ - userSettingsStore: await DatabaseUserSettingsStore.create({ - database: { getClient: async () => database }, - }), + userSettingsStore: await DatabaseUserSettingsStore.create({ database }), identity: identityMock, }); diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index dcd46282a1..3353f23a79 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-user-settings +## 0.7.11 + +### Patch Changes + +- 18c8dee6f5: Added experimental support for declarative integration via the `/alpha` subpath. +- d1b637d005: Fixed a bug where the theme icons would not be colored according to their active state. +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/frontend-plugin-api@0.2.0 + - @backstage/core-app-api@1.11.0 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + - @backstage/types@1.1.1 + +## 0.7.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.11.0-next.2 + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + - @backstage/types@1.1.1 + ## 0.7.11-next.1 ### Patch Changes diff --git a/plugins/user-settings/alpha-api-report.md b/plugins/user-settings/alpha-api-report.md index 203cfac601..f375eadbee 100644 --- a/plugins/user-settings/alpha-api-report.md +++ b/plugins/user-settings/alpha-api-report.md @@ -3,8 +3,19 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackstagePlugin } from '@backstage/frontend-plugin-api'; +import { RouteRef } from '@backstage/frontend-plugin-api'; import { TranslationRef } from '@backstage/core-plugin-api/alpha'; +// @alpha (undocumented) +const _default: BackstagePlugin< + { + root: RouteRef<undefined>; + }, + {} +>; +export default _default; + // @alpha (undocumented) export const userSettingsTranslationRef: TranslationRef< 'user-settings', diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 251436e85a..264521ee45 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,19 +1,19 @@ { "name": "@backstage/plugin-user-settings", "description": "A Backstage plugin that provides a settings page", - "version": "0.7.11-next.1", + "version": "0.7.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts", + "./alpha": "./src/alpha.tsx", "./package.json": "./package.json" }, "typesVersions": { "*": { "alpha": [ - "src/alpha.ts" + "src/alpha.tsx" ], "package.json": [ "package.json" @@ -50,6 +50,7 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", "@backstage/plugin-catalog-react": "workspace:^", "@backstage/theme": "workspace:^", "@backstage/types": "workspace:^", @@ -61,8 +62,8 @@ "zen-observable": "^0.10.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -70,9 +71,9 @@ "@backstage/dev-utils": "workspace:^", "@backstage/plugin-catalog": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "cross-fetch": "^3.1.5", "msw": "^1.0.0" diff --git a/plugins/user-settings/src/alpha.tsx b/plugins/user-settings/src/alpha.tsx new file mode 100644 index 0000000000..07cc8ce547 --- /dev/null +++ b/plugins/user-settings/src/alpha.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 { + coreExtensionData, + createExtensionInput, + createPageExtension, + createPlugin, +} from '@backstage/frontend-plugin-api'; +import { convertLegacyRouteRef } from '@backstage/core-plugin-api/alpha'; +import { settingsRouteRef } from './plugin'; + +import React from 'react'; + +export * from './translation'; + +const UserSettingsPage = createPageExtension({ + id: 'plugin.user-settings.page', + defaultPath: '/settings', + routeRef: convertLegacyRouteRef(settingsRouteRef), + inputs: { + providerSettings: createExtensionInput( + { + element: coreExtensionData.reactElement, + }, + { singleton: true, optional: true }, + ), + }, + loader: ({ inputs }) => + import('./components/SettingsPage').then(m => ( + <m.SettingsPage providerSettings={inputs.providerSettings?.element} /> + )), +}); + +/** + * @alpha + */ +export default createPlugin({ + id: 'user-settings', + extensions: [UserSettingsPage], + routes: { + root: convertLegacyRouteRef(settingsRouteRef), + }, +}); diff --git a/plugins/vault-backend/CHANGELOG.md b/plugins/vault-backend/CHANGELOG.md index 3253d8b99c..d623adcf33 100644 --- a/plugins/vault-backend/CHANGELOG.md +++ b/plugins/vault-backend/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-vault-backend +## 0.3.11 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-tasks@0.5.11 + - @backstage/backend-common@0.19.8 + - @backstage/errors@1.2.3 + - @backstage/config@1.1.1 + +## 0.3.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-common@0.19.8-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/backend-tasks@0.5.11-next.2 + - @backstage/config@1.1.1-next.0 + ## 0.3.10-next.1 ### Patch Changes diff --git a/plugins/vault-backend/package.json b/plugins/vault-backend/package.json index 6906b8124d..883bb5281b 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.3.10-next.1", + "version": "0.3.11", "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 38121353c0..37ed1eb14e 100644 --- a/plugins/vault/CHANGELOG.md +++ b/plugins/vault/CHANGELOG.md @@ -1,5 +1,31 @@ # @backstage/plugin-vault +## 0.1.20 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/plugin-catalog-react@1.8.5 + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/catalog-model@1.4.3 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.1.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/catalog-model@1.4.3-next.0 + - @backstage/plugin-catalog-react@1.8.5-next.2 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.1.20-next.1 ### Patch Changes diff --git a/plugins/vault/package.json b/plugins/vault/package.json index 014e9b0d50..055d38073a 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.20-next.1", + "version": "0.1.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -47,8 +47,8 @@ "react-use": "^17.2.4" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -56,9 +56,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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", "msw": "^1.0.0" }, diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index f3bebcb916..9682aa6411 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-xcmetrics +## 0.2.44 + +### Patch Changes + +- 9a1fce352e: Updated dependency `@testing-library/jest-dom` to `^6.0.0`. +- f95af4e540: Updated dependency `@testing-library/dom` to `^9.0.0`. +- Updated dependencies + - @backstage/core-plugin-api@1.7.0 + - @backstage/core-components@0.13.6 + - @backstage/errors@1.2.3 + - @backstage/theme@0.4.3 + +## 0.2.44-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.13.6-next.2 + - @backstage/core-plugin-api@1.7.0-next.1 + - @backstage/errors@1.2.3-next.0 + - @backstage/theme@0.4.3-next.0 + ## 0.2.44-next.1 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index c39c0e4963..97887eb2ea 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.44-next.1", + "version": "0.2.44", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -44,8 +44,8 @@ "recharts": "^2.5.0" }, "peerDependencies": { - "react": "^16.13.1 || ^17.0.0", - "react-dom": "^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", "react-router-dom": "6.0.0-beta.0 || ^6.3.0" }, "devDependencies": { @@ -53,9 +53,9 @@ "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^8.0.0", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^12.1.3", + "@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/luxon": "^3.0.0", "msw": "^1.0.0" diff --git a/scripts/build-plugins-report.js b/scripts/build-plugins-report.js new file mode 100755 index 0000000000..2caaba4530 --- /dev/null +++ b/scripts/build-plugins-report.js @@ -0,0 +1,183 @@ +#!/usr/bin/env node +/* + * 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. + */ + +const fs = require('fs-extra'); +const path = require('path'); +const { execFile: execFileCb } = require('child_process'); +const { promisify } = require('util'); + +const execFile = promisify(execFileCb); + +const rootDirectory = path.resolve(__dirname, '..'); +const pluginsDirectory = path.resolve(rootDirectory, 'plugins'); + +async function run(command, ...args) { + const { stdout, stderr } = await execFile(command, args, { + cwd: rootDirectory, + }); + + if (stderr) { + console.error(stderr); + } + + return stdout.trim(); +} + +function findLatestValidCommit(commits, directoryPath) { + return commits.find(commit => { + const { author, message, files } = commit; + + // exclude merge commits + if (message.startsWith('Merge pull request #')) { + return false; + } + + // exclude commits authored by a bot + if (author.includes('[bot]')) { + return false; + } + + // exclude core maintainers' commits + if ( + [ + 'ben@blam.sh', + 'freben@gmail.com', + 'poldsberg@gmail.com', + 'johan.haals@gmail.com', + ].some(email => author.includes(email)) + ) { + return false; + } + + // ignore multiple plugins changes + if ( + files.some(file => { + const fileFullPath = path.resolve(rootDirectory, file); + if (!fileFullPath.startsWith(pluginsDirectory)) { + return false; + } + const pluginBasePath = directoryPath.replace( + /-(backend|common|react|node).*$/, + '', + ); + return !fileFullPath.startsWith(pluginBasePath); + }) + ) { + return false; + } + + return true; + }); +} + +async function getPluginDirectory(directoryName) { + const directoryPath = path.resolve(pluginsDirectory, directoryName); + const packageJson = await fs.readJson( + path.resolve(directoryPath, 'package.json'), + ); + return { directoryName, directoryPath, packageJson }; +} + +function parseCommitsLog(log) { + const lines = log.split('\n'); + return lines.reduce((commits, line) => { + if (!line) return commits; + if (line.includes(';')) { + const [author, message, date] = line.split(';'); + return [...commits, { author, message, date, files: [] }]; + } + const { files, ...commit } = commits.pop(); + return [...commits, { ...commit, files: [...files, line] }]; + }, []); +} + +async function readDirectoryCommits(directoryName) { + const maxCount = 100; + const directoryPath = path.resolve(pluginsDirectory, directoryName); + + const logOutput = await run( + 'git', + 'log', + 'origin/master', + '--name-only', + `--max-count=${maxCount}`, + '--pretty=format:%an <%ae>;%s;%as', + '--', + // ignore changes on README and package.json files + path.posix.resolve(directoryPath, 'src'), + `:(exclude)${path.posix.resolve(directoryPath, 'src', '**', '*.test.*')}`, + ); + + return parseCommitsLog(logOutput); +} + +async function getLatestDirectoryCommit({ directoryName, directoryPath }) { + console.log(`🔎 Reading data for ${directoryName}`); + + const commits = await readDirectoryCommits(directoryName); + + const commit = findLatestValidCommit(commits, directoryPath) ?? { + author: '-', + message: '-', + date: '-', + }; + + return { plugin: directoryName, ...commit }; +} + +function isValidDirectory({ packageJson }) { + const roles = [ + 'frontend-plugin', + 'frontend-plugin-module', + 'backend-plugin', + 'backend-plugin-module', + ]; + return roles.includes(packageJson?.backstage?.role ?? ''); +} + +async function main() { + const directoryNames = fs + .readdirSync(pluginsDirectory, { withFileTypes: true }) + .filter(dirent => dirent.isDirectory()) + .map(dirent => dirent.name); + + const directories = await Promise.all(directoryNames.map(getPluginDirectory)); + + const commits = await Promise.all( + directories.filter(isValidDirectory).map(getLatestDirectoryCommit), + ); + + const fileName = 'plugins-report.csv'; + + const fileContent = [ + 'Plugin;Author;Message;Date', + ...commits.map(c => `${c.plugin};${c.author};${c.message};${c.date}`), + ]; + + console.log(`📊 Generating plugins report...`); + + fs.writeFile(fileName, fileContent.join('\n'), err => { + if (err) throw err; + }); + + console.log(`📄 Report generated at ${fileName}`); +} + +main(process.argv.slice(2)).catch(error => { + console.error(error.stack || error); + process.exit(1); +}); diff --git a/storybook/package.json b/storybook/package.json index 6a86cd90bd..46cf09dc79 100644 --- a/storybook/package.json +++ b/storybook/package.json @@ -9,8 +9,8 @@ }, "dependencies": { "@swc/core": "^1.3.46", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.0.2", + "react-dom": "^18.0.2", "react-hot-loader": "^4.13.0", "swc-loader": "^0.2.3" }, diff --git a/storybook/yarn.lock b/storybook/yarn.lock index 9a533c46c0..00ec6908f0 100644 --- a/storybook/yarn.lock +++ b/storybook/yarn.lock @@ -9592,16 +9592,15 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^17.0.2": - version: 17.0.2 - resolution: "react-dom@npm:17.0.2" +"react-dom@npm:^18.0.2": + version: 18.2.0 + resolution: "react-dom@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - scheduler: ^0.20.2 + scheduler: ^0.23.0 peerDependencies: - react: 17.0.2 - checksum: 1c1eaa3bca7c7228d24b70932e3d7c99e70d1d04e13bb0843bbf321582bc25d7961d6b8a6978a58a598af2af496d1cedcfb1bf65f6b0960a0a8161cb8dab743c + react: ^18.2.0 + checksum: 7d323310bea3a91be2965f9468d552f201b1c27891e45ddc2d6b8f717680c95a75ae0bc1e3f5cf41472446a2589a75aed4483aee8169287909fcd59ad149e8cc languageName: node linkType: hard @@ -9710,13 +9709,12 @@ __metadata: languageName: node linkType: hard -"react@npm:^17.0.2": - version: 17.0.2 - resolution: "react@npm:17.0.2" +"react@npm:^18.0.2": + version: 18.2.0 + resolution: "react@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: b254cc17ce3011788330f7bbf383ab653c6848902d7936a87b09d835d091e3f295f7e9dd1597c6daac5dc80f90e778c8230218ba8ad599f74adcc11e33b9d61b + checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b languageName: node linkType: hard @@ -10149,13 +10147,12 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:^0.20.2": - version: 0.20.2 - resolution: "scheduler@npm:0.20.2" +"scheduler@npm:^0.23.0": + version: 0.23.0 + resolution: "scheduler@npm:0.23.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: c4b35cf967c8f0d3e65753252d0f260271f81a81e427241295c5a7b783abf4ea9e905f22f815ab66676f5313be0a25f47be582254db8f9241b259213e999b8fc + checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a languageName: node linkType: hard @@ -10682,8 +10679,8 @@ __metadata: "@storybook/react": ^6.5.9 "@storybook/testing-library": ^0.2.0 "@swc/core": ^1.3.46 - react: ^17.0.2 - react-dom: ^17.0.2 + react: ^18.0.2 + react-dom: ^18.0.2 react-hot-loader: ^4.13.0 storybook-dark-mode: ^1.1.0 swc-loader: ^0.2.3 diff --git a/yarn.lock b/yarn.lock index 24252922b9..1e2f6fdb5d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,7 +12,7 @@ __metadata: languageName: node linkType: hard -"@adobe/css-tools@npm:^4.0.1": +"@adobe/css-tools@npm:^4.3.1": version: 4.3.1 resolution: "@adobe/css-tools@npm:4.3.1" checksum: ad43456379ff391132aff687ece190cb23ea69395e23c9b96690eeabe2468da89a4aaf266e4f8b6eaab53db3d1064107ce0f63c3a974e864f4a04affc768da3f @@ -103,8 +103,8 @@ __metadata: linkType: hard "@apollo/client@npm:^3.0.0": - version: 3.8.5 - resolution: "@apollo/client@npm:3.8.5" + version: 3.8.6 + resolution: "@apollo/client@npm:3.8.6" dependencies: "@graphql-typed-document-node/core": ^3.1.1 "@wry/context": ^0.7.3 @@ -134,7 +134,7 @@ __metadata: optional: true subscriptions-transport-ws: optional: true - checksum: 242db8340d5f04ff8f2c9ad6a0dc6ab6d596fb5c763865b0d392f6e5771d55de28faa981dcadaea80ee8b21d4ff40bfa51152a10bcae4158ecf035e47b0d17c4 + checksum: 34a917d3456c1f728834eaaee00a98f82c7f60de8e0e0c62154667f7e95a635740a2d43fe43f51f85950eb2abe06a3d326f32393a48dd4afc6e4fb4357876dc1 languageName: node linkType: hard @@ -1689,8 +1689,8 @@ __metadata: linkType: hard "@azure/identity@npm:^3.2.1": - version: 3.3.0 - resolution: "@azure/identity@npm:3.3.0" + version: 3.3.1 + resolution: "@azure/identity@npm:3.3.1" dependencies: "@azure/abort-controller": ^1.0.0 "@azure/core-auth": ^1.5.0 @@ -1708,7 +1708,7 @@ __metadata: stoppable: ^1.1.0 tslib: ^2.2.0 uuid: ^8.3.0 - checksum: 95c6f8761ad6bbfd3fbf8a88d1a4af17199fb6b61134a761d51a2df096cb175a5841f02ca5ae3285378c64676e72ce6cddc58143306eef5086a63459c2cef914 + checksum: ba58ce8d6178566757c0554b9b5d6ca3d4e934eb6831c9a7d57ada185ec57bd9a9de1ce9500a547e35f4d11cfb362c312afaad019d1ed6bf7b6ebf908bfea362 languageName: node linkType: hard @@ -1800,13 +1800,13 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.18.6, @babel/code-frame@npm:^7.22.10, @babel/code-frame@npm:^7.22.5, @babel/code-frame@npm:^7.8.3": - version: 7.22.10 - resolution: "@babel/code-frame@npm:7.22.10" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.0, @babel/code-frame@npm:^7.16.7, @babel/code-frame@npm:^7.18.6, @babel/code-frame@npm:^7.22.10, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.8.3": + version: 7.22.13 + resolution: "@babel/code-frame@npm:7.22.13" dependencies: - "@babel/highlight": ^7.22.10 + "@babel/highlight": ^7.22.13 chalk: ^2.4.2 - checksum: 89a06534ad19759da6203a71bad120b1d7b2ddc016c8e07d4c56b35dea25e7396c6da60a754e8532a86733092b131ae7f661dbe6ba5d165ea777555daa2ed3c9 + checksum: 22e342c8077c8b77eeb11f554ecca2ba14153f707b85294fcf6070b6f6150aae88a7b7436dd88d8c9289970585f3fe5b9b941c5aa3aa26a6d5a8ef3f292da058 languageName: node linkType: hard @@ -1840,15 +1840,15 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.14.0, @babel/generator@npm:^7.18.13, @babel/generator@npm:^7.22.10, @babel/generator@npm:^7.7.2": - version: 7.22.10 - resolution: "@babel/generator@npm:7.22.10" +"@babel/generator@npm:^7.14.0, @babel/generator@npm:^7.18.13, @babel/generator@npm:^7.22.10, @babel/generator@npm:^7.23.0, @babel/generator@npm:^7.7.2": + version: 7.23.0 + resolution: "@babel/generator@npm:7.23.0" dependencies: - "@babel/types": ^7.22.10 + "@babel/types": ^7.23.0 "@jridgewell/gen-mapping": ^0.3.2 "@jridgewell/trace-mapping": ^0.3.17 jsesc: ^2.5.1 - checksum: 59a79730abdff9070692834bd3af179e7a9413fa2ff7f83dff3eb888765aeaeb2bfc7b0238a49613ed56e1af05956eff303cc139f2407eda8df974813e486074 + checksum: 8efe24adad34300f1f8ea2add420b28171a646edc70f2a1b3e1683842f23b8b7ffa7e35ef0119294e1901f45bfea5b3dc70abe1f10a1917ccdfb41bed69be5f1 languageName: node linkType: hard @@ -1930,20 +1930,20 @@ __metadata: languageName: node linkType: hard -"@babel/helper-environment-visitor@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-environment-visitor@npm:7.22.5" - checksum: 248532077d732a34cd0844eb7b078ff917c3a8ec81a7f133593f71a860a582f05b60f818dc5049c2212e5baa12289c27889a4b81d56ef409b4863db49646c4b1 +"@babel/helper-environment-visitor@npm:^7.22.20, @babel/helper-environment-visitor@npm:^7.22.5": + version: 7.22.20 + resolution: "@babel/helper-environment-visitor@npm:7.22.20" + checksum: d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 languageName: node linkType: hard -"@babel/helper-function-name@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-function-name@npm:7.22.5" +"@babel/helper-function-name@npm:^7.22.5, @babel/helper-function-name@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-function-name@npm:7.23.0" dependencies: - "@babel/template": ^7.22.5 - "@babel/types": ^7.22.5 - checksum: 6b1f6ce1b1f4e513bf2c8385a557ea0dd7fa37971b9002ad19268ca4384bbe90c09681fe4c076013f33deabc63a53b341ed91e792de741b4b35e01c00238177a + "@babel/template": ^7.22.15 + "@babel/types": ^7.23.0 + checksum: e44542257b2d4634a1f979244eb2a4ad8e6d75eb6761b4cfceb56b562f7db150d134bc538c8e6adca3783e3bc31be949071527aa8e3aab7867d1ad2d84a26e10 languageName: node linkType: hard @@ -2065,10 +2065,10 @@ __metadata: languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-validator-identifier@npm:7.22.5" - checksum: 7f0f30113474a28298c12161763b49de5018732290ca4de13cdaefd4fd0d635a6fe3f6686c37a02905fb1e64f21a5ee2b55140cf7b070e729f1bd66866506aea +"@babel/helper-validator-identifier@npm:^7.22.20, @babel/helper-validator-identifier@npm:^7.22.5": + version: 7.22.20 + resolution: "@babel/helper-validator-identifier@npm:7.22.20" + checksum: 136412784d9428266bcdd4d91c32bcf9ff0e8d25534a9d94b044f77fe76bc50f941a90319b05aafd1ec04f7d127cd57a179a3716009ff7f3412ef835ada95bdc languageName: node linkType: hard @@ -2101,23 +2101,23 @@ __metadata: languageName: node linkType: hard -"@babel/highlight@npm:^7.0.0, @babel/highlight@npm:^7.22.10": - version: 7.22.10 - resolution: "@babel/highlight@npm:7.22.10" +"@babel/highlight@npm:^7.0.0, @babel/highlight@npm:^7.22.13": + version: 7.22.20 + resolution: "@babel/highlight@npm:7.22.20" dependencies: - "@babel/helper-validator-identifier": ^7.22.5 + "@babel/helper-validator-identifier": ^7.22.20 chalk: ^2.4.2 js-tokens: ^4.0.0 - checksum: f714a1e1a72dd9d72f6383f4f30fd342e21a8df32d984a4ea8f5eab691bb6ba6db2f8823d4b4cf135d98869e7a98925b81306aa32ee3c429f8cfa52c75889e1b + checksum: 84bd034dca309a5e680083cd827a766780ca63cef37308404f17653d32366ea76262bd2364b2d38776232f2d01b649f26721417d507e8b4b6da3e4e739f6d134 languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.13.16, @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.22.11, @babel/parser@npm:^7.22.5": - version: 7.22.11 - resolution: "@babel/parser@npm:7.22.11" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.13.16, @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.22.11, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/parser@npm:7.23.0" bin: parser: ./bin/babel-parser.js - checksum: 332079ed09794d3685343e9fc39c6a12dcb6ea589119f2135952cdef2424296786bb609a33f6dfa9be271797bbf8339f1865118418ea50b32a0c701734c96664 + checksum: 453fdf8b9e2c2b7d7b02139e0ce003d1af21947bbc03eb350fb248ee335c9b85e4ab41697ddbdd97079698de825a265e45a0846bb2ed47a2c7c1df833f42a354 languageName: node linkType: hard @@ -3295,13 +3295,13 @@ __metadata: languageName: node linkType: hard -"@babel/runtime-corejs3@npm:^7.20.13, @babel/runtime-corejs3@npm:^7.20.7, @babel/runtime-corejs3@npm:^7.22.11": - version: 7.22.15 - resolution: "@babel/runtime-corejs3@npm:7.22.15" +"@babel/runtime-corejs3@npm:^7.20.7, @babel/runtime-corejs3@npm:^7.22.15, @babel/runtime-corejs3@npm:^7.23.1": + version: 7.23.1 + resolution: "@babel/runtime-corejs3@npm:7.23.1" dependencies: core-js-pure: ^3.30.2 regenerator-runtime: ^0.14.0 - checksum: 6e27ca3890282612316aa87a9cd60fc19888ac26c802af926b4488ad67b3b06929086884974e9237fa550f48a5fe22c9c5e5be229bba9c4c017cfb2374835518 + checksum: 5d52b0cc8b5d243e67cf29c584d15acdc0c89b64de4a3fe1cb8a83b84b64a5621802e36931f93ca696cb637884abd11c8514615d890a4edf057ec4464f73915d languageName: node linkType: hard @@ -3314,43 +3314,43 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.18.10, @babel/template@npm:^7.22.5, @babel/template@npm:^7.3.3": - version: 7.22.5 - resolution: "@babel/template@npm:7.22.5" +"@babel/template@npm:^7.18.10, @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: - "@babel/code-frame": ^7.22.5 - "@babel/parser": ^7.22.5 - "@babel/types": ^7.22.5 - checksum: c5746410164039aca61829cdb42e9a55410f43cace6f51ca443313f3d0bdfa9a5a330d0b0df73dc17ef885c72104234ae05efede37c1cc8a72dc9f93425977a3 + "@babel/code-frame": ^7.22.13 + "@babel/parser": ^7.22.15 + "@babel/types": ^7.22.15 + checksum: 1f3e7dcd6c44f5904c184b3f7fe280394b191f2fed819919ffa1e529c259d5b197da8981b6ca491c235aee8dbad4a50b7e31304aa531271cb823a4a24a0dd8fd languageName: node linkType: hard "@babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.22.11, @babel/traverse@npm:^7.4.5, @babel/traverse@npm:^7.7.2": - version: 7.22.11 - resolution: "@babel/traverse@npm:7.22.11" + version: 7.23.2 + resolution: "@babel/traverse@npm:7.23.2" dependencies: - "@babel/code-frame": ^7.22.10 - "@babel/generator": ^7.22.10 - "@babel/helper-environment-visitor": ^7.22.5 - "@babel/helper-function-name": ^7.22.5 + "@babel/code-frame": ^7.22.13 + "@babel/generator": ^7.23.0 + "@babel/helper-environment-visitor": ^7.22.20 + "@babel/helper-function-name": ^7.23.0 "@babel/helper-hoist-variables": ^7.22.5 "@babel/helper-split-export-declaration": ^7.22.6 - "@babel/parser": ^7.22.11 - "@babel/types": ^7.22.11 + "@babel/parser": ^7.23.0 + "@babel/types": ^7.23.0 debug: ^4.1.0 globals: ^11.1.0 - checksum: 4ad62d548ca8b95dbf45bae16cc167428f174f3c837d55a5878b1f17bdbc8b384d6df741dc7c461b62c04d881cf25644d3ab885909ba46e3ac43224e2b15b504 + checksum: 26a1eea0dde41ab99dde8b9773a013a0dc50324e5110a049f5d634e721ff08afffd54940b3974a20308d7952085ac769689369e9127dea655f868c0f6e1ab35d 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.22.10, @babel/types@npm:^7.22.11, @babel/types@npm:^7.22.5, @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.22.11 - resolution: "@babel/types@npm:7.22.11" +"@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.22.10, @babel/types@npm:^7.22.11, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @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.0 + resolution: "@babel/types@npm:7.23.0" dependencies: "@babel/helper-string-parser": ^7.22.5 - "@babel/helper-validator-identifier": ^7.22.5 + "@babel/helper-validator-identifier": ^7.22.20 to-fast-properties: ^2.0.0 - checksum: 431a6446896adb62c876d0fe75263835735d3c974aae05356a87eb55f087c20a777028cf08eadcace7993e058bbafe3b21ce2119363222c6cef9eedd7a204810 + checksum: 215fe04bd7feef79eeb4d33374b39909ce9cad1611c4135a4f7fdf41fe3280594105af6d7094354751514625ea92d0875aba355f53e86a92600f290e77b0e604 languageName: node linkType: hard @@ -3367,12 +3367,12 @@ __metadata: "@backstage/theme": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@testing-library/jest-dom": ^6.0.0 + "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -3415,7 +3415,6 @@ __metadata: logform: ^2.3.2 minimatch: ^5.0.0 minimist: ^1.2.5 - mock-fs: ^5.2.0 morgan: ^1.10.0 node-forge: ^1.3.1 selfsigned: ^2.0.0 @@ -3450,7 +3449,7 @@ __metadata: "@google-cloud/storage": ^6.0.0 "@keyv/memcache": ^1.3.5 "@keyv/redis": ^2.5.3 - "@kubernetes/client-node": 0.18.1 + "@kubernetes/client-node": 0.19.0 "@manypkg/get-packages": ^1.1.3 "@octokit/rest": ^19.0.3 "@types/archiver": ^5.1.0 @@ -3463,12 +3462,7 @@ __metadata: "@types/fs-extra": ^9.0.3 "@types/http-errors": ^2.0.0 "@types/luxon": ^3.0.0 - "@types/minimist": ^1.2.0 - "@types/morgan": ^1.9.0 - "@types/node-forge": ^1.3.0 "@types/pg": ^8.6.6 - "@types/recursive-readdir": ^2.2.0 - "@types/stoppable": ^1.1.0 "@types/supertest": ^2.0.8 "@types/tar": ^6.1.1 "@types/webpack-env": ^1.15.2 @@ -3495,17 +3489,11 @@ __metadata: logform: ^2.3.2 luxon: ^3.0.0 minimatch: ^5.0.0 - minimist: ^1.2.5 - morgan: ^1.10.0 msw: ^1.0.0 mysql2: ^2.2.5 node-fetch: ^2.6.7 - node-forge: ^1.3.1 pg: ^8.3.0 raw-body: ^2.4.1 - recursive-readdir: ^2.2.2 - selfsigned: ^2.0.0 - stoppable: ^1.1.0 supertest: ^6.1.3 tar: ^6.1.12 uuid: ^8.3.2 @@ -3662,7 +3650,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/catalog-client@^1.4.4, @backstage/catalog-client@workspace:^, @backstage/catalog-client@workspace:packages/catalog-client": +"@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" dependencies: @@ -3679,15 +3667,12 @@ __metadata: resolution: "@backstage/catalog-model@workspace:packages/catalog-model" dependencies: "@backstage/cli": "workspace:^" - "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/types": "workspace:^" "@types/json-schema": ^7.0.5 "@types/lodash": ^4.14.151 ajv: ^8.10.0 - json-schema: ^0.4.0 lodash: ^4.17.21 - uuid: ^8.0.0 yaml: ^2.0.0 languageName: unknown linkType: soft @@ -3773,7 +3758,6 @@ __metadata: "@types/inquirer": ^8.1.3 "@types/jest": ^29.0.0 "@types/minimatch": ^5.0.0 - "@types/mock-fs": ^4.13.0 "@types/node": ^18.17.8 "@types/npm-packlist": ^3.0.0 "@types/recursive-readdir": ^2.2.0 @@ -3784,8 +3768,8 @@ __metadata: "@types/terser-webpack-plugin": ^5.0.4 "@types/webpack-env": ^1.15.2 "@types/yarnpkg__lockfile": ^1.1.4 - "@typescript-eslint/eslint-plugin": ^5.9.0 - "@typescript-eslint/parser": ^5.9.0 + "@typescript-eslint/eslint-plugin": 6.7.5 + "@typescript-eslint/parser": ^6.7.2 "@yarnpkg/lockfile": ^1.1.0 "@yarnpkg/parsers": ^3.0.0-rc.4 bfj: ^7.0.2 @@ -3828,7 +3812,6 @@ __metadata: lodash: ^4.17.21 mini-css-extract-plugin: ^2.4.2 minimatch: ^5.1.1 - mock-fs: ^5.2.0 msw: ^1.0.0 node-fetch: ^2.6.7 node-libs-browser: ^2.2.1 @@ -3904,7 +3887,6 @@ __metadata: "@types/json-schema": ^7.0.6 "@types/json-schema-merge-allof": ^0.6.0 "@types/mock-fs": ^4.10.0 - "@types/yup": ^0.29.13 ajv: ^8.10.0 chokidar: ^3.5.2 fs-extra: 10.1.0 @@ -3913,17 +3895,15 @@ __metadata: json-schema-traverse: ^1.0.0 lodash: ^4.17.21 minimist: ^1.2.5 - mock-fs: ^5.2.0 msw: ^1.0.0 node-fetch: ^2.6.7 - typescript-json-schema: ^0.55.0 + typescript-json-schema: ^0.61.0 yaml: ^2.0.0 - yup: ^0.32.9 zen-observable: ^0.10.0 languageName: unknown linkType: soft -"@backstage/config@^1.0.6, @backstage/config@^1.0.7, @backstage/config@^1.1.0, @backstage/config@workspace:^, @backstage/config@workspace:packages/config": +"@backstage/config@^1.0.6, @backstage/config@^1.0.7, @backstage/config@workspace:^, @backstage/config@workspace:packages/config": version: 0.0.0-use.local resolution: "@backstage/config@workspace:packages/config" dependencies: @@ -3945,9 +3925,9 @@ __metadata: "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" "@backstage/version-bridge": "workspace:^" - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@testing-library/dom": ^9.0.0 + "@testing-library/jest-dom": ^6.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 "@types/prop-types": ^15.7.3 @@ -3966,8 +3946,101 @@ __metadata: zen-observable: ^0.10.0 zod: ^3.21.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + languageName: unknown + linkType: soft + +"@backstage/core-compat-api@workspace:^, @backstage/core-compat-api@workspace:packages/core-compat-api": + version: 0.0.0-use.local + resolution: "@backstage/core-compat-api@workspace:packages/core-compat-api" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" + "@backstage/plugin-puppetdb": "workspace:^" + "@backstage/plugin-stackstorm": "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.5, @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/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/plugin-catalog-react": "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: ^3.1.5 + 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.1 + linkifyjs: 4.1.1 + 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 @@ -4022,158 +4095,7 @@ __metadata: languageName: node linkType: hard -"@backstage/core-components@npm:^0.13.5": - version: 0.13.5 - resolution: "@backstage/core-components@npm:0.13.5" - dependencies: - "@backstage/config": ^1.1.0 - "@backstage/core-plugin-api": ^1.6.0 - "@backstage/errors": ^1.2.2 - "@backstage/theme": ^0.4.2 - "@backstage/version-bridge": ^1.0.5 - "@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.1 - linkifyjs: 4.1.1 - lodash: ^4.17.21 - pluralize: ^8.0.0 - prop-types: ^15.7.2 - 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 - react-dom: ^16.13.1 || ^17.0.0 - react-router-dom: 6.0.0-beta.0 || ^6.3.0 - checksum: f1c9290fd1358561c9a1098200cdf1d2dc16117aebf4010759f122b0a638acb50a89faa24988ad4a854ace59a74606329550c59fc98ab6281feb4b4f5bfe52c0 - 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/catalog-model": "workspace:^" - "@backstage/cli": "workspace:^" - "@backstage/config": "workspace:^" - "@backstage/core-app-api": "workspace:^" - "@backstage/core-plugin-api": "workspace:^" - "@backstage/errors": "workspace:^" - "@backstage/plugin-catalog-react": "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": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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: ^3.1.5 - 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.1 - linkifyjs: 4.1.1 - lodash: ^4.17.21 - msw: ^1.0.0 - pluralize: ^8.0.0 - prop-types: ^15.7.2 - 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 - react-dom: ^16.13.1 || ^17.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.6.0": - version: 1.6.0 - resolution: "@backstage/core-plugin-api@npm:1.6.0" - dependencies: - "@backstage/config": ^1.1.0 - "@backstage/types": ^1.1.1 - "@backstage/version-bridge": ^1.0.5 - "@types/react": ^16.13.1 || ^17.0.0 - history: ^5.0.0 - i18next: ^22.4.15 - prop-types: ^15.7.2 - zen-observable: ^0.10.0 - 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: 540deb91d3c143ce1c3736359c3301af64fbd6eccbaae61bfc96f4e180654e7eb025bb1d4ff5be62b7ea3d6dac7ed617e4dba0c176cfdbf865400fde0f987ddb - languageName: node - linkType: hard - -"@backstage/core-plugin-api@workspace:^, @backstage/core-plugin-api@workspace:packages/core-plugin-api": +"@backstage/core-plugin-api@^1.3.0, @backstage/core-plugin-api@^1.5.0, @backstage/core-plugin-api@^1.6.0, @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: @@ -4183,22 +4105,16 @@ __metadata: "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" "@backstage/version-bridge": "workspace:^" - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/prop-types": ^15.7.3 "@types/react": ^16.13.1 || ^17.0.0 - "@types/zen-observable": ^0.8.0 history: ^5.0.0 i18next: ^22.4.15 - msw: ^1.0.0 - prop-types: ^15.7.2 - zen-observable: ^0.10.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4207,6 +4123,7 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/create-app@workspace:packages/create-app" dependencies: + "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" "@types/command-exists": ^1.2.0 @@ -4245,16 +4162,16 @@ __metadata: "@backstage/theme": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 react-use: ^17.2.4 zen-observable: ^0.10.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4276,13 +4193,12 @@ __metadata: languageName: unknown linkType: soft -"@backstage/errors@^1.1.5, @backstage/errors@^1.2.2, @backstage/errors@workspace:^, @backstage/errors@workspace:packages/errors": +"@backstage/errors@^1.1.5, @backstage/errors@workspace:^, @backstage/errors@workspace:packages/errors": version: 0.0.0-use.local resolution: "@backstage/errors@workspace:packages/errors" dependencies: "@backstage/cli": "workspace:^" "@backstage/types": "workspace:^" - cross-fetch: ^3.1.5 serialize-error: ^8.0.1 languageName: unknown linkType: soft @@ -4315,12 +4231,12 @@ __metadata: "@backstage/version-bridge": "workspace:^" "@material-ui/core": ^4.12.4 "@material-ui/icons": ^4.11.3 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@testing-library/jest-dom": ^6.0.0 + "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 lodash: ^4.17.21 peerDependencies: - react: ^16.13.1 || ^17.0.0 + 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 @@ -4334,14 +4250,16 @@ __metadata: "@backstage/frontend-app-api": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@backstage/version-bridge": "workspace:^" + "@testing-library/jest-dom": ^6.0.0 + "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 + history: ^5.3.0 lodash: ^4.17.21 zod: ^3.21.4 zod-to-json-schema: ^3.21.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 + 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 @@ -4365,29 +4283,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/integration-react@npm:^1.1.19": - version: 1.1.19 - resolution: "@backstage/integration-react@npm:1.1.19" - dependencies: - "@backstage/config": ^1.1.0 - "@backstage/core-components": ^0.13.5 - "@backstage/core-plugin-api": ^1.6.0 - "@backstage/integration": ^1.7.0 - "@backstage/theme": ^0.4.2 - "@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 - 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: 8ef2b46bf91b71351aa4b114de147d130e0298d8849cf2fa358ac1559c2026ffbfad10b15f6fa4bf94c7bbb4f4419766c6c66b77d2859fe184a43351f1f5df81 - languageName: node - linkType: hard - -"@backstage/integration-react@workspace:^, @backstage/integration-react@workspace:packages/integration-react": +"@backstage/integration-react@^1.1.19, @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: @@ -4398,41 +4294,19 @@ __metadata: "@backstage/dev-utils": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/test-utils": "workspace:^" - "@backstage/theme": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 - "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/user-event": ^14.0.0 + "@testing-library/dom": ^9.0.0 + "@testing-library/jest-dom": ^6.0.0 "@types/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 - react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft -"@backstage/integration@npm:^1.7.0": - version: 1.7.0 - resolution: "@backstage/integration@npm:1.7.0" - dependencies: - "@azure/identity": ^3.2.1 - "@backstage/config": ^1.1.0 - "@backstage/errors": ^1.2.2 - "@octokit/auth-app": ^4.0.0 - "@octokit/rest": ^19.0.3 - cross-fetch: ^3.1.5 - git-url-parse: ^13.0.0 - lodash: ^4.17.21 - luxon: ^3.0.0 - checksum: f02516b7bdb7adb0516b49b90802e588f09c43b4db66bcce68314518c46b9c6fb8ca76ac7a55d4a80cdd414bb6876475b42eb6256b2efda9824ad3667ffa8f54 - languageName: node - linkType: hard - "@backstage/integration@workspace:^, @backstage/integration@workspace:packages/integration": version: 0.0.0-use.local resolution: "@backstage/integration@workspace:packages/integration" @@ -4441,7 +4315,6 @@ __metadata: "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/config-loader": "workspace:^" - "@backstage/errors": "workspace:^" "@octokit/auth-app": ^4.0.0 "@octokit/rest": ^19.0.3 "@types/luxon": ^3.0.0 @@ -4516,9 +4389,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/git-url-parse": ^9.0.0 "@types/react": ^16.13.1 || ^17.0.0 @@ -4529,8 +4402,8 @@ __metadata: react-use: ^17.2.4 remark-gfm: ^3.0.1 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4572,16 +4445,16 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4602,16 +4475,16 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4628,9 +4501,9 @@ __metadata: "@backstage/dev-utils": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/jest": ^28.1.3 "@types/react": ^16.13.1 || ^17.0.0 @@ -4638,8 +4511,8 @@ __metadata: react-ga4: ^2.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4659,18 +4532,17 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 - prop-types: ^15.7.2 react-ga: ^3.3.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4687,13 +4559,13 @@ __metadata: "@backstage/dev-utils": "workspace:^" "@backstage/test-utils": "workspace:^" "@newrelic/browser-agent": ^1.236.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@testing-library/jest-dom": ^6.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 languageName: unknown linkType: soft @@ -4710,9 +4582,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 cross-fetch: ^3.1.5 @@ -4720,8 +4592,8 @@ __metadata: qs: ^6.10.1 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4731,12 +4603,12 @@ __metadata: resolution: "@backstage/plugin-api-docs-module-protoc-gen-doc@workspace:plugins/api-docs-module-protoc-gen-doc" dependencies: "@backstage/cli": "workspace:^" - "@testing-library/jest-dom": ^5.16.4 + "@testing-library/jest-dom": ^6.0.0 "@types/react": ^16.13.1 || ^17.0.0 grpc-docs: ^1.1.2 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4759,9 +4631,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 "@types/swagger-ui-react": ^4.18.0 @@ -4774,8 +4646,8 @@ __metadata: react-use: ^17.2.4 swagger-ui-react: ^5.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4794,17 +4666,17 @@ __metadata: "@backstage/theme": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 use-deep-compare-effect: ^1.8.1 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -4919,6 +4791,24 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-auth-backend-module-microsoft-provider@workspace:^, @backstage/plugin-auth-backend-module-microsoft-provider@workspace:plugins/auth-backend-module-microsoft-provider": + version: 0.0.0-use.local + resolution: "@backstage/plugin-auth-backend-module-microsoft-provider@workspace:plugins/auth-backend-module-microsoft-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.6.0 + passport-microsoft: ^1.0.0 + supertest: ^6.3.3 + languageName: unknown + linkType: soft + "@backstage/plugin-auth-backend-module-oauth2-provider@workspace:^, @backstage/plugin-auth-backend-module-oauth2-provider@workspace:plugins/auth-backend-module-oauth2-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-oauth2-provider@workspace:plugins/auth-backend-module-oauth2-provider" @@ -4937,6 +4827,30 @@ __metadata: 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" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-defaults": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/plugin-auth-backend": "workspace:^" + "@backstage/plugin-auth-node": "workspace:^" + cookie-parser: ^1.4.6 + express: ^4.18.2 + express-promise-router: ^4.1.1 + express-session: ^1.17.3 + jose: ^4.14.6 + msw: ^1.3.0 + openid-client: ^5.4.3 + passport: ^0.6.0 + supertest: ^6.3.3 + languageName: unknown + linkType: soft + "@backstage/plugin-auth-backend@workspace:^, @backstage/plugin-auth-backend@workspace:plugins/auth-backend": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend@workspace:plugins/auth-backend" @@ -4954,6 +4868,7 @@ __metadata: "@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-microsoft-provider": "workspace:^" "@backstage/plugin-auth-backend-module-oauth2-provider": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" @@ -5090,9 +5005,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 humanize-duration: ^3.27.0 @@ -5100,8 +5015,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5153,17 +5068,17 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 luxon: ^3.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5213,12 +5128,12 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/jest-dom": ^5.16.5 + "@testing-library/jest-dom": ^6.0.0 "@types/react": ^16.13.1 || ^17.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5262,15 +5177,15 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@material-ui/pickers": ^3.3.10 - "@testing-library/jest-dom": ^5.10.1 + "@testing-library/jest-dom": ^6.0.0 "@types/react": ^16.13.1 || ^17.0.0 luxon: ^3.0.0 material-ui-search-bar: ^1.0.0 react-hook-form: ^7.13.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5304,9 +5219,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 "@types/recharts": ^1.8.15 @@ -5317,8 +5232,8 @@ __metadata: react-use: ^17.2.4 recharts: ^2.5.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5496,7 +5411,23 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-backend-module-github@workspace:plugins/catalog-backend-module-github": +"@backstage/plugin-catalog-backend-module-github-org@workspace:plugins/catalog-backend-module-github-org": + version: 0.0.0-use.local + resolution: "@backstage/plugin-catalog-backend-module-github-org@workspace:plugins/catalog-backend-module-github-org" + dependencies: + "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-tasks": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/plugin-catalog-backend-module-github": "workspace:^" + "@backstage/plugin-catalog-node": "workspace:^" + luxon: ^3.0.0 + languageName: unknown + linkType: soft + +"@backstage/plugin-catalog-backend-module-github@workspace:^, @backstage/plugin-catalog-backend-module-github@workspace:plugins/catalog-backend-module-github": version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-github@workspace:plugins/catalog-backend-module-github" dependencies: @@ -5508,13 +5439,11 @@ __metadata: "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" - "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-catalog-backend": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-events-node": "workspace:^" - "@backstage/types": "workspace:^" "@octokit/graphql": ^5.0.0 "@octokit/rest": ^19.0.3 "@types/lodash": ^4.14.151 @@ -5540,10 +5469,8 @@ __metadata: "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" - "@backstage/errors": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" - "@backstage/types": "workspace:^" "@types/lodash": ^4.14.151 "@types/uuid": ^8.0.0 lodash: ^4.17.21 @@ -5559,7 +5486,6 @@ __metadata: version: 0.0.0-use.local resolution: "@backstage/plugin-catalog-backend-module-incremental-ingestion@workspace:plugins/catalog-backend-module-incremental-ingestion" dependencies: - "@backstage/backend-app-api": "workspace:^" "@backstage/backend-common": "workspace:^" "@backstage/backend-defaults": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" @@ -5578,7 +5504,6 @@ __metadata: express: ^4.17.1 express-promise-router: ^4.1.0 knex: ^2.0.0 - lodash: ^4.17.21 luxon: ^3.0.0 uuid: ^8.3.2 winston: ^3.2.1 @@ -5728,10 +5653,7 @@ __metadata: "@backstage/plugin-events-node": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-node": "workspace:^" - "@backstage/plugin-scaffolder-common": "workspace:^" "@backstage/plugin-search-backend-module-catalog": "workspace:^" - "@backstage/plugin-search-backend-node": "workspace:^" - "@backstage/plugin-search-common": "workspace:^" "@backstage/types": "workspace:^" "@opentelemetry/api": ^1.3.0 "@types/core-js": ^2.5.4 @@ -5744,7 +5666,6 @@ __metadata: codeowners-utils: ^1.0.2 core-js: ^3.6.5 express: ^4.17.1 - express-promise-router: ^4.1.0 fast-json-stable-stringify: ^2.1.0 fs-extra: 10.1.0 git-url-parse: ^13.0.0 @@ -5767,7 +5688,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-common@^1.0.10, @backstage/plugin-catalog-common@^1.0.16, @backstage/plugin-catalog-common@workspace:^, @backstage/plugin-catalog-common@workspace:plugins/catalog-common": +"@backstage/plugin-catalog-common@^1.0.10, @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: @@ -5797,10 +5718,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/react": ^16.13.1 || ^17.0.0 classnames: ^2.3.1 @@ -5809,8 +5729,8 @@ __metadata: qs: ^6.9.4 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5840,8 +5760,8 @@ __metadata: node-fetch: ^2.6.7 winston: ^3.2.1 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5859,6 +5779,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@backstage/integration": "workspace:^" "@backstage/integration-react": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" @@ -5868,10 +5789,9 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@octokit/rest": ^19.0.3 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/react": ^16.13.1 || ^17.0.0 git-url-parse: ^13.0.0 @@ -5882,8 +5802,8 @@ __metadata: react-use: ^17.2.4 yaml: ^2.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -5904,44 +5824,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-catalog-react@npm:^1.2.4, @backstage/plugin-catalog-react@npm:^1.8.4": - version: 1.8.4 - resolution: "@backstage/plugin-catalog-react@npm:1.8.4" - dependencies: - "@backstage/catalog-client": ^1.4.4 - "@backstage/catalog-model": ^1.4.2 - "@backstage/core-components": ^0.13.5 - "@backstage/core-plugin-api": ^1.6.0 - "@backstage/errors": ^1.2.2 - "@backstage/integration": ^1.7.0 - "@backstage/plugin-catalog-common": ^1.0.16 - "@backstage/plugin-permission-common": ^0.7.8 - "@backstage/plugin-permission-react": ^0.4.15 - "@backstage/theme": ^0.4.2 - "@backstage/types": ^1.1.1 - "@backstage/version-bridge": ^1.0.5 - "@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 - jwt-decode: ^3.1.0 - lodash: ^4.17.21 - material-ui-popup-state: ^1.9.3 - qs: ^6.9.4 - react-use: ^17.2.4 - yaml: ^2.0.0 - zen-observable: ^0.10.0 - 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: 6434741a60e4f53604a958c121d283d3d8b2756e1013d3a9b32659ae41b58359cbc3bee0791a95a35c847f43a76de9f9d2ea1f8e5fa6697adfc9115b5042a57e - languageName: node - linkType: hard - -"@backstage/plugin-catalog-react@workspace:^, @backstage/plugin-catalog-react@workspace:plugins/catalog-react": +"@backstage/plugin-catalog-react@^1.2.4, @backstage/plugin-catalog-react@^1.8.4, @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: @@ -5965,16 +5848,13 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@react-hookz/web": ^23.0.0 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/jwt-decode": ^3.1.0 "@types/react": ^16.13.1 || ^17.0.0 "@types/zen-observable": ^0.8.0 classnames: ^2.2.6 - jwt-decode: ^3.1.0 lodash: ^4.17.21 material-ui-popup-state: ^1.9.3 qs: ^6.9.4 @@ -5983,8 +5863,8 @@ __metadata: yaml: ^2.0.0 zen-observable: ^0.10.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6005,15 +5885,15 @@ __metadata: "@material-ui/core": ^4.9.13 "@material-ui/icons": ^4.9.1 "@material-ui/lab": ^4.0.0-alpha.60 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6044,20 +5924,19 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 history: ^5.0.0 lodash: ^4.17.21 pluralize: ^8.0.0 - react-helmet: 6.1.0 react-use: ^17.2.4 zen-observable: ^0.10.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6076,8 +5955,8 @@ __metadata: luxon: ^3.0.0 p-limit: ^4.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6101,12 +5980,11 @@ __metadata: humanize-duration: ^3.27.0 lodash: ^4.17.21 luxon: ^3.0.0 - prop-types: ^15.7.2 react-use: ^17.3.1 recharts: ^2.5.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6127,9 +6005,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/humanize-duration": ^3.25.1 "@types/react": ^16.13.1 || ^17.0.0 @@ -6141,8 +6019,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6163,9 +6041,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 cross-fetch: ^3.1.5 @@ -6174,8 +6052,8 @@ __metadata: qs: ^6.9.4 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6195,9 +6073,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/humanize-duration": ^3.27.1 "@types/luxon": ^3.0.0 @@ -6207,8 +6085,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6261,9 +6139,9 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@material-ui/styles": ^4.11.0 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/highlightjs": ^10.1.0 "@types/react": ^16.13.1 || ^17.0.0 @@ -6274,8 +6152,8 @@ __metadata: react-use: ^17.2.4 recharts: ^2.5.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6296,17 +6174,17 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 rc-progress: 3.5.1 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6328,9 +6206,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 jsonschema: ^1.2.6 @@ -6338,8 +6216,8 @@ __metadata: react-use: ^17.2.4 zen-observable: ^0.10.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6371,9 +6249,9 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@material-ui/styles": ^4.9.6 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/pluralize": ^0.0.31 "@types/react": ^16.13.1 || ^17.0.0 @@ -6393,8 +6271,8 @@ __metadata: regression: ^2.0.1 yup: ^0.32.9 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6465,8 +6343,8 @@ __metadata: "@material-ui/core": ^4.9.13 "@material-ui/icons": ^4.9.1 "@material-ui/lab": ^4.0.0-alpha.57 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@testing-library/jest-dom": ^6.0.0 + "@testing-library/react": ^14.0.0 "@testing-library/user-event": ^14.0.0 cross-fetch: ^3.1.5 msw: ^1.0.0 @@ -6474,8 +6352,8 @@ __metadata: react-use: ^17.2.4 peerDependencies: "@types/react": ^16.13.1 || ^17.0.0 - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6495,9 +6373,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 express: ^4.18.1 @@ -6505,8 +6383,8 @@ __metadata: react-use: ^17.2.4 peerDependencies: "@backstage/plugin-catalog-react": "workspace:^" - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6563,17 +6441,16 @@ __metadata: "@material-ui/core": ^4.9.13 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.1 + "@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 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6601,9 +6478,9 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@react-hookz/web": ^20.0.0 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 "@uiw/react-codemirror": ^4.9.3 @@ -6612,8 +6489,8 @@ __metadata: react-use: ^17.2.4 yaml: ^2.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6790,16 +6667,16 @@ __metadata: "@backstage/dev-utils": "workspace:^" "@backstage/plugin-explore-common": "workspace:^" "@backstage/test-utils": "workspace:^" - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 cross-fetch: ^3.1.5 msw: ^1.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6827,9 +6704,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 classnames: ^2.2.6 @@ -6838,8 +6715,8 @@ __metadata: pluralize: ^8.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6860,17 +6737,17 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 luxon: ^3.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6892,9 +6769,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 cross-fetch: ^3.1.5 @@ -6903,8 +6780,8 @@ __metadata: p-limit: ^3.0.2 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6926,9 +6803,9 @@ __metadata: "@material-ui/lab": 4.0.0-alpha.61 "@maxim_mazurok/gapi.client.calendar": ^3.0.20220408 "@tanstack/react-query": ^4.1.3 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/dompurify": ^2.3.3 "@types/react": ^16.13.1 || ^17.0.0 @@ -6942,8 +6819,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6963,16 +6840,16 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@react-hookz/web": ^20.0.0 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 cross-fetch: ^3.1.5 msw: ^1.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -6993,10 +6870,9 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@octokit/rest": ^19.0.3 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/react": ^16.13.1 || ^17.0.0 "@types/recharts": ^1.8.15 @@ -7006,8 +6882,8 @@ __metadata: react-use: ^17.2.4 recharts: ^2.5.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7031,9 +6907,9 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@octokit/rest": ^19.0.3 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 cross-fetch: ^3.1.5 @@ -7042,8 +6918,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7068,17 +6944,17 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@octokit/graphql": ^5.0.0 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 luxon: ^3.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7101,9 +6977,9 @@ __metadata: "@material-ui/core": ^4.12.4 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 luxon: ^3.0.0 @@ -7111,8 +6987,8 @@ __metadata: octokit: ^2.0.4 react-use: ^17.4.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7134,9 +7010,9 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@octokit/rest": ^19.0.3 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 luxon: ^3.0.0 @@ -7144,8 +7020,8 @@ __metadata: p-limit: ^4.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7165,17 +7041,17 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 cross-fetch: ^3.1.5 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7197,9 +7073,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/lodash": ^4.14.173 "@types/luxon": ^3.0.0 @@ -7210,8 +7086,8 @@ __metadata: qs: ^6.10.1 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7231,9 +7107,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/codemirror": ^5.0.0 "@types/react": ^16.13.1 || ^17.0.0 @@ -7244,8 +7120,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7289,40 +7165,22 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 graphql-voyager: ^1.0.0-rc.31 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft -"@backstage/plugin-home-react@npm:^0.1.3": - version: 0.1.3 - resolution: "@backstage/plugin-home-react@npm:0.1.3" - dependencies: - "@backstage/core-components": ^0.13.5 - "@backstage/core-plugin-api": ^1.6.0 - "@material-ui/core": ^4.12.2 - "@material-ui/icons": ^4.9.1 - "@rjsf/utils": 5.13.0 - "@types/react": ^16.13.1 || ^17.0.0 - 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: e87c9fd44c65aa1a768555812f32f42b1d2dc7ab1097c283cae37105d1f17a7b1b198c85d39d72258551015161f317c8e4538a652f6e8ebe9800c3a365f6ebc3 - languageName: node - linkType: hard - -"@backstage/plugin-home-react@workspace:^, @backstage/plugin-home-react@workspace:plugins/home-react": +"@backstage/plugin-home-react@^0.1.3, @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: @@ -7335,17 +7193,17 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@rjsf/utils": 5.13.0 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 "@types/react-grid-layout": ^1.3.2 cross-fetch: ^3.1.5 msw: ^1.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7361,6 +7219,7 @@ __metadata: "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" "@backstage/plugin-home-react": "workspace:^" "@backstage/test-utils": "workspace:^" @@ -7369,14 +7228,13 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@rjsf/core-v5": "npm:@rjsf/core@5.13.0" - "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@5.13.0" + "@rjsf/core": 5.13.0 + "@rjsf/material-ui": 5.13.0 "@rjsf/utils": 5.13.0 "@rjsf/validator-ajv8": 5.13.0 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.1 + "@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 "@types/react-grid-layout": ^1.3.2 @@ -7388,8 +7246,8 @@ __metadata: react-use: ^17.2.4 zod: ^3.21.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7413,19 +7271,18 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@material-ui/pickers": ^3.3.10 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 humanize-duration: ^3.26.0 luxon: ^3.0.0 msw: ^1.0.0 - prop-types: ^15.7.2 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7435,12 +7292,14 @@ __metadata: resolution: "@backstage/plugin-jenkins-backend@workspace:plugins/jenkins-backend" dependencies: "@backstage/backend-common": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" "@backstage/catalog-client": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" + "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-jenkins-common": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-node": "workspace:^" @@ -7486,9 +7345,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 "@types/testing-library__jest-dom": ^5.9.1 @@ -7497,8 +7356,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7543,18 +7402,17 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/react": ^16.13.1 || ^17.0.0 jest-when: ^3.1.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7567,6 +7425,7 @@ __metadata: "@aws-sdk/credential-providers": ^3.350.0 "@aws-sdk/signature-v4": ^3.347.0 "@azure/identity": ^3.2.1 + "@backstage/backend-app-api": "workspace:^" "@backstage/backend-common": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" @@ -7579,12 +7438,13 @@ __metadata: "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-kubernetes-common": "workspace:^" + "@backstage/plugin-kubernetes-node": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-node": "workspace:^" "@backstage/types": "workspace:^" "@google-cloud/container": ^4.0.0 "@jest-mock/express": ^2.0.1 - "@kubernetes/client-node": 0.18.1 + "@kubernetes/client-node": 0.19.0 "@types/aws4": ^1.5.1 "@types/express": ^4.17.6 "@types/http-proxy-middleware": ^0.19.3 @@ -7631,10 +7491,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/node": ^16.11.26 "@types/react": ^16.13.1 || ^17.0.0 @@ -7646,8 +7505,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7664,7 +7523,7 @@ __metadata: "@backstage/plugin-permission-common": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" - "@kubernetes/client-node": 0.18.1 + "@kubernetes/client-node": 0.19.0 kubernetes-models: ^4.3.1 lodash: ^4.17.21 luxon: ^3.0.0 @@ -7672,6 +7531,17 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-kubernetes-node@workspace:^, @backstage/plugin-kubernetes-node@workspace:plugins/kubernetes-node": + version: 0.0.0-use.local + resolution: "@backstage/plugin-kubernetes-node@workspace:plugins/kubernetes-node" + dependencies: + "@backstage/backend-plugin-api": "workspace:^" + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/plugin-kubernetes-common": "workspace:^" + languageName: unknown + linkType: soft + "@backstage/plugin-kubernetes-react@workspace:^, @backstage/plugin-kubernetes-react@workspace:plugins/kubernetes-react": version: 0.0.0-use.local resolution: "@backstage/plugin-kubernetes-react@workspace:plugins/kubernetes-react" @@ -7691,9 +7561,8 @@ __metadata: "@material-ui/core": ^4.9.13 "@material-ui/icons": ^4.11.3 "@material-ui/lab": ^4.0.0-alpha.61 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.1 + "@testing-library/jest-dom": ^6.0.0 + "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cronstrue: ^2.32.0 jest-websocket-mock: ^2.5.0 @@ -7707,7 +7576,7 @@ __metadata: xterm-addon-attach: ^0.9.0 xterm-addon-fit: ^0.8.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 languageName: unknown linkType: soft @@ -7731,14 +7600,13 @@ __metadata: "@backstage/types": "workspace:^" "@kubernetes-models/apimachinery": ^1.1.0 "@kubernetes-models/base": ^4.0.1 - "@kubernetes/client-node": 0.18.1 + "@kubernetes/client-node": 0.19.0 "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/react": ^16.13.1 || ^17.0.0 cronstrue: ^2.2.0 @@ -7750,11 +7618,11 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 xterm: ^5.2.1 - xterm-addon-attach: ^0.8.0 - xterm-addon-fit: ^0.7.0 + xterm-addon-attach: ^0.9.0 + xterm-addon-fit: ^0.8.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7804,17 +7672,16 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/react": ^16.13.1 || ^17.0.0 msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7880,9 +7747,9 @@ __metadata: "@material-ui/core": ^4.9.13 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 luxon: ^2.0.2 @@ -7890,8 +7757,8 @@ __metadata: react-use: ^17.2.4 slugify: ^1.6.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7912,9 +7779,9 @@ __metadata: "@material-ui/icons": ^4.9.1 "@microsoft/microsoft-graph-types": ^2.25.0 "@tanstack/react-query": ^4.1.3 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 classnames: ^2.3.1 @@ -7925,8 +7792,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7942,15 +7809,16 @@ __metadata: "@backstage/dev-utils": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" + "@backstage/test-utils": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/jest-dom": ^5.10.1 + "@testing-library/jest-dom": ^6.0.0 "@types/react": ^16.13.1 || ^17.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -7970,9 +7838,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/parse-link-header": ^2.0.1 "@types/react": ^16.13.1 || ^17.0.0 @@ -7981,8 +7849,8 @@ __metadata: parse-link-header: ^2.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8025,8 +7893,8 @@ __metadata: "@material-ui/core": ^4.9.13 "@material-ui/icons": ^4.9.1 "@material-ui/lab": ^4.0.0-alpha.60 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 cross-fetch: ^3.1.5 @@ -8034,8 +7902,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8056,16 +7924,16 @@ __metadata: "@material-ui/core": ^4.9.13 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8087,8 +7955,8 @@ __metadata: "@material-ui/lab": ^4.0.0-alpha.60 "@material-ui/pickers": ^3.3.10 "@material-ui/styles": ^4.11.5 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 axios: ^1.4.0 @@ -8099,7 +7967,7 @@ __metadata: react-use: ^17.2.4 recharts: ^2.5.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 || ^18.0.0 react-router-dom: "*" languageName: unknown linkType: soft @@ -8121,16 +7989,16 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8155,10 +8023,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.1 + "@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 lodash: ^4.17.21 @@ -8168,8 +8035,8 @@ __metadata: qs: ^6.10.1 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8192,9 +8059,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 classnames: ^2.2.6 @@ -8202,8 +8069,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8245,9 +8112,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/luxon": ^3.0.0 "@types/react": ^16.13.1 || ^17.0.0 @@ -8255,8 +8122,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8303,7 +8170,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-permission-common@^0.7.8, @backstage/plugin-permission-common@workspace:^, @backstage/plugin-permission-common@workspace:plugins/permission-common": +"@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: @@ -8341,25 +8208,6 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-permission-react@npm:^0.4.15": - version: 0.4.15 - resolution: "@backstage/plugin-permission-react@npm:0.4.15" - dependencies: - "@backstage/config": ^1.1.0 - "@backstage/core-plugin-api": ^1.6.0 - "@backstage/plugin-permission-common": ^0.7.8 - "@types/react": ^16.13.1 || ^17.0.0 - cross-fetch: ^3.1.5 - react-use: ^17.2.4 - swr: ^2.0.0 - 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: 5f11264a7d46bee0924b9a00133e756e38d3cce5ce842104546963e08b8bfc6445e28ac4b2b75878fd5407631353e964e5f0b399bc958a76aaa732741b80a52a - 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" @@ -8369,15 +8217,15 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/plugin-permission-common": "workspace:^" "@backstage/test-utils": "workspace:^" - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@testing-library/jest-dom": ^6.0.0 + "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 react-use: ^17.2.4 swr: ^2.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8438,16 +8286,16 @@ __metadata: "@backstage/plugin-permission-common": "workspace:^" "@backstage/plugin-permission-react": "workspace:^" "@backstage/plugin-playlist-common": "workspace:^" + "@backstage/plugin-search-common": "workspace:^" "@backstage/plugin-search-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/react": ^16.13.1 || ^17.0.0 lodash: ^4.17.21 @@ -8458,8 +8306,8 @@ __metadata: react-use: ^17.2.4 swr: ^2.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8510,15 +8358,15 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": ^4.0.0-alpha.57 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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.1 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8564,10 +8412,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 @@ -8576,8 +8423,8 @@ __metadata: react-sparklines: ^1.7.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8723,7 +8570,6 @@ __metadata: "@types/git-url-parse": ^9.0.0 "@types/libsodium-wrappers": ^0.7.10 "@types/luxon": ^3.0.0 - "@types/mock-fs": ^4.13.0 "@types/nunjucks": ^3.1.4 "@types/supertest": ^2.0.8 "@types/zen-observable": ^0.8.0 @@ -8746,7 +8592,6 @@ __metadata: libsodium-wrappers: ^0.7.11 lodash: ^4.17.21 luxon: ^3.0.0 - mock-fs: ^5.2.0 morgan: ^1.10.0 msw: ^1.0.0 node-fetch: ^2.6.7 @@ -8821,16 +8666,13 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@react-hookz/web": ^20.0.0 - "@rjsf/core": ^3.2.1 - "@rjsf/core-v5": "npm:@rjsf/core@5.13.0" - "@rjsf/material-ui": ^3.2.1 - "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@5.13.0" + "@rjsf/core": 5.13.0 + "@rjsf/material-ui": 5.13.0 "@rjsf/utils": 5.13.0 "@rjsf/validator-ajv8": 5.13.0 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/humanize-duration": ^3.18.1 "@types/json-schema": ^7.0.9 @@ -8850,8 +8692,8 @@ __metadata: zod: ^3.21.4 zod-to-json-schema: ^3.20.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -8887,14 +8729,13 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@react-hookz/web": ^20.0.0 - "@rjsf/core": ^3.2.1 - "@rjsf/material-ui": ^3.2.1 + "@rjsf/core": 5.13.0 + "@rjsf/material-ui": 5.13.0 "@rjsf/utils": 5.13.0 "@rjsf/validator-ajv8": 5.13.0 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/humanize-duration": ^3.18.1 "@types/json-schema": ^7.0.9 @@ -8918,8 +8759,8 @@ __metadata: zod: ^3.21.4 zod-to-json-schema: ^3.20.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9113,18 +8954,17 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/react": ^16.13.1 || ^17.0.0 lodash: ^4.17.21 qs: ^6.9.4 react-use: ^17.3.2 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9152,10 +8992,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/react": ^16.13.1 || ^17.0.0 history: ^5.0.0 @@ -9163,8 +9002,8 @@ __metadata: qs: ^6.9.4 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9187,9 +9026,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/luxon": ^3.0.0 "@types/react": ^16.13.1 || ^17.0.0 @@ -9199,8 +9038,8 @@ __metadata: react-sparklines: ^1.7.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9220,9 +9059,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 "@types/zen-observable": ^0.8.2 @@ -9232,8 +9071,8 @@ __metadata: uuid: ^8.3.2 zen-observable: ^0.10.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9269,8 +9108,8 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@types/react": ^16.13.1 || ^17.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9293,9 +9132,9 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@material-ui/styles": ^4.10.0 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 cross-fetch: ^3.1.5 @@ -9304,8 +9143,8 @@ __metadata: rc-progress: 3.5.1 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9326,9 +9165,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/luxon": ^3.0.0 "@types/react": ^16.13.1 || ^17.0.0 @@ -9337,8 +9176,8 @@ __metadata: msw: ^1.0.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9377,9 +9216,9 @@ __metadata: "@backstage/theme": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 cross-fetch: ^3.1.5 @@ -9388,8 +9227,8 @@ __metadata: qs: ^6.9.4 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9408,16 +9247,16 @@ __metadata: "@backstage/theme": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9519,17 +9358,17 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 qs: ^6.9.4 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9549,9 +9388,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/color": ^3.0.1 "@types/d3-force": ^3.0.0 @@ -9560,11 +9399,10 @@ __metadata: cross-fetch: ^3.1.5 d3-force: ^3.0.0 msw: ^1.0.0 - prop-types: ^15.7.2 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9588,17 +9426,17 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9657,9 +9495,9 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@react-hookz/web": ^20.0.0 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 git-url-parse: ^13.0.0 @@ -9667,8 +9505,8 @@ __metadata: photoswipe: ^5.3.7 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9731,17 +9569,16 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/lab": 4.0.0-alpha.61 "@material-ui/styles": ^4.11.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/jest-dom": ^6.0.0 + "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 jss: ~10.10.0 lodash: ^4.17.21 react-helmet: 6.1.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9772,10 +9609,9 @@ __metadata: "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 "@material-ui/styles": ^4.10.0 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.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/dompurify": ^2.2.2 "@types/event-source-polyfill": ^1.0.0 @@ -9791,8 +9627,8 @@ __metadata: react-helmet: 6.1.0 react-use: ^17.2.4 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9840,16 +9676,16 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9863,6 +9699,7 @@ __metadata: "@backstage/backend-test-utils": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" "@backstage/errors": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" "@backstage/types": "workspace:^" @@ -9887,6 +9724,7 @@ __metadata: "@backstage/core-plugin-api": "workspace:^" "@backstage/dev-utils": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" "@backstage/plugin-catalog": "workspace:^" "@backstage/plugin-catalog-react": "workspace:^" "@backstage/test-utils": "workspace:^" @@ -9895,9 +9733,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 cross-fetch: ^3.1.5 @@ -9905,8 +9743,8 @@ __metadata: react-use: ^17.2.4 zen-observable: ^0.10.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9955,16 +9793,16 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -9984,9 +9822,9 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/luxon": ^3.0.0 "@types/react": ^16.13.1 || ^17.0.0 @@ -9996,8 +9834,8 @@ __metadata: react-use: ^17.2.4 recharts: ^2.5.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -10079,7 +9917,7 @@ __metadata: "@backstage/types": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 - "@testing-library/jest-dom": ^5.10.1 + "@testing-library/jest-dom": ^6.0.0 "@types/react": ^16.13.1 || ^17.0.0 cross-fetch: ^3.1.5 i18next: ^22.4.15 @@ -10105,8 +9943,8 @@ __metadata: peerDependencies: "@material-ui/core": ^4.12.2 "@types/react": ^16.13.1 || ^17.0.0 - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 @@ -10122,7 +9960,7 @@ __metadata: languageName: node linkType: hard -"@backstage/types@^1.0.2, @backstage/types@^1.1.1, @backstage/types@workspace:^, @backstage/types@workspace:packages/types": +"@backstage/types@^1.0.2, @backstage/types@workspace:^, @backstage/types@workspace:packages/types": version: 0.0.0-use.local resolution: "@backstage/types@workspace:packages/types" dependencies: @@ -10133,18 +9971,17 @@ __metadata: languageName: unknown linkType: soft -"@backstage/version-bridge@^1.0.3, @backstage/version-bridge@^1.0.5, @backstage/version-bridge@workspace:^, @backstage/version-bridge@workspace:packages/version-bridge": +"@backstage/version-bridge@^1.0.3, @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: "@backstage/cli": "workspace:^" - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 - "@testing-library/react-hooks": ^8.0.0 + "@testing-library/jest-dom": ^6.0.0 + "@testing-library/react": ^14.0.0 "@types/react": ^16.13.1 || ^17.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -10500,13 +10337,13 @@ __metadata: linkType: hard "@codemirror/view@npm:^6.0.0": - version: 6.21.2 - resolution: "@codemirror/view@npm:6.21.2" + version: 6.21.3 + resolution: "@codemirror/view@npm:6.21.3" dependencies: "@codemirror/state": ^6.1.4 style-mod: ^4.1.0 w3c-keyname: ^2.2.4 - checksum: d972a32f26882a1811ffab833f8705339cd4c1bfe56765ed6ecbc1d84466b71a728adb8f4b4fc566ca3bccee5aacd2585e79cb96a851dcd48777e2320dab1892 + checksum: 7fda5a60e04fe1ac3d22ee478d4a90fc307953b8c900752ef5ca33af06c4e7851356e460f14b05034230b3a1677f36379ea01d85a3ea3b3a3e85e871ed62346a languageName: node linkType: hard @@ -10517,6 +10354,13 @@ __metadata: languageName: node linkType: hard +"@colors/colors@npm:^1.6.0": + version: 1.6.0 + resolution: "@colors/colors@npm:1.6.0" + checksum: aa209963e0c3218e80a4a20553ba8c0fbb6fa13140540b4e5f97923790be06801fc90172c1114fc8b7e888b3d012b67298cde6b9e81521361becfaee400c662f + languageName: node + linkType: hard + "@cspotcode/source-map-support@npm:^0.8.0": version: 0.8.1 resolution: "@cspotcode/source-map-support@npm:0.8.1" @@ -10785,23 +10629,23 @@ __metadata: languageName: node linkType: hard -"@esbuild-kit/core-utils@npm:^3.0.0": - version: 3.0.0 - resolution: "@esbuild-kit/core-utils@npm:3.0.0" +"@esbuild-kit/core-utils@npm:^3.0.0, @esbuild-kit/core-utils@npm:^3.3.2": + version: 3.3.2 + resolution: "@esbuild-kit/core-utils@npm:3.3.2" dependencies: - esbuild: ~0.15.10 + esbuild: ~0.18.20 source-map-support: ^0.5.21 - checksum: 0e89ec718e2211bf95c48a8085aaef88e8e416f42abd1c62d488d5458eecd3fbc144179a0c5570ad36fa7e2d3bbc411f8d3fb28802c37ced2154dc2c6ded9dfe + checksum: 62f3b97457fa4ef39d752bd2ad1c8adac08929b50c411f5259f105cc74896f1fdb3429a540aa423e8eae37f32ef44656ca21ccb9a723cd9955d65a820960ab1f languageName: node linkType: hard "@esbuild-kit/esm-loader@npm:^2.5.5": - version: 2.5.5 - resolution: "@esbuild-kit/esm-loader@npm:2.5.5" + version: 2.6.5 + resolution: "@esbuild-kit/esm-loader@npm:2.6.5" dependencies: - "@esbuild-kit/core-utils": ^3.0.0 - get-tsconfig: ^4.4.0 - checksum: 9d4a03ffc937fbec75a8456c3d45d7cdb1a65768416791a5720081753502bc9f485ba27942a46f564b12483b140a8a46c12433a4496430d93e4513e430484ec7 + "@esbuild-kit/core-utils": ^3.3.2 + get-tsconfig: ^4.7.0 + checksum: 88a27203898f14bd69f03244ae2b3bae727e00243d7801292c4da8caba69813b0978fb8245a55b83bc9b907f475ed634f094a1f44cc590c0754993f4a924cc22 languageName: node linkType: hard @@ -10812,6 +10656,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/android-arm64@npm:0.18.20" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/android-arm64@npm:0.19.4" @@ -10819,16 +10670,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.15.18": - version: 0.15.18 - resolution: "@esbuild/android-arm@npm:0.15.18" +"@esbuild/android-arm@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/android-arm@npm:0.16.17" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-arm@npm:0.16.17": - version: 0.16.17 - resolution: "@esbuild/android-arm@npm:0.16.17" +"@esbuild/android-arm@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/android-arm@npm:0.18.20" conditions: os=android & cpu=arm languageName: node linkType: hard @@ -10847,6 +10698,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/android-x64@npm:0.18.20" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/android-x64@npm:0.19.4" @@ -10861,6 +10719,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/darwin-arm64@npm:0.18.20" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/darwin-arm64@npm:0.19.4" @@ -10875,6 +10740,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/darwin-x64@npm:0.18.20" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/darwin-x64@npm:0.19.4" @@ -10889,6 +10761,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/freebsd-arm64@npm:0.18.20" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/freebsd-arm64@npm:0.19.4" @@ -10903,6 +10782,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/freebsd-x64@npm:0.18.20" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/freebsd-x64@npm:0.19.4" @@ -10917,6 +10803,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-arm64@npm:0.18.20" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/linux-arm64@npm:0.19.4" @@ -10931,6 +10824,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-arm@npm:0.18.20" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/linux-arm@npm:0.19.4" @@ -10945,6 +10845,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-ia32@npm:0.18.20" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/linux-ia32@npm:0.19.4" @@ -10952,16 +10859,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.15.18": - version: 0.15.18 - resolution: "@esbuild/linux-loong64@npm:0.15.18" +"@esbuild/linux-loong64@npm:0.16.17": + version: 0.16.17 + resolution: "@esbuild/linux-loong64@npm:0.16.17" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.16.17": - version: 0.16.17 - resolution: "@esbuild/linux-loong64@npm:0.16.17" +"@esbuild/linux-loong64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-loong64@npm:0.18.20" conditions: os=linux & cpu=loong64 languageName: node linkType: hard @@ -10980,6 +10887,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-mips64el@npm:0.18.20" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/linux-mips64el@npm:0.19.4" @@ -10994,6 +10908,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-ppc64@npm:0.18.20" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/linux-ppc64@npm:0.19.4" @@ -11008,6 +10929,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-riscv64@npm:0.18.20" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/linux-riscv64@npm:0.19.4" @@ -11022,6 +10950,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-s390x@npm:0.18.20" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/linux-s390x@npm:0.19.4" @@ -11036,6 +10971,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/linux-x64@npm:0.18.20" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/linux-x64@npm:0.19.4" @@ -11050,6 +10992,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/netbsd-x64@npm:0.18.20" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/netbsd-x64@npm:0.19.4" @@ -11064,6 +11013,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/openbsd-x64@npm:0.18.20" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/openbsd-x64@npm:0.19.4" @@ -11078,6 +11034,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/sunos-x64@npm:0.18.20" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/sunos-x64@npm:0.19.4" @@ -11092,6 +11055,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/win32-arm64@npm:0.18.20" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/win32-arm64@npm:0.19.4" @@ -11106,6 +11076,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/win32-ia32@npm:0.18.20" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/win32-ia32@npm:0.19.4" @@ -11120,6 +11097,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.18.20": + version: 0.18.20 + resolution: "@esbuild/win32-x64@npm:0.18.20" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.19.4": version: 0.19.4 resolution: "@esbuild/win32-x64@npm:0.19.4" @@ -11127,7 +11111,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.2.0": +"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" dependencies: @@ -11138,10 +11122,10 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.6.1": - version: 4.6.2 - resolution: "@eslint-community/regexpp@npm:4.6.2" - checksum: a3c341377b46b54fa228f455771b901d1a2717f95d47dcdf40199df30abc000ba020f747f114f08560d119e979d882a94cf46cfc51744544d54b00319c0f2724 +"@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": + version: 4.8.1 + resolution: "@eslint-community/regexpp@npm:4.8.1" + checksum: 82d62c845ef42b810f268cfdc84d803a2da01735fb52e902fd34bdc09f92464a094fd8e4802839874b000b2f73f67c972859e813ba705233515d3e954f234bf2 languageName: node linkType: hard @@ -11162,10 +11146,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.50.0": - version: 8.50.0 - resolution: "@eslint/js@npm:8.50.0" - checksum: 302478f2acaaa7228729ec6a04f56641590185e1d8cd1c836a6db8a6b8009f80a57349341be9fbb9aa1721a7a569d1be3ffc598a33300d22816f11832095386c +"@eslint/js@npm:8.51.0": + version: 8.51.0 + resolution: "@eslint/js@npm:8.51.0" + checksum: 0228bf1e1e0414843e56d9ff362a2a72d579c078f93174666f29315690e9e30a8633ad72c923297f7fd7182381b5a476805ff04dac8debe638953eb1ded3ac73 languageName: node linkType: hard @@ -11219,6 +11203,13 @@ __metadata: languageName: node linkType: hard +"@fastify/busboy@npm:^2.0.0": + version: 2.0.0 + resolution: "@fastify/busboy@npm:2.0.0" + checksum: 41879937ce1dee6421ef9cd4da53239830617e1f0bb7a0e843940772cd72827205d05e518af6adabe6e1ea19301285fff432b9d11bad01a531e698bea95c781b + languageName: node + linkType: hard + "@floating-ui/core@npm:^1.4.2": version: 1.5.0 resolution: "@floating-ui/core@npm:1.5.0" @@ -12307,16 +12298,16 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.61 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -12782,11 +12773,11 @@ __metadata: linkType: hard "@keyv/redis@npm:^2.5.3": - version: 2.7.1 - resolution: "@keyv/redis@npm:2.7.1" + version: 2.8.0 + resolution: "@keyv/redis@npm:2.8.0" dependencies: ioredis: ^5.3.2 - checksum: 917547d9f6a3af2d0c355c9c78cac9392a8f3d7f2cc379d42ae158189da346cf0c831708cbb530496fda91dfeb4be2bad207ce154ef2205c2b8ce48b2e43a0fc + checksum: 753e18897bf8e1fed585357d85749c7a1689f5efc1eb7114e790bf760460f7f510d5e76da5cc742269949205c18aad3c58ce4f8ceef5db0ace4ee108833632ba languageName: node linkType: hard @@ -12824,35 +12815,7 @@ __metadata: languageName: node linkType: hard -"@kubernetes/client-node@npm:0.18.1": - version: 0.18.1 - resolution: "@kubernetes/client-node@npm:0.18.1" - dependencies: - "@types/js-yaml": ^4.0.1 - "@types/node": ^18.11.17 - "@types/request": ^2.47.1 - "@types/ws": ^8.5.3 - byline: ^5.0.0 - isomorphic-ws: ^5.0.0 - js-yaml: ^4.1.0 - jsonpath-plus: ^7.2.0 - openid-client: ^5.3.0 - request: ^2.88.0 - rfc4648: ^1.3.0 - stream-buffers: ^3.0.2 - tar: ^6.1.11 - tmp-promise: ^3.0.2 - tslib: ^2.4.1 - underscore: ^1.13.6 - ws: ^8.11.0 - dependenciesMeta: - openid-client: - optional: true - checksum: 7205f10256f182a0292d483195fab7f4d9b500b3a47e6861dcf2fa8851c0bfd554e4f9a9f832ff76500efefb0422df2ecf2e378c5c3a4290e86abd8bc69ef11d - languageName: node - linkType: hard - -"@kubernetes/client-node@npm:^0.19.0": +"@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" dependencies: @@ -13131,7 +13094,7 @@ __metadata: languageName: node linkType: hard -"@material-ui/pickers@npm:^3.2.10, @material-ui/pickers@npm:^3.3.10": +"@material-ui/pickers@npm:3.3.11": version: 3.3.11 resolution: "@material-ui/pickers@npm:3.3.11" dependencies: @@ -13151,6 +13114,26 @@ __metadata: languageName: node linkType: hard +"@material-ui/pickers@patch:@material-ui/pickers@npm%3A3.3.11#./.yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch::locator=root%40workspace%3A.": + version: 3.3.11 + resolution: "@material-ui/pickers@patch:@material-ui/pickers@npm%3A3.3.11#./.yarn/patches/@material-ui-pickers-npm-3.3.11-1c8f68ea20.patch::version=3.3.11&hash=c18f79&locator=root%40workspace%3A." + dependencies: + "@babel/runtime": ^7.6.0 + "@date-io/core": 1.x + "@types/styled-jsx": ^2.2.8 + clsx: ^1.0.2 + react-transition-group: ^4.0.0 + rifm: ^0.7.0 + peerDependencies: + "@date-io/core": ^1.3.6 + "@material-ui/core": ^4.0.0 + prop-types: ^15.6.0 + react: ^16.8.0 || ^17.0.0 + react-dom: ^16.8.0 || ^17.0.0 + checksum: e736e4d53f1b660f4a338e8ca3537dc86638ed41ed988f42baebb18d35d5eab19e4b35952217a46032128639a9af59b354f78dbccc02d90971b844bc5a8cdcf0 + languageName: node + linkType: hard + "@material-ui/styles@npm:^4.10.0, @material-ui/styles@npm:^4.11.0, @material-ui/styles@npm:^4.11.4, @material-ui/styles@npm:^4.11.5, @material-ui/styles@npm:^4.9.6": version: 4.11.5 resolution: "@material-ui/styles@npm:4.11.5" @@ -13379,14 +13362,14 @@ __metadata: languageName: node linkType: hard -"@mui/base@npm:5.0.0-beta.18": - version: 5.0.0-beta.18 - resolution: "@mui/base@npm:5.0.0-beta.18" +"@mui/base@npm:5.0.0-beta.19": + version: 5.0.0-beta.19 + resolution: "@mui/base@npm:5.0.0-beta.19" dependencies: "@babel/runtime": ^7.23.1 "@floating-ui/react-dom": ^2.0.2 - "@mui/types": ^7.2.5 - "@mui/utils": ^5.14.12 + "@mui/types": ^7.2.6 + "@mui/utils": ^5.14.13 "@popperjs/core": ^2.11.8 clsx: ^2.0.0 prop-types: ^15.8.1 @@ -13397,28 +13380,28 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 7d4ca1e9d537b7b5850567f1adecd1caa47b8613b43a587cf2f399cfda0a8c17dfda06b030c0bea554b76abe7ac25bb9b1af3c996574def5f860cda0c6ea4a3c + checksum: 7503d5609ba242e270cbcaea69f6c7d4935763a34a8ce8de2695078eae12ffcc1d7a57b5d735200de08f2314b2482aa7279631ffd92af240af24f6c31b633d8f languageName: node linkType: hard -"@mui/core-downloads-tracker@npm:^5.14.12": - version: 5.14.12 - resolution: "@mui/core-downloads-tracker@npm:5.14.12" - checksum: 1c1576ceecf7cade9e0d7a531632f5f9db24853d9ebbd47bb9ed943a3af7de734ad4f3374bab79880e9591db3ea55ea84cc10df72177f9ca5e32cc7662e04405 +"@mui/core-downloads-tracker@npm:^5.14.13": + version: 5.14.13 + resolution: "@mui/core-downloads-tracker@npm:5.14.13" + checksum: 3094f8c289d53eb2189ce3f9e4c71e735f91cfefeadda4cf37b0f3c3de47d9261fdbd49485f74267e2fe93d8c0cb289d38e9c802a404489017e9f1cee9e56488 languageName: node linkType: hard "@mui/material@npm:^5.12.2": - version: 5.14.12 - resolution: "@mui/material@npm:5.14.12" + version: 5.14.13 + resolution: "@mui/material@npm:5.14.13" dependencies: "@babel/runtime": ^7.23.1 - "@mui/base": 5.0.0-beta.18 - "@mui/core-downloads-tracker": ^5.14.12 - "@mui/system": ^5.14.12 - "@mui/types": ^7.2.5 - "@mui/utils": ^5.14.12 - "@types/react-transition-group": ^4.4.6 + "@mui/base": 5.0.0-beta.19 + "@mui/core-downloads-tracker": ^5.14.13 + "@mui/system": ^5.14.13 + "@mui/types": ^7.2.6 + "@mui/utils": ^5.14.13 + "@types/react-transition-group": ^4.4.7 clsx: ^2.0.0 csstype: ^3.1.2 prop-types: ^15.8.1 @@ -13437,16 +13420,16 @@ __metadata: optional: true "@types/react": optional: true - checksum: a0d3b52ce3cc282da04036db0805f95f27b35a9c899f132f962fe96f05d3eb112e99ccbf6bd9d05cae617b24beda95470aedaff129d6e39d1b52e1ddf80a9e12 + checksum: 07d73cb5f770743e080494684fd087770893232415c681a25bff2e791414b702d76d02100996a850e89ced81f986c1dc378cc6fb35fcd0724d19b3b0a4a34bed languageName: node linkType: hard -"@mui/private-theming@npm:^5.14.12": - version: 5.14.12 - resolution: "@mui/private-theming@npm:5.14.12" +"@mui/private-theming@npm:^5.14.13": + version: 5.14.13 + resolution: "@mui/private-theming@npm:5.14.13" dependencies: "@babel/runtime": ^7.23.1 - "@mui/utils": ^5.14.12 + "@mui/utils": ^5.14.13 prop-types: ^15.8.1 peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 @@ -13454,13 +13437,13 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: f8127347dc29126fece3b530cb156f6ababf747b64bb1c712874375e6efae6c738c014304d9553001d67a59b24ca6a665f2d03bb5ae137f03bdba90815f0ecc1 + checksum: fb2f3644c332a454897f83b98b6fda7344ce30f9382715194442b7d954fdff4e0b96ef017a631259b2f0e44706737eecda7c5306d4833bf5bd834d59b059a6f9 languageName: node linkType: hard -"@mui/styled-engine@npm:^5.14.12": - version: 5.14.12 - resolution: "@mui/styled-engine@npm:5.14.12" +"@mui/styled-engine@npm:^5.14.13": + version: 5.14.13 + resolution: "@mui/styled-engine@npm:5.14.13" dependencies: "@babel/runtime": ^7.23.1 "@emotion/cache": ^11.11.0 @@ -13475,19 +13458,19 @@ __metadata: optional: true "@emotion/styled": optional: true - checksum: c689ccad59e7fd54cd8367838612daa4f132c64d8c6b99ccb7c8f9697b5c940a6bf7edcccd686ce437b565dbcf3bfc12bb0dea47cbd5fbd750ea1553017f9c0d + checksum: b927fffbfb3a2c8d09f10b3770da610c94826312c2aa3e17791bd0355ef64056a842ede32f9d22225b952e3055aa2364c06f17620ae5203a0d4bb782ec90388f languageName: node linkType: hard -"@mui/system@npm:^5.14.12": - version: 5.14.12 - resolution: "@mui/system@npm:5.14.12" +"@mui/system@npm:^5.14.13": + version: 5.14.13 + resolution: "@mui/system@npm:5.14.13" dependencies: "@babel/runtime": ^7.23.1 - "@mui/private-theming": ^5.14.12 - "@mui/styled-engine": ^5.14.12 - "@mui/types": ^7.2.5 - "@mui/utils": ^5.14.12 + "@mui/private-theming": ^5.14.13 + "@mui/styled-engine": ^5.14.13 + "@mui/types": ^7.2.6 + "@mui/utils": ^5.14.13 clsx: ^2.0.0 csstype: ^3.1.2 prop-types: ^15.8.1 @@ -13503,25 +13486,25 @@ __metadata: optional: true "@types/react": optional: true - checksum: 70c3920eadc593395a2d258ddea0f3b28689c7f02fdaf97fc205e16efaeebe462b2ab01c69a20a3bcb011e0d07ea47fa66a433e70d0a1ce15d7b694fb3c52135 + checksum: 1dfcd19737792d36e87b83623f1bf836f1e1282faf44646f9788cec9e5fb6502e6082872ab839dcebd0ae3d72c5771aa12bad9d3ee4b7e039582970acda13a8d languageName: node linkType: hard -"@mui/types@npm:^7.2.5": - version: 7.2.5 - resolution: "@mui/types@npm:7.2.5" +"@mui/types@npm:^7.2.6": + version: 7.2.6 + resolution: "@mui/types@npm:7.2.6" peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: 2807e9a8eb251294eee6384a4d68b2159f7660466625f1781e9efea282aa7c6ff35b42bc7039c2d43e7a5ac80291dcb85c4110022b0b6de4e12b6406b62f3dc1 + checksum: eb92f9c2fa5df048bcf182a611131bee2799ce1de64acfca12855f349d0b69f5f92c953b7e6c4e341e1df48f0e86f1329ed0251be4835ed194f53342827bd576 languageName: node linkType: hard -"@mui/utils@npm:^5.14.12": - version: 5.14.12 - resolution: "@mui/utils@npm:5.14.12" +"@mui/utils@npm:^5.14.13": + version: 5.14.13 + resolution: "@mui/utils@npm:5.14.13" dependencies: "@babel/runtime": ^7.23.1 "@types/prop-types": ^15.7.7 @@ -13533,7 +13516,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 41470b6292b7a46c71fb0a0acc6a5f05a5e080648106b8805555de920e8f748669c7e8d39cbbcf0f52be9053927bb8439a748e24bd02bc1a220c9bded4435f42 + checksum: 5f04382d7761d35c5f53bcc0ce91c29aba0b3c0afb731f01d2ff078b05afe8098dee412538d846ab3a4b00eec934d46d730f9ef2ef493c3db885e2672480b6f0 languageName: node linkType: hard @@ -14324,65 +14307,65 @@ __metadata: linkType: hard "@opentelemetry/api@npm:^1.0.1, @opentelemetry/api@npm:^1.3.0, @opentelemetry/api@npm:^1.4.1": - version: 1.4.1 - resolution: "@opentelemetry/api@npm:1.4.1" - checksum: e783c40d1a518abf9c4c5d65223237c1392cd9a6c53ac6e2c3ef0c05ff7266e3dfc4fd9874316dae0dcb7a97950878deb513bcbadfaad653d48f0215f2a0911b + version: 1.6.0 + resolution: "@opentelemetry/api@npm:1.6.0" + checksum: 3283b78b62a39f6568eaa050ac7045fcca747679e255874f6d2107cb8e1a3b2e10bfbf553c3e82a72500fb5fdca49dc07a5fe27fd6980debac24506cca638859 languageName: node linkType: hard -"@opentelemetry/core@npm:1.13.0": - version: 1.13.0 - resolution: "@opentelemetry/core@npm:1.13.0" +"@opentelemetry/core@npm:1.17.1": + version: 1.17.1 + resolution: "@opentelemetry/core@npm:1.17.1" dependencies: - "@opentelemetry/semantic-conventions": 1.13.0 + "@opentelemetry/semantic-conventions": 1.17.1 peerDependencies: - "@opentelemetry/api": ">=1.0.0 <1.5.0" - checksum: a69916bcb710f1241e98a58ac5f5dfbc3372fdcd6cb2a4b2d33cdeb941765ecbdeea029f60f650a5743a56f583b0f06b672566467b89db84a24f1304bf2e5205 + "@opentelemetry/api": ">=1.0.0 <1.7.0" + checksum: 06157f4a51dd1b3c98487c0d29a927a5a0fbbc997a81b04ccc4923968424582f517969b91c4f4f19dc1718f27a97f43b0b07af1310a5c240a96c5ff14c4b5cec languageName: node linkType: hard -"@opentelemetry/exporter-prometheus@npm:^0.39.1": - version: 0.39.1 - resolution: "@opentelemetry/exporter-prometheus@npm:0.39.1" +"@opentelemetry/exporter-prometheus@npm:^0.44.0": + version: 0.44.0 + resolution: "@opentelemetry/exporter-prometheus@npm:0.44.0" dependencies: - "@opentelemetry/core": 1.13.0 - "@opentelemetry/resources": 1.13.0 - "@opentelemetry/sdk-metrics": 1.13.0 + "@opentelemetry/core": 1.17.1 + "@opentelemetry/resources": 1.17.1 + "@opentelemetry/sdk-metrics": 1.17.1 peerDependencies: "@opentelemetry/api": ^1.3.0 - checksum: 97697926ef26e3dca9654b6ea8d2ab8e7fc7fc33ce617d25a6eb70c0ef2e2fe47192fcede15cbe45179d0ade67e55769bbed11c691d34f9e59ebd50aab22add7 + checksum: f0c093ba8b70c23f16fb08e7f2ca59986dff853ae006fd42864b952e4dc9ceac97fcb423586288828f1a35271589a6676eed46f2017369d59e8ed3315e6ac79d languageName: node linkType: hard -"@opentelemetry/resources@npm:1.13.0": - version: 1.13.0 - resolution: "@opentelemetry/resources@npm:1.13.0" +"@opentelemetry/resources@npm:1.17.1": + version: 1.17.1 + resolution: "@opentelemetry/resources@npm:1.17.1" dependencies: - "@opentelemetry/core": 1.13.0 - "@opentelemetry/semantic-conventions": 1.13.0 + "@opentelemetry/core": 1.17.1 + "@opentelemetry/semantic-conventions": 1.17.1 peerDependencies: - "@opentelemetry/api": ">=1.0.0 <1.5.0" - checksum: ef0a11596f27b5e1c13b74357da06c5c2725a1056df0a583562dbcc739927ad85bb8bdec4e01f4b43f348b448c0146c033b135840a7d388b75cc751a33a6364e + "@opentelemetry/api": ">=1.0.0 <1.7.0" + checksum: ea4ec5568f5b67626be6eb2b975614d140dab4f6eb7ca73ee30d0f1957ef9779953956d1d44c35bb124c75e311b34a05e2036b32fcf31cf50ae983154df9ee3d languageName: node linkType: hard -"@opentelemetry/sdk-metrics@npm:1.13.0, @opentelemetry/sdk-metrics@npm:^1.13.0": - version: 1.13.0 - resolution: "@opentelemetry/sdk-metrics@npm:1.13.0" +"@opentelemetry/sdk-metrics@npm:1.17.1, @opentelemetry/sdk-metrics@npm:^1.13.0": + version: 1.17.1 + resolution: "@opentelemetry/sdk-metrics@npm:1.17.1" dependencies: - "@opentelemetry/core": 1.13.0 - "@opentelemetry/resources": 1.13.0 - lodash.merge: 4.6.2 + "@opentelemetry/core": 1.17.1 + "@opentelemetry/resources": 1.17.1 + lodash.merge: ^4.6.2 peerDependencies: - "@opentelemetry/api": ">=1.3.0 <1.5.0" - checksum: 2f87444b6c789acdde3465383b4255b072e201cf9bed642e82970540bfe913d76d4c4ebf8cc1ff3da383d3235dd8399cd6407fac86085a9ac9ff5b5b3afc9f38 + "@opentelemetry/api": ">=1.3.0 <1.7.0" + checksum: 6f6a59c5f594ebfc75da7ba203cb35a9271f4536ed4c2499c83f5953b3a2486d306d7aa17f0d7c2fde0efb8cbe9ac4346988adab0e039d082ec95d8d32703509 languageName: node linkType: hard -"@opentelemetry/semantic-conventions@npm:1.13.0": - version: 1.13.0 - resolution: "@opentelemetry/semantic-conventions@npm:1.13.0" - checksum: 9cccf1d73315fed3920bb2201c0e82f66e58dddfa475314b6613780c2804570d6f657be3894eb8b84a2a543c9b8cd520587f5d6cd4b62bc6731d7299b4c5ee69 +"@opentelemetry/semantic-conventions@npm:1.17.1": + version: 1.17.1 + resolution: "@opentelemetry/semantic-conventions@npm:1.17.1" + checksum: 16161f70526d2abcd37a39771229ffe01a25d569f76c86e97200dc20399e7fa87b231c557a9654629b4789e945350e4fc55f88df979a502911f1dde4643ad416 languageName: node linkType: hard @@ -14639,10 +14622,10 @@ __metadata: languageName: node linkType: hard -"@remix-run/router@npm:1.8.0": - version: 1.8.0 - resolution: "@remix-run/router@npm:1.8.0" - checksum: f754f02d3b4fc86791b88acf16065000609e2324b9436027844a76831c7107c0994067cb83abdd6093c282bd518a5c89b5e02aead585782978586e3a04534428 +"@remix-run/router@npm:1.9.0": + version: 1.9.0 + resolution: "@remix-run/router@npm:1.9.0" + checksum: 0537b0ff29879ac85077cb4c42eaca4a295b9efd71477848984c2f2dfa5741c9b83d3106a7bb72994a51a9adfeeab3b0f5a40f2dee8be3f0750feeeca2a6d513 languageName: node linkType: hard @@ -14653,7 +14636,7 @@ __metadata: languageName: node linkType: hard -"@rjsf/core-v5@npm:@rjsf/core@5.13.0": +"@rjsf/core@npm:5.13.0": version: 5.13.0 resolution: "@rjsf/core@npm:5.13.0" dependencies: @@ -14669,26 +14652,7 @@ __metadata: languageName: node linkType: hard -"@rjsf/core@npm:^3.2.1": - version: 3.2.1 - resolution: "@rjsf/core@npm:3.2.1" - dependencies: - "@types/json-schema": ^7.0.7 - ajv: ^6.7.0 - core-js-pure: ^3.6.5 - json-schema-merge-allof: ^0.6.0 - jsonpointer: ^5.0.0 - lodash: ^4.17.15 - nanoid: ^3.1.23 - prop-types: ^15.7.2 - react-is: ^16.9.0 - peerDependencies: - react: ">=16" - checksum: 2142d4a31229ea242b79aca4ed93e2fe89e75f15ce93111457c3017d3ab295cae8f53e4dd870c619afa571959d00f46b3c19085c6a336f522c891fc07ecc46f1 - languageName: node - linkType: hard - -"@rjsf/material-ui-v5@npm:@rjsf/material-ui@5.13.0": +"@rjsf/material-ui@npm:5.13.0": version: 5.13.0 resolution: "@rjsf/material-ui@npm:5.13.0" peerDependencies: @@ -14701,18 +14665,6 @@ __metadata: languageName: node linkType: hard -"@rjsf/material-ui@npm:^3.2.1": - version: 3.2.1 - resolution: "@rjsf/material-ui@npm:3.2.1" - peerDependencies: - "@material-ui/core": ^4.2.0 - "@material-ui/icons": ^4.2.1 - "@rjsf/core": ^3.0.0 - react: ">=16" - checksum: bd25cd9f2e2d568c653755e7268fe3e53279e1ae675e39bccd85f65557623d2052b706763e017a949f897751e25a16d0f2c8b995508bb56907be6786b09e2b1e - languageName: node - linkType: hard - "@rjsf/utils@npm:5.13.0": version: 5.13.0 resolution: "@rjsf/utils@npm:5.13.0" @@ -16141,341 +16093,364 @@ __metadata: languageName: node linkType: hard -"@swagger-api/apidom-ast@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-ast@npm:0.74.1" +"@swagger-api/apidom-ast@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-ast@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 + "@swagger-api/apidom-error": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 - ramda-adjunct: ^4.0.0 + ramda-adjunct: ^4.1.1 stampit: ^4.3.2 unraw: ^3.0.0 - checksum: 453880bafb11c9c53768629bf0c9c3cfdab76625dbd4eb34ec146c23eb782dace3c279ca4cff665ac20f3fae229ba96bff2bdbacba383630107f23522183f130 + checksum: ffd54c63103bb24763f6531f672d8b8112bcc6a6730b770621f2b95a0e25e72cdcf513608739006a6a937b82e59d16b9368e95f1dc7560388ccdb65178b9501d languageName: node linkType: hard -"@swagger-api/apidom-core@npm:>=0.74.1 <1.0.0, @swagger-api/apidom-core@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-core@npm:0.74.1" +"@swagger-api/apidom-core@npm:>=0.77.0 <1.0.0, @swagger-api/apidom-core@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-core@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-ast": ^0.74.1 + "@swagger-api/apidom-ast": ^0.77.0 + "@swagger-api/apidom-error": ^0.77.0 "@types/ramda": ~0.29.3 minim: ~0.23.8 ramda: ~0.29.0 - ramda-adjunct: ^4.0.0 - short-unique-id: ^4.4.4 + ramda-adjunct: ^4.1.1 + short-unique-id: ^5.0.2 stampit: ^4.3.2 - checksum: 8369c45198a2d955dd84a55564f89411394df388c2cf277208fbfcaf3014ae596f4de9916b55d918683b13fc18f0c54a0e190bf34206cf4c16c10a1a7e50ab07 + checksum: 06251765371bc89cedbd142979913c8b5006e6c434e21f9567816a0da7450ed4e7d0430db487cfad1f0244f63a1adaad48a7115148029a9bf034cca995eb0df4 languageName: node linkType: hard -"@swagger-api/apidom-json-pointer@npm:>=0.74.1 <1.0.0, @swagger-api/apidom-json-pointer@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-json-pointer@npm:0.74.1" +"@swagger-api/apidom-error@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-error@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 "@types/ramda": ~0.29.3 ramda: ~0.29.0 ramda-adjunct: ^4.0.0 - checksum: 2adbbb735cd559b975fa58d11b7d99844eb5eb48282842cb6048e61742229198519cfbcf90f48c38cfbbad089b9d71a258c9aeb92c3fbec8abe392756e4816f0 + checksum: 9a9424cdd659b024d7e5afbcf66808c15ff9455c21beda2f8f2442b798f4968c424e5bdc71f70a4284e7feed1ea1697d09823d65b91c752efc0a2767119e9674 languageName: node linkType: hard -"@swagger-api/apidom-ns-api-design-systems@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-ns-api-design-systems@npm:0.74.1" +"@swagger-api/apidom-json-pointer@npm:>=0.77.0 <1.0.0, @swagger-api/apidom-json-pointer@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-json-pointer@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-ns-openapi-3-1": ^0.74.1 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-error": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 ramda-adjunct: ^4.0.0 + checksum: 55f1b0d72eb96b9079f67a028d882841c94ab88a0ee67b826ab79d543763eae9428607dd47efb5524ce9bf80321620465f35d296282e1f3d0a6fd969c5269057 + languageName: node + linkType: hard + +"@swagger-api/apidom-ns-api-design-systems@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-ns-api-design-systems@npm:0.77.0" + dependencies: + "@babel/runtime-corejs3": ^7.20.7 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-error": ^0.77.0 + "@swagger-api/apidom-ns-openapi-3-1": ^0.77.0 + "@types/ramda": ~0.29.3 + ramda: ~0.29.0 + ramda-adjunct: ^4.1.1 stampit: ^4.3.2 - checksum: 83bb664015243a9fb342d81f1700f7dde12015a3c34c45ac0575fc79388eeec99dd97f6139207437b883b0e3c261916ebb931571c1c0e0240f84ea7fd57d8c93 + checksum: 93dd9b8c30592c8b98798aa7243d322fc4f287bd37ffb00b0a503f9c24759c96f9538212ca28972f684f9cb62ee7e6b8a4f76ac90e2b61616c4adb7b978a026a languageName: node linkType: hard -"@swagger-api/apidom-ns-asyncapi-2@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-ns-asyncapi-2@npm:0.74.1" +"@swagger-api/apidom-ns-asyncapi-2@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-ns-asyncapi-2@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-ns-json-schema-draft-7": ^0.74.1 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-ns-json-schema-draft-7": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 - ramda-adjunct: ^4.0.0 + ramda-adjunct: ^4.1.1 stampit: ^4.3.2 - checksum: 8577a17410f4bcc9d1a921f6e567c611b71316a6aba4bc3e06a11316b915d053a589693d44350ded7de67f8f6c58b4b0075cabee88a2603ce9790e54be2a1946 + checksum: 3675d90580baabcd4b866ca8a18f2eee865d2b5be0313fd7d6d8abfb4e342c5fdcc40b11abdff5547098f0bf44a85967f31fc1e8a266b3f3608628139981f808 languageName: node linkType: hard -"@swagger-api/apidom-ns-json-schema-draft-4@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-ns-json-schema-draft-4@npm:0.74.1" +"@swagger-api/apidom-ns-json-schema-draft-4@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-ns-json-schema-draft-4@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-ast": ^0.74.1 - "@swagger-api/apidom-core": ^0.74.1 + "@swagger-api/apidom-ast": ^0.77.0 + "@swagger-api/apidom-core": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 - ramda-adjunct: ^4.0.0 + ramda-adjunct: ^4.1.1 stampit: ^4.3.2 - checksum: 1d07a05dee36b1fdb238f57a22b620814fcaae21bbf46b83296048a1806a4be66901bc5aefbc42e4928d058a5df9203f9ad3fdf3f57476b6b61bb985f82bd99b + checksum: d8f2a94fab06d731f397a8a5eb950053a2af67509155f2379033ed59592f95dad2ab9a1d15e39bfd606cb2d11003230b7e34bb2f52a837640d8b9c20f1e96a0d languageName: node linkType: hard -"@swagger-api/apidom-ns-json-schema-draft-6@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-ns-json-schema-draft-6@npm:0.74.1" +"@swagger-api/apidom-ns-json-schema-draft-6@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-ns-json-schema-draft-6@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-ns-json-schema-draft-4": ^0.74.1 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-error": ^0.77.0 + "@swagger-api/apidom-ns-json-schema-draft-4": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 - ramda-adjunct: ^4.0.0 + ramda-adjunct: ^4.1.1 stampit: ^4.3.2 - checksum: d2460a3afaebfbb304aa610e4dd5dc5fdab4325dd9ce14d393b13bb7399e3b37f4bde837266ba9876c973b6dfc5eb179c27346c2941ad2fe77923b743b3a4ebc + checksum: e80387564631180bd132f76046cbf8f773d6e1a4cd8cef9210320d5b8d4bec047a7884428ec625f9cb002b8d455bfffb5de5369647be6e25ef16b669568611e7 languageName: node linkType: hard -"@swagger-api/apidom-ns-json-schema-draft-7@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-ns-json-schema-draft-7@npm:0.74.1" +"@swagger-api/apidom-ns-json-schema-draft-7@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-ns-json-schema-draft-7@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-ns-json-schema-draft-6": ^0.74.1 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-error": ^0.77.0 + "@swagger-api/apidom-ns-json-schema-draft-6": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 - ramda-adjunct: ^4.0.0 + ramda-adjunct: ^4.1.1 stampit: ^4.3.2 - checksum: cefc04786f2ce5640397e84141ab02e921d578ae5ebd9b3d06d8ad405f1ebc8589f2069f4c57cbdf5e8b911cb6a39fd248bfb7567a66968fe62542f6f64e52eb + checksum: c57146e2adfa810a2d7204a72fe952914fb9ae66bcdba27f495d216dc15ed8e81c7d7d77eb8b27cd1efadb662059fdb761de5e1ba9e0ca36ba32cdc2fe34c7b7 languageName: node linkType: hard -"@swagger-api/apidom-ns-openapi-3-0@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-ns-openapi-3-0@npm:0.74.1" +"@swagger-api/apidom-ns-openapi-3-0@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-ns-openapi-3-0@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-ns-json-schema-draft-4": ^0.74.1 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-ns-json-schema-draft-4": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 - ramda-adjunct: ^4.0.0 + ramda-adjunct: ^4.1.1 stampit: ^4.3.2 - checksum: 4c482714ce82287493d54cd454633bb044ca02659f3080084f34fc93f2f6f162cc5809499ced20a4db33092d30396d22fc80c63db080320306216a84077e26f5 + checksum: 54ab6155addc04c5c889768438b9e5fb084e084f2226034cafd71a1b22a66c90cd29d7731b24330a914cd5c049d0f2cfca92fc541eb3a3f297fdd9ca0b97036b languageName: node linkType: hard -"@swagger-api/apidom-ns-openapi-3-1@npm:>=0.74.1 <1.0.0, @swagger-api/apidom-ns-openapi-3-1@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-ns-openapi-3-1@npm:0.74.1" +"@swagger-api/apidom-ns-openapi-3-1@npm:>=0.77.0 <1.0.0, @swagger-api/apidom-ns-openapi-3-1@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-ns-openapi-3-1@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-ast": ^0.74.1 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-ns-openapi-3-0": ^0.74.1 + "@swagger-api/apidom-ast": ^0.77.0 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-ns-openapi-3-0": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 - ramda-adjunct: ^4.0.0 + ramda-adjunct: ^4.1.1 stampit: ^4.3.2 - checksum: 1de6568ad876481ab83cec6755854314511d45bfd67f5b65f2fc44238e4bd7269f688d1931b31d939fdddfa2b29ba3442e3fe778736a777462fc517a54b8c0d9 + checksum: cac2c97892f104ef130a75e3ff6e244b36e0f9706d9a8106ab7bfa8eb0d64a547970b7a54ab5cc67c90b28a9ddc7141d5819015ad1682a9ef116348bb14b3401 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-api-design-systems-json@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-parser-adapter-api-design-systems-json@npm:0.74.1" +"@swagger-api/apidom-parser-adapter-api-design-systems-json@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-parser-adapter-api-design-systems-json@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-ns-api-design-systems": ^0.74.1 - "@swagger-api/apidom-parser-adapter-json": ^0.74.1 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-ns-api-design-systems": ^0.77.0 + "@swagger-api/apidom-parser-adapter-json": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 ramda-adjunct: ^4.0.0 - checksum: 223720aac5979da9ccd931cebddfa6be944c5ba269ddddde4c5a9bec24627f0cc3655d83ea54b60bc093603c2d5fb169a451d356e5dafe49be66b150c6542a8b + checksum: 98278205fc50670f3b7bcade96326354f51e28071b2a9c33044d9b547c199d6386e2050fb27c0b939cf6feab0b3433b2f01f27b40d08e5e214221058a00243c9 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-api-design-systems-yaml@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-parser-adapter-api-design-systems-yaml@npm:0.74.1" +"@swagger-api/apidom-parser-adapter-api-design-systems-yaml@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-parser-adapter-api-design-systems-yaml@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-ns-api-design-systems": ^0.74.1 - "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.74.1 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-ns-api-design-systems": ^0.77.0 + "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 ramda-adjunct: ^4.0.0 - checksum: 0072ec50f650c8e8758e87deafffd86805bb858edcb83301739301a4e8f24e6a563311b65e261573c1858f1e7772cd3a6f9a78102ade9da225f9079ebbe5fdb5 + checksum: 996b6f77458d3f9ca4bbe1680f87bb0226eec48ee5d81c653f3341565a091a5dc118a01dd715e593cc61069b5476bd20d89fd3cb7e60d51d66d08f3095869e0c languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-asyncapi-json-2@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-parser-adapter-asyncapi-json-2@npm:0.74.1" +"@swagger-api/apidom-parser-adapter-asyncapi-json-2@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-parser-adapter-asyncapi-json-2@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-ns-asyncapi-2": ^0.74.1 - "@swagger-api/apidom-parser-adapter-json": ^0.74.1 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-ns-asyncapi-2": ^0.77.0 + "@swagger-api/apidom-parser-adapter-json": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 ramda-adjunct: ^4.0.0 - checksum: 0ba020d883cd305fd11dde0d25714bf2b59ba7772a67b743ae15b5efd204b48be8654c2f3fd10879cb84550aa53bba0ab0186ddd3de6c590f7da5a620f416c1a + checksum: 1dca476bc5b38f3a7da2c8b3a37d6fc18933acaf097c898d50541e323607b038388b84f4df01a68d7a955d2baeedc9359e00aa3bb866372c27e2d49d123450af languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@npm:0.74.1" +"@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-ns-asyncapi-2": ^0.74.1 - "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.74.1 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-ns-asyncapi-2": ^0.77.0 + "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 ramda-adjunct: ^4.0.0 - checksum: b446ffa2ce7189df644259dbbc9bcfef39e8327fb2c47febff0abea58889069f45a47143dfc5b846c90ca9258e64d277f436b1166bdfe67c22c935170301e22c + checksum: 0d39636ad24c7dc3d8008bf36a887ef374b6cc7d3da70615f593604daabfb950217be2d648a48eefe0ec8a8b797f1097568d9658dcc628b1d7f6f2f85f16f2f8 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-json@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-parser-adapter-json@npm:0.74.1" +"@swagger-api/apidom-parser-adapter-json@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-parser-adapter-json@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-ast": ^0.74.1 - "@swagger-api/apidom-core": ^0.74.1 + "@swagger-api/apidom-ast": ^0.77.0 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-error": ^0.77.0 "@types/ramda": ~0.29.3 node-gyp: latest ramda: ~0.29.0 - ramda-adjunct: ^4.0.0 + ramda-adjunct: ^4.1.1 stampit: ^4.3.2 tree-sitter: =0.20.4 tree-sitter-json: =0.20.0 web-tree-sitter: =0.20.3 - checksum: d80a2f9880a73b6cf6dec91bdb119eb52d57d4bce5431e4b344c734878ebec91e3350f9220b7f7eca2987ae955f236c92884f617b50631ddf97477d4bef4ab5b + checksum: 4201832631976179d738de8e80c42c07d3bc9e369485b68b6074dab3cae5753ddc908bb875418fd8b90bdd290e1dfe12d058fc32b0a2285f98aa975bb2d6f754 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-json-3-0@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-parser-adapter-openapi-json-3-0@npm:0.74.1" +"@swagger-api/apidom-parser-adapter-openapi-json-3-0@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-parser-adapter-openapi-json-3-0@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-ns-openapi-3-0": ^0.74.1 - "@swagger-api/apidom-parser-adapter-json": ^0.74.1 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-ns-openapi-3-0": ^0.77.0 + "@swagger-api/apidom-parser-adapter-json": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 ramda-adjunct: ^4.0.0 - checksum: 223e6f8589b792b47a7c21006cdfe08f4472c3e085fdc66a99528a479a46fedef536e6f27e89b75bd8f3cd983749eabaabcba60700599dad8c041ba1417600a8 + checksum: 2b98f225839c556ae332766960b49477cf5f3f89a710f8eb8151eb078827f5fc82dc5f1d8691454200a24aa192ad3799fe2446c4a779fba137ac2ee09fb0ee01 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-json-3-1@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-parser-adapter-openapi-json-3-1@npm:0.74.1" +"@swagger-api/apidom-parser-adapter-openapi-json-3-1@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-parser-adapter-openapi-json-3-1@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-ns-openapi-3-1": ^0.74.1 - "@swagger-api/apidom-parser-adapter-json": ^0.74.1 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-ns-openapi-3-1": ^0.77.0 + "@swagger-api/apidom-parser-adapter-json": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 ramda-adjunct: ^4.0.0 - checksum: defdbd6e641317bd0d6508b4f92dca0216e041a6672fc48c998aef53c08aeb89591954d6a348ead1be728b9cefcc9e9e786bcba3aa7bc2659cce7e47e08b31a0 + checksum: a033f89957c4ef1e25f093026462d361942d613622f69acfd460c57485d183642ea9c29a004d94cff108779f2e55378cae5cd4dfd6e28fc20ecf93a5310369c8 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@npm:0.74.1" +"@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-ns-openapi-3-0": ^0.74.1 - "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.74.1 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-ns-openapi-3-0": ^0.77.0 + "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 ramda-adjunct: ^4.0.0 - checksum: c63fcb9501f28a1a9c6815fc71a1a5200f49822fe101665bb5ffbe4fcb52f67e68c072f268a334d5495bac4cea261206add12d0deb08594cb934d897cd1cf604 + checksum: ce1b582d4c8f5abaaa595e6064e61c5003697257dac21b3e1602f43f42510284c2e9b720380a94e2eb035abec90a25e5ced41071a5560600bc0ad85ad3651d4a languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@npm:0.74.1" +"@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-ns-openapi-3-1": ^0.74.1 - "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.74.1 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-ns-openapi-3-1": ^0.77.0 + "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.77.0 "@types/ramda": ~0.29.3 ramda: ~0.29.0 ramda-adjunct: ^4.0.0 - checksum: 11893a6477013377bc60785f4e2769c5c7ddd403358c3ad2def037b75227d661cc26ec85d5a5dad9cae906696fe9091cdaab9a1d822c80c627f5cd99af1ed295 + checksum: 169fb616d2c2f3b5f136450122c9c5c6e5016d50efe5b2e64b67fde72359fc7114580b22f952ae97e5d6f30377e3b8688cc610e679f2ebf1c4e5e973130fd9e1 languageName: node linkType: hard -"@swagger-api/apidom-parser-adapter-yaml-1-2@npm:^0.74.1": - version: 0.74.1 - resolution: "@swagger-api/apidom-parser-adapter-yaml-1-2@npm:0.74.1" +"@swagger-api/apidom-parser-adapter-yaml-1-2@npm:^0.77.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-parser-adapter-yaml-1-2@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-ast": ^0.74.1 - "@swagger-api/apidom-core": ^0.74.1 + "@swagger-api/apidom-ast": ^0.77.0 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-error": ^0.77.0 "@types/ramda": ~0.29.3 node-gyp: latest ramda: ~0.29.0 - ramda-adjunct: ^4.0.0 + ramda-adjunct: ^4.1.1 stampit: ^4.3.2 tree-sitter: =0.20.4 tree-sitter-yaml: =0.5.0 web-tree-sitter: =0.20.3 - checksum: 145a1f248f9de7a7f31593f7a9ad593c653948414e3fe70349d54b2301a7bb501765ccd595db318d00fcb5d9eafaa394e514fc68c4f69741096b750ad4f3affe + checksum: 8f58f0b05c4e1cce86c456bf5f4d68a479992542620194fd8207b4550c6b876568847583e19b2f1855afe20946197742c1a7ddddb36f175e82f638dce4c33a07 languageName: node linkType: hard -"@swagger-api/apidom-reference@npm:>=0.74.1 <1.0.0": - version: 0.74.1 - resolution: "@swagger-api/apidom-reference@npm:0.74.1" +"@swagger-api/apidom-reference@npm:>=0.77.0 <1.0.0": + version: 0.77.0 + resolution: "@swagger-api/apidom-reference@npm:0.77.0" dependencies: "@babel/runtime-corejs3": ^7.20.7 - "@swagger-api/apidom-core": ^0.74.1 - "@swagger-api/apidom-json-pointer": ^0.74.1 - "@swagger-api/apidom-ns-asyncapi-2": ^0.74.1 - "@swagger-api/apidom-ns-openapi-3-0": ^0.74.1 - "@swagger-api/apidom-ns-openapi-3-1": ^0.74.1 - "@swagger-api/apidom-parser-adapter-api-design-systems-json": ^0.74.1 - "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": ^0.74.1 - "@swagger-api/apidom-parser-adapter-asyncapi-json-2": ^0.74.1 - "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": ^0.74.1 - "@swagger-api/apidom-parser-adapter-json": ^0.74.1 - "@swagger-api/apidom-parser-adapter-openapi-json-3-0": ^0.74.1 - "@swagger-api/apidom-parser-adapter-openapi-json-3-1": ^0.74.1 - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": ^0.74.1 - "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": ^0.74.1 - "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.74.1 + "@swagger-api/apidom-core": ^0.77.0 + "@swagger-api/apidom-error": ^0.77.0 + "@swagger-api/apidom-json-pointer": ^0.77.0 + "@swagger-api/apidom-ns-asyncapi-2": ^0.77.0 + "@swagger-api/apidom-ns-openapi-3-0": ^0.77.0 + "@swagger-api/apidom-ns-openapi-3-1": ^0.77.0 + "@swagger-api/apidom-parser-adapter-api-design-systems-json": ^0.77.0 + "@swagger-api/apidom-parser-adapter-api-design-systems-yaml": ^0.77.0 + "@swagger-api/apidom-parser-adapter-asyncapi-json-2": ^0.77.0 + "@swagger-api/apidom-parser-adapter-asyncapi-yaml-2": ^0.77.0 + "@swagger-api/apidom-parser-adapter-json": ^0.77.0 + "@swagger-api/apidom-parser-adapter-openapi-json-3-0": ^0.77.0 + "@swagger-api/apidom-parser-adapter-openapi-json-3-1": ^0.77.0 + "@swagger-api/apidom-parser-adapter-openapi-yaml-3-0": ^0.77.0 + "@swagger-api/apidom-parser-adapter-openapi-yaml-3-1": ^0.77.0 + "@swagger-api/apidom-parser-adapter-yaml-1-2": ^0.77.0 "@types/ramda": ~0.29.3 axios: ^1.4.0 minimatch: ^7.4.3 process: ^0.11.10 ramda: ~0.29.0 - ramda-adjunct: ^4.0.0 + ramda-adjunct: ^4.1.1 stampit: ^4.3.2 dependenciesMeta: + "@swagger-api/apidom-error": + optional: true "@swagger-api/apidom-json-pointer": optional: true "@swagger-api/apidom-ns-asyncapi-2": @@ -16504,7 +16479,7 @@ __metadata: optional: true "@swagger-api/apidom-parser-adapter-yaml-1-2": optional: true - checksum: dda3f3da4fcea911bd19136635293c07e62d3ba6d4248fe3fee22eb659250631809f045a439cad03b6afc5a5472bd4ee3168bfe5be1bf53bfbd3dceed7ef60f4 + checksum: 19c9fc67aa37d0377eb210a49dfbc219be65c70ca8f3cc497453b5a4f76e597e363990aec0d36fbab9a43401ba6c1152c62ee3920d8f3f462f68ef957b911b77 languageName: node linkType: hard @@ -16632,11 +16607,11 @@ __metadata: linkType: hard "@swc/helpers@npm:^0.5.0": - version: 0.5.2 - resolution: "@swc/helpers@npm:0.5.2" + version: 0.5.3 + resolution: "@swc/helpers@npm:0.5.3" dependencies: tslib: ^2.4.0 - checksum: 51d7e3d8bd56818c49d6bfbd715f0dbeedc13cf723af41166e45c03e37f109336bbcb57a1f2020f4015957721aeb21e1a7fff281233d797ff7d3dd1f447fa258 + checksum: 61c3f7ccd47fc70ad91437df88be6b458cdc11e311cb331288827d7c50befffc72aa18fe913ec2a9e70fbf44e4b818bed38bfd7c329d689e1ff3c198d084cd02 languageName: node linkType: hard @@ -16668,18 +16643,18 @@ __metadata: languageName: node linkType: hard -"@tanstack/query-core@npm:4.35.7": - version: 4.35.7 - resolution: "@tanstack/query-core@npm:4.35.7" - checksum: b82600ee0b2cea085eb6065d36bf944f4fff72b3fa575b5aa55590498fa431f951c5557a4e7ee36ae5b5de5fd5856cb841b974ff6f78cf773199f0f8c860b6c8 +"@tanstack/query-core@npm:4.36.1": + version: 4.36.1 + resolution: "@tanstack/query-core@npm:4.36.1" + checksum: 47672094da20d89402d9fe03bb7b0462be73a76ff9ca715169738bc600a719d064d106d083a8eedae22a2c22de22f87d5eb5d31ef447aba771d9190f2117ed10 languageName: node linkType: hard "@tanstack/react-query@npm:^4.1.3": - version: 4.35.7 - resolution: "@tanstack/react-query@npm:4.35.7" + version: 4.36.1 + resolution: "@tanstack/react-query@npm:4.36.1" dependencies: - "@tanstack/query-core": 4.35.7 + "@tanstack/query-core": 4.36.1 use-sync-external-store: ^1.2.0 peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -16690,7 +16665,7 @@ __metadata: optional: true react-native: optional: true - checksum: ba4e1aa883a42424085c81d44816fb7ee8efdc8c8d1c190320e78818ce8a45cfcafd2a9c0e217d19ff25b0ec58592c98f5286b5a9b738a799c3ee016a02f9447 + checksum: 1aff0a476859386f8d32253fa0d0bde7b81769a6d4d4d9cbd78778f0f955459a3bdb7ee27a0d2ee7373090f12998b45df80db0b5b313bd0a7a39d36c6e8e51c5 languageName: node linkType: hard @@ -16728,9 +16703,9 @@ __metadata: languageName: unknown linkType: soft -"@testing-library/dom@npm:^8.0.0": - version: 8.20.1 - resolution: "@testing-library/dom@npm:8.20.1" +"@testing-library/dom@npm:^9.0.0": + version: 9.3.3 + resolution: "@testing-library/dom@npm:9.3.3" dependencies: "@babel/code-frame": ^7.10.4 "@babel/runtime": ^7.12.5 @@ -16740,28 +16715,41 @@ __metadata: dom-accessibility-api: ^0.5.9 lz-string: ^1.5.0 pretty-format: ^27.0.2 - checksum: 06fc8dc67849aadb726cbbad0e7546afdf8923bd39acb64c576d706249bd7d0d05f08e08a31913fb621162e3b9c2bd0dce15964437f030f9fa4476326fdd3007 + checksum: 34e0a564da7beb92aa9cc44a9080221e2412b1a132eb37be3d513fe6c58027674868deb9f86195756d98d15ba969a30fe00632a4e26e25df2a5a4f6ac0686e37 languageName: node linkType: hard -"@testing-library/jest-dom@npm:^5.10.1, @testing-library/jest-dom@npm:^5.16.4, @testing-library/jest-dom@npm:^5.16.5": - version: 5.17.0 - resolution: "@testing-library/jest-dom@npm:5.17.0" +"@testing-library/jest-dom@npm:^6.0.0": + version: 6.1.4 + resolution: "@testing-library/jest-dom@npm:6.1.4" dependencies: - "@adobe/css-tools": ^4.0.1 + "@adobe/css-tools": ^4.3.1 "@babel/runtime": ^7.9.2 - "@types/testing-library__jest-dom": ^5.9.1 aria-query: ^5.0.0 chalk: ^3.0.0 css.escape: ^1.5.1 dom-accessibility-api: ^0.5.6 lodash: ^4.17.15 redent: ^3.0.0 - checksum: 9f28dbca8b50d7c306aae40c3aa8e06f0e115f740360004bd87d57f95acf7ab4b4f4122a7399a76dbf2bdaaafb15c99cc137fdcb0ae457a92e2de0f3fbf9b03b + peerDependencies: + "@jest/globals": ">= 28" + "@types/jest": ">= 28" + jest: ">= 28" + vitest: ">= 0.32" + peerDependenciesMeta: + "@jest/globals": + optional: true + "@types/jest": + optional: true + jest: + optional: true + vitest: + optional: true + checksum: c6bd9469554136a25d94b55ea16736d56b8c5d200526023774dbf35ca35551a721257e6734f1b404bbd07ae0a1950f1912b5be60e113db2ff2ff50af14f7085c languageName: node linkType: hard -"@testing-library/react-hooks@npm:^8.0.0, @testing-library/react-hooks@npm:^8.0.1": +"@testing-library/react-hooks@npm:^8.0.0": version: 8.0.1 resolution: "@testing-library/react-hooks@npm:8.0.1" dependencies: @@ -16783,17 +16771,17 @@ __metadata: languageName: node linkType: hard -"@testing-library/react@npm:^12.1.3": - version: 12.1.5 - resolution: "@testing-library/react@npm:12.1.5" +"@testing-library/react@npm:^14.0.0": + version: 14.0.0 + resolution: "@testing-library/react@npm:14.0.0" dependencies: "@babel/runtime": ^7.12.5 - "@testing-library/dom": ^8.0.0 - "@types/react-dom": <18.0.0 + "@testing-library/dom": ^9.0.0 + "@types/react-dom": ^18.0.0 peerDependencies: - react: <18.0.0 - react-dom: <18.0.0 - checksum: 4abd0490405e709a7df584a0db604e508a4612398bb1326e8fa32dd9393b15badc826dcf6d2f7525437886d507871f719f127b9860ed69ddd204d1fa834f576a + react: ^18.0.0 + react-dom: ^18.0.0 + checksum: 4a54c8f56cc4a39b50803205f84f06280bb76521d6d5d4b3b36651d760c7c7752ef142d857d52aaf4fad4848ed7a8be49afc793a5dda105955d2f8bef24901ac languageName: node linkType: hard @@ -17329,9 +17317,9 @@ __metadata: linkType: hard "@types/diff@npm:^5.0.0": - version: 5.0.5 - resolution: "@types/diff@npm:5.0.5" - checksum: 5f093341d5488cd33079400d4b2ff463dfd4f589bf0a54fbb25f7c87a7bdc16bd1e6125f252c081fa9a3ad44fc78b156c0a5f38bd8128edceb40ba084e051885 + version: 5.0.6 + resolution: "@types/diff@npm:5.0.6" + checksum: 8ce79492a89d568b54792a8491d01b1ff69526e19560670ef2de078c467738cdc0aae81fc4f895e49f915a2b9bbf694f6f95a2e5544e7c0989448956eba9ff66 languageName: node linkType: hard @@ -17443,14 +17431,14 @@ __metadata: linkType: hard "@types/express@npm:*, @types/express@npm:^4.17.13, @types/express@npm:^4.17.17, @types/express@npm:^4.17.6": - version: 4.17.18 - resolution: "@types/express@npm:4.17.18" + version: 4.17.19 + resolution: "@types/express@npm:4.17.19" dependencies: "@types/body-parser": "*" "@types/express-serve-static-core": ^4.17.33 "@types/qs": "*" "@types/serve-static": "*" - checksum: 8c178da4f0edff1f006d871fbdc3f849620986ff10bad252f3dfd45b57554e26aaa28c602285df028930d5216e257a06fbaf795070f8bb42f7d87e3b689cba50 + checksum: 3d39d0655eb0825d96fec100985a38737767ddd6da2dbda1e330a3adf36c98a9b7cd8d9539db32876d1fbb47a09343cad7b38c30c8dd7c291271fcb9b85cb21b languageName: node linkType: hard @@ -17580,12 +17568,12 @@ __metadata: linkType: hard "@types/inquirer@npm:^8.1.3": - version: 8.2.6 - resolution: "@types/inquirer@npm:8.2.6" + version: 8.2.7 + resolution: "@types/inquirer@npm:8.2.7" dependencies: "@types/through": "*" rxjs: ^7.2.0 - checksum: d09c3b6bbfb1aff8bdb8fc938d43536be55dfb51af0c91d0105e3f7c5e3950c12618ac00e2e91f10b5abeba38f4b903289be1df5aa31f213b58c3cc675a19f81 + checksum: 8f021bc2ad0cdcccbd55abd11a8ecc73f716ea108f2ffb5f8f605d23519b47acb46fdcac032d8c81e7c05f183c0f2300a0a394c449ad8980bc11f333708d4387 languageName: node linkType: hard @@ -17669,11 +17657,11 @@ __metadata: linkType: hard "@types/jquery@npm:^3.3.34": - version: 3.5.21 - resolution: "@types/jquery@npm:3.5.21" + version: 3.5.22 + resolution: "@types/jquery@npm:3.5.22" dependencies: "@types/sizzle": "*" - checksum: 48cce8892f0292ac68853677d408195436a460ed45445a2da13deddcf21b407b3f896bbf5714f320c8f44666fdff5ceba5c59e873a316486098040404dcf56f4 + checksum: b81c95e27bb30686c1ad5d3f414781243d0cbb468b91d5584dedd3d3ca07ac99796d876e257a7246d6d9b69916bbb0cd0508142ab9f88848605c6d431144d729 languageName: node linkType: hard @@ -17692,9 +17680,9 @@ __metadata: linkType: hard "@types/js-yaml@npm:^4.0.0, @types/js-yaml@npm:^4.0.1": - version: 4.0.6 - resolution: "@types/js-yaml@npm:4.0.6" - checksum: d4439ec2cc830d355c2a1d7508f49888931b2cfe59d786d27621edd530bf06314b1dceeaa759e21f9b035a0ff623a0ca306752ebb73df9485c02abe045bd962c + version: 4.0.7 + resolution: "@types/js-yaml@npm:4.0.7" + checksum: e02eca876f3f19dbba62a26a18e59ec5df4e29300b99808fb0b4ca980cbfbb60e4a2c7d75d521728f5b2a3b92a0da5b9343497b2acf621b8ea019d48b40bbd78 languageName: node linkType: hard @@ -17728,7 +17716,7 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.11, @types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.7, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.11, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.7, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": version: 7.0.13 resolution: "@types/json-schema@npm:7.0.13" checksum: 345df21a678fa72fb389f35f33de77833d09d4a142bb2bcb27c18690efa4cf70fc2876e43843cefb3fbdb9fcb12cd3e970a90936df30f53bbee899865ff605ab @@ -17959,28 +17947,30 @@ __metadata: 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": - version: 2.6.5 - resolution: "@types/node-fetch@npm:2.6.5" + version: 2.6.6 + resolution: "@types/node-fetch@npm:2.6.6" dependencies: "@types/node": "*" form-data: ^4.0.0 - checksum: 686ee0d52bb82d73f82c0da0bb025d4af1ba7bd8df4edd09336f6179eb838b6d4b5f0a524677a8faec2b00918d1b08a1690d50fa592c9741a5df6a8041a52495 + checksum: ac66389d9d597ab91f5e5d3724e594965b9f80ae5841ab5da9f0c3bd54ceac084591cfe69b1c413f18bb7efdd97002d05bd7651d58ba0c6c10f804f4fd85e598 languageName: node linkType: hard "@types/node-forge@npm:^1.3.0": - version: 1.3.6 - resolution: "@types/node-forge@npm:1.3.6" + version: 1.3.7 + resolution: "@types/node-forge@npm:1.3.7" dependencies: "@types/node": "*" - checksum: 5fe97ce83937c51215a52eb8c9d5c4458abbca2b3cfd91a65142f20fd4a2830ed10ab1a8c860efc55ff36553f939a75c4a6d5c243ed6e24e55a005c9bddeaf43 + checksum: e604e0e09e0ffdcf7babdf2415f7d2de14a7718ddc9c5916a693f81597dc80865d525dfb7fc876a787c25bf1164518cd8ecf1667598bee00c9ba1349f93ba4eb 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.8.2 - resolution: "@types/node@npm:20.8.2" - checksum: 3da73e25d821bfcdb7de98589027e08bb4848e55408671c4a83ec0341e124b5313a0b20e1e4b4eff1168ea17a86f622ad73fcb04b761abd77496b9a27cbd5de5 + version: 20.8.6 + resolution: "@types/node@npm:20.8.6" + dependencies: + undici-types: ~5.25.1 + checksum: ccfb7ac482c5a96edeb239893c5c099f5257fcc2ed9ae62fefdfbc782b79e16dbc2af9a85b379665237bf759904b44ca2be68e75d239e0297882aad42f61905c languageName: node linkType: hard @@ -17999,16 +17989,16 @@ __metadata: linkType: hard "@types/node@npm:^16.11.26, @types/node@npm:^16.9.2": - version: 16.18.57 - resolution: "@types/node@npm:16.18.57" - checksum: db21a14416de3abce8dfc30d9e9513c505060ef4d197fdc1b1b7374feca3417a7757172d041989fd49910245e9f2d7869201accac3cceee7c75bfdf8759ead6d + version: 16.18.58 + resolution: "@types/node@npm:16.18.58" + checksum: 6d8404abc6c97bacd220f606441727adea923f3bd010d07d869f0dc6c4c6dc016430880af1f270edf1b84ae637a7fa5339e6adb3abba210a4820ac5e28f34067 languageName: node linkType: hard -"@types/node@npm:^18.11.17, @types/node@npm:^18.17.8": - version: 18.18.3 - resolution: "@types/node@npm:18.18.3" - checksum: ed97a832179e0cfbb93738021fe16d0bc5c0f34bea35269c23c9dd5f0ecc8be93dbe5efd51630189a099b31786a47c1bde115508831a7245613a55c3ad1a7d6b +"@types/node@npm:^18.17.8": + version: 18.18.5 + resolution: "@types/node@npm:18.18.5" + checksum: fc8c9b2bf226270cf9085a7dac76ce09dd7c3519ec9b687ee2b50385954ab3709c45ca82d002d1536e24286803cd194d7ab7008acebdcd6681b8b19d4277fa5c languageName: node linkType: hard @@ -18138,13 +18128,13 @@ __metadata: linkType: hard "@types/pg@npm:^8.6.6": - version: 8.10.3 - resolution: "@types/pg@npm:8.10.3" + version: 8.10.5 + resolution: "@types/pg@npm:8.10.5" dependencies: "@types/node": "*" pg-protocol: "*" pg-types: ^4.0.1 - checksum: 05a12be3f18cc67728e3aee5a7426f065351ca991e351d2e7a0562c5d9063425d67fe88fd35108834e0fa1f5624032fefbf371cf8f3cc47230a666aa953425b9 + checksum: 532a3104ed7898e3c7806e00cbde486dcfc803d2e99e236066f1b675ff0546a1cb232fe6f2ffc60dac81d3df209b69dbe62a597b565bff0965dd622fef957afe languageName: node linkType: hard @@ -18208,12 +18198,12 @@ __metadata: languageName: node linkType: hard -"@types/react-dom@npm:^17": - version: 17.0.21 - resolution: "@types/react-dom@npm:17.0.21" +"@types/react-dom@npm:^18": + version: 18.2.13 + resolution: "@types/react-dom@npm:18.2.13" dependencies: - "@types/react": ^17 - checksum: a2e3f068c1374601856b63bc57f3f436cf6270c1ba5c5cef0776def6de296c8bdd31c39b5be9e9e77f4652e923bef1e71ae377a2b038f4a81bfd0fec8d10d0d0 + "@types/react": "*" + checksum: 22ba066b141dca5a5a9227fae0afc7c94b470fff8e8a38ade72649da57a8ea04d0cb2ba3e22005e7d8e772d49bddd28855b1dd98e6defd033bba6afb6edff883 languageName: node linkType: hard @@ -18257,11 +18247,11 @@ __metadata: linkType: hard "@types/react-syntax-highlighter@npm:^15.0.0": - version: 15.5.7 - resolution: "@types/react-syntax-highlighter@npm:15.5.7" + version: 15.5.8 + resolution: "@types/react-syntax-highlighter@npm:15.5.8" dependencies: "@types/react": "*" - checksum: 1918d01baaa9bf485093fb04167d0dc87131be708bd68d32d3f614c0e7dba05de765fc62df139fa1972836b13e27983a2d89552eda5b5a38691a4ec300949648 + checksum: 3bee4fe5901abc57c06b70aee528a7a2aa9617f8347fbe960f6b7ba14a231aa6fab892e1f6cd9b1e1321078183a9773fcf55488df63cfc7dfa8a307aa48040b3 languageName: node linkType: hard @@ -18283,12 +18273,12 @@ __metadata: languageName: node linkType: hard -"@types/react-transition-group@npm:^4.2.0, @types/react-transition-group@npm:^4.4.6": - version: 4.4.6 - resolution: "@types/react-transition-group@npm:4.4.6" +"@types/react-transition-group@npm:^4.2.0, @types/react-transition-group@npm:^4.4.7": + version: 4.4.7 + resolution: "@types/react-transition-group@npm:4.4.7" dependencies: "@types/react": "*" - checksum: 0872143821d7ee20a1d81e965f8b1e837837f11cd2206973f1f98655751992d9390304d58bac192c9cd923eca95bff107d8c9e3364a180240d5c2a6fd70fd7c3 + checksum: 3b91486e7aa777a3787e773efce79a0fa9be4ec9e02d51ccda8c7532c5c5d84fbcefe248dacb4007293d85bf0794ac51603bb9cec360db81cf3657d2b7123fb9 languageName: node linkType: hard @@ -18310,14 +18300,14 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:^17": - version: 17.0.67 - resolution: "@types/react@npm:17.0.67" +"@types/react@npm:^18": + version: 18.2.28 + resolution: "@types/react@npm:18.2.28" dependencies: "@types/prop-types": "*" "@types/scheduler": "*" csstype: ^3.0.2 - checksum: eb4915fc7d24e19fe6e98dfe98ade377423b1263e7dc001beda41b0298152fb5a410a55dde5def5ec0838156239a48e778d522da03d319ae5ecea80d455da604 + checksum: 81381bedeba83278f4c9febb0b83e0bd3f42a25897a50b9cb36ef53651d34b3d50f87ebf11211ea57ea575131f85d31e93e496ce46478a00b0f9bf7b26b5917a languageName: node linkType: hard @@ -18423,11 +18413,11 @@ __metadata: linkType: hard "@types/sanitize-html@npm:^2.6.2": - version: 2.9.1 - resolution: "@types/sanitize-html@npm:2.9.1" + version: 2.9.2 + resolution: "@types/sanitize-html@npm:2.9.2" dependencies: htmlparser2: ^8.0.0 - checksum: 381db8e3f22876e8f6aa8f0997af73c71220c8398545d809ebd4e25d33480e73642b8c143a87d87bba504a43ab58d70a724c60eb3fd8fde31a813b682730c98f + checksum: bdd0db4a39125b8836573ede5ec5cc2f7b0dff5ecfbeae68aefb40163c916429cfb500d581ad3a18613e8d6a53f707abb279350e0811122e84e21b0223b8d560 languageName: node linkType: hard @@ -18824,54 +18814,46 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^5.9.0": - version: 5.53.0 - resolution: "@typescript-eslint/eslint-plugin@npm:5.53.0" +"@typescript-eslint/eslint-plugin@npm:6.7.5": + version: 6.7.5 + resolution: "@typescript-eslint/eslint-plugin@npm:6.7.5" dependencies: - "@typescript-eslint/scope-manager": 5.53.0 - "@typescript-eslint/type-utils": 5.53.0 - "@typescript-eslint/utils": 5.53.0 + "@eslint-community/regexpp": ^4.5.1 + "@typescript-eslint/scope-manager": 6.7.5 + "@typescript-eslint/type-utils": 6.7.5 + "@typescript-eslint/utils": 6.7.5 + "@typescript-eslint/visitor-keys": 6.7.5 debug: ^4.3.4 - grapheme-splitter: ^1.0.4 - ignore: ^5.2.0 - natural-compare-lite: ^1.4.0 - regexpp: ^3.2.0 - semver: ^7.3.7 - tsutils: ^3.21.0 + graphemer: ^1.4.0 + ignore: ^5.2.4 + natural-compare: ^1.4.0 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 peerDependencies: - "@typescript-eslint/parser": ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + "@typescript-eslint/parser": ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 12dffe65969d8e5248c86a700fe46a737e55ecafb276933e747b4731eab6266fe55e2d43a34b8b340179fe248e127d861cd016a7614b1b9804cd0687c99616d1 + checksum: c37edf5a703db4ff9227d67c2d2cf817e65c9afc94cc0e650fa3d2b05ac55201ef887ce9dadb9ca13779f4025bf4367e132b013e3559e777006a2332079bb180 languageName: node linkType: hard -"@typescript-eslint/parser@npm:^5.9.0": - version: 5.53.0 - resolution: "@typescript-eslint/parser@npm:5.53.0" +"@typescript-eslint/parser@npm:^6.7.2": + version: 6.7.5 + resolution: "@typescript-eslint/parser@npm:6.7.5" dependencies: - "@typescript-eslint/scope-manager": 5.53.0 - "@typescript-eslint/types": 5.53.0 - "@typescript-eslint/typescript-estree": 5.53.0 + "@typescript-eslint/scope-manager": 6.7.5 + "@typescript-eslint/types": 6.7.5 + "@typescript-eslint/typescript-estree": 6.7.5 + "@typescript-eslint/visitor-keys": 6.7.5 debug: ^4.3.4 peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 979e5d63793a9e64998b1f956ba0f00f8a2674db3a664fafce7b2433323f5248bd776af8305e2419d73a9d94c55176fee099abc5c153b4cc52e5765c725c1edd - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:5.53.0": - version: 5.53.0 - resolution: "@typescript-eslint/scope-manager@npm:5.53.0" - dependencies: - "@typescript-eslint/types": 5.53.0 - "@typescript-eslint/visitor-keys": 5.53.0 - checksum: 51f31dc01e95908611f402441f58404da80a338c0237b2b82f4a7b0b2e8868c4bfe8f7cf44b2567dd56533de609156a5d4ac54bb1f9f09c7014b99428aef2543 + checksum: 63f988c1c87697bd20487933be952b97f7a5f2a9977f505af671c7d49367fc01ca508817576646caa937c15cc0a0ef1e86adff9111eb19df8b489e7436d10620 languageName: node linkType: hard @@ -18885,27 +18867,30 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:5.53.0": - version: 5.53.0 - resolution: "@typescript-eslint/type-utils@npm:5.53.0" +"@typescript-eslint/scope-manager@npm:6.7.5": + version: 6.7.5 + resolution: "@typescript-eslint/scope-manager@npm:6.7.5" dependencies: - "@typescript-eslint/typescript-estree": 5.53.0 - "@typescript-eslint/utils": 5.53.0 - debug: ^4.3.4 - tsutils: ^3.21.0 - peerDependencies: - eslint: "*" - peerDependenciesMeta: - typescript: - optional: true - checksum: 52c40967c5fabd58c2ae8bf519ef89e4feb511e4df630aeaeac8335661a79b6b3a32d30a61a5f1d8acc703f21c4d90751a5d41cda1b35d08867524da11bc2e1d + "@typescript-eslint/types": 6.7.5 + "@typescript-eslint/visitor-keys": 6.7.5 + checksum: f21858ed78f81ab2d9879139f69657fda2a7b901078f79df64d1262d80f84ef66c56525ed0bb5e393fa5ca5474ad97f2225b7f713977c2d0f79cda31b2744af9 languageName: node linkType: hard -"@typescript-eslint/types@npm:5.53.0": - version: 5.53.0 - resolution: "@typescript-eslint/types@npm:5.53.0" - checksum: b0eaf23de4ab13697d4d2095838c959a3f410c30f0d19091e5ca08e62320c3cc3c72bcb631823fb6a4fbb31db0a059e386a0801244930d0a88a6a698e5f46548 +"@typescript-eslint/type-utils@npm:6.7.5": + version: 6.7.5 + resolution: "@typescript-eslint/type-utils@npm:6.7.5" + dependencies: + "@typescript-eslint/typescript-estree": 6.7.5 + "@typescript-eslint/utils": 6.7.5 + debug: ^4.3.4 + ts-api-utils: ^1.0.1 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 8023d8ddcfbf4a0411b192016711068e9e6787c5811aee3a25ac40025ade0d063a1a3d7b38469e1a534bb31fa9dbeec08ab53b7a6d7b3128358294ac5b219d9a languageName: node linkType: hard @@ -18916,21 +18901,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:5.53.0": - version: 5.53.0 - resolution: "@typescript-eslint/typescript-estree@npm:5.53.0" - dependencies: - "@typescript-eslint/types": 5.53.0 - "@typescript-eslint/visitor-keys": 5.53.0 - debug: ^4.3.4 - globby: ^11.1.0 - is-glob: ^4.0.3 - semver: ^7.3.7 - tsutils: ^3.21.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 6e119c8e4167c8495d728c5556a834545a9c064918dd5e7b79b0d836726f4f8e2a0297b0ac82bf2b71f1e5427552217d0b59d8fb1406fd79bd3bf91b75dca873 +"@typescript-eslint/types@npm:6.7.5": + version: 6.7.5 + resolution: "@typescript-eslint/types@npm:6.7.5" + checksum: f21e5726b60f13feb3a920c92515fbc1205ba0e9bba9959b2e42c02c282a0ab4fb0e5ae84f3807b9b1cf95036027e9033d92a911fa88e6c243a87621d8dd7a01 languageName: node linkType: hard @@ -18952,21 +18926,38 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:5.53.0": - version: 5.53.0 - resolution: "@typescript-eslint/utils@npm:5.53.0" +"@typescript-eslint/typescript-estree@npm:6.7.5": + version: 6.7.5 + resolution: "@typescript-eslint/typescript-estree@npm:6.7.5" dependencies: - "@types/json-schema": ^7.0.9 - "@types/semver": ^7.3.12 - "@typescript-eslint/scope-manager": 5.53.0 - "@typescript-eslint/types": 5.53.0 - "@typescript-eslint/typescript-estree": 5.53.0 - eslint-scope: ^5.1.1 - eslint-utils: ^3.0.0 - semver: ^7.3.7 + "@typescript-eslint/types": 6.7.5 + "@typescript-eslint/visitor-keys": 6.7.5 + 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: 17685e8321edce1d1ec4278d84e63c0f41ccb19e9308f21c37450943ad0c33328755ac52b966e7855af17e01d22bc83d1fcda79c279fabe7d3460c8f315a7265 + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:6.7.5": + version: 6.7.5 + resolution: "@typescript-eslint/utils@npm:6.7.5" + dependencies: + "@eslint-community/eslint-utils": ^4.4.0 + "@types/json-schema": ^7.0.12 + "@types/semver": ^7.5.0 + "@typescript-eslint/scope-manager": 6.7.5 + "@typescript-eslint/types": 6.7.5 + "@typescript-eslint/typescript-estree": 6.7.5 + semver: ^7.5.4 peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 18e6bac14ae853385a74123759850bca367904723e170c37416fc014673eb714afb6bb090367bff61494a8387e941b6af65ee5f4f845f7177fabb4df85e01643 + eslint: ^7.0.0 || ^8.0.0 + checksum: f365c654241f927e7784640079627d60a296aa3d575552b07594a69cfc419832eb5fa4adc87acb1988bea9741ae9cc4a5277dab168990310caef5de125255752 languageName: node linkType: hard @@ -18988,16 +18979,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:5.53.0": - version: 5.53.0 - resolution: "@typescript-eslint/visitor-keys@npm:5.53.0" - dependencies: - "@typescript-eslint/types": 5.53.0 - eslint-visitor-keys: ^3.3.0 - checksum: 090695883c15364c6f401e97f56b13db0f31c1114f3bd22562bd41734864d27f6a3c80de33957e9dedab2d5f94b0f4480ba3fde1d4574e74dca4593917b7b54a - languageName: node - linkType: hard - "@typescript-eslint/visitor-keys@npm:5.59.8": version: 5.59.8 resolution: "@typescript-eslint/visitor-keys@npm:5.59.8" @@ -19008,6 +18989,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:6.7.5": + version: 6.7.5 + resolution: "@typescript-eslint/visitor-keys@npm:6.7.5" + dependencies: + "@typescript-eslint/types": 6.7.5 + eslint-visitor-keys: ^3.4.1 + checksum: 2df996742f63d89fa339b0e8ff3a3a289d36b3f584f7538a7626bed3869e9ae27f8f56ab31748519d25a63de2ae22a43dd8413610b00436ff342b0a17eb85289 + languageName: node + linkType: hard + "@uiw/codemirror-extensions-basic-setup@npm:4.21.19": version: 4.21.19 resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.21.19" @@ -19588,7 +19579,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.7.0, ajv@npm:~6.12.6": +"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": version: 6.12.6 resolution: "ajv@npm:6.12.6" dependencies: @@ -19750,8 +19741,8 @@ __metadata: cross-fetch: ^3.1.5 msw: ^1.0.0 peerDependencies: - react: ^16.13.1 || ^17.0.0 - react-dom: ^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 react-router-dom: 6.0.0-beta.0 || ^6.3.0 languageName: unknown linkType: soft @@ -22247,7 +22238,7 @@ __metadata: languageName: node linkType: hard -"compute-lcm@npm:^1.1.0, compute-lcm@npm:^1.1.2": +"compute-lcm@npm:^1.1.2": version: 1.1.2 resolution: "compute-lcm@npm:1.1.2" dependencies: @@ -22513,7 +22504,7 @@ __metadata: languageName: node linkType: hard -"core-js-pure@npm:^3.23.3, core-js-pure@npm:^3.30.2, core-js-pure@npm:^3.6.5": +"core-js-pure@npm:^3.23.3, core-js-pure@npm:^3.30.2": version: 3.31.0 resolution: "core-js-pure@npm:3.31.0" checksum: 2bc5d2f6c3c9732fd5c066529b8d41fae9c746206ddf7614712dc4120a9efd47bf894df4fc600fde8c04324171c1999869798b48b23fca128eff5f09f58cd2f6 @@ -23932,10 +23923,10 @@ __metadata: languageName: node linkType: hard -"dompurify@npm:=3.0.5": - version: 3.0.5 - resolution: "dompurify@npm:3.0.5" - checksum: 2d9421570c833ce26ce7022955241749b646d41e8bf453f42ede9f22d0e98af482cedb7dfbf8129419eb48b351c1d677a08fc9f1cd91836ce7f6c1807a0676b2 +"dompurify@npm:=3.0.6": + version: 3.0.6 + resolution: "dompurify@npm:3.0.6" + checksum: e5c6cdc5fe972a9d0859d939f1d86320de275be00bbef7bd5591c80b1e538935f6ce236624459a1b0c84ecd7c6a1e248684aa4637512659fccc0ce7c353828a6 languageName: node linkType: hard @@ -24471,104 +24462,6 @@ __metadata: languageName: node linkType: hard -"esbuild-android-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-android-64@npm:0.15.18" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"esbuild-android-arm64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-android-arm64@npm:0.15.18" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"esbuild-darwin-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-darwin-64@npm:0.15.18" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"esbuild-darwin-arm64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-darwin-arm64@npm:0.15.18" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"esbuild-freebsd-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-freebsd-64@npm:0.15.18" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"esbuild-freebsd-arm64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-freebsd-arm64@npm:0.15.18" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"esbuild-linux-32@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-32@npm:0.15.18" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"esbuild-linux-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-64@npm:0.15.18" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"esbuild-linux-arm64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-arm64@npm:0.15.18" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"esbuild-linux-arm@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-arm@npm:0.15.18" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"esbuild-linux-mips64le@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-mips64le@npm:0.15.18" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"esbuild-linux-ppc64le@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-ppc64le@npm:0.15.18" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"esbuild-linux-riscv64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-riscv64@npm:0.15.18" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"esbuild-linux-s390x@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-linux-s390x@npm:0.15.18" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - "esbuild-loader@npm:^2.18.0": version: 2.21.0 resolution: "esbuild-loader@npm:2.21.0" @@ -24585,48 +24478,6 @@ __metadata: languageName: node linkType: hard -"esbuild-netbsd-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-netbsd-64@npm:0.15.18" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"esbuild-openbsd-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-openbsd-64@npm:0.15.18" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"esbuild-sunos-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-sunos-64@npm:0.15.18" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"esbuild-windows-32@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-windows-32@npm:0.15.18" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"esbuild-windows-64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-windows-64@npm:0.15.18" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"esbuild-windows-arm64@npm:0.15.18": - version: 0.15.18 - resolution: "esbuild-windows-arm64@npm:0.15.18" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - "esbuild@npm:^0.16.17": version: 0.16.17 resolution: "esbuild@npm:0.16.17" @@ -24781,80 +24632,80 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:~0.15.10": - version: 0.15.18 - resolution: "esbuild@npm:0.15.18" +"esbuild@npm:~0.18.20": + version: 0.18.20 + resolution: "esbuild@npm:0.18.20" dependencies: - "@esbuild/android-arm": 0.15.18 - "@esbuild/linux-loong64": 0.15.18 - esbuild-android-64: 0.15.18 - esbuild-android-arm64: 0.15.18 - esbuild-darwin-64: 0.15.18 - esbuild-darwin-arm64: 0.15.18 - esbuild-freebsd-64: 0.15.18 - esbuild-freebsd-arm64: 0.15.18 - esbuild-linux-32: 0.15.18 - esbuild-linux-64: 0.15.18 - esbuild-linux-arm: 0.15.18 - esbuild-linux-arm64: 0.15.18 - esbuild-linux-mips64le: 0.15.18 - esbuild-linux-ppc64le: 0.15.18 - esbuild-linux-riscv64: 0.15.18 - esbuild-linux-s390x: 0.15.18 - esbuild-netbsd-64: 0.15.18 - esbuild-openbsd-64: 0.15.18 - esbuild-sunos-64: 0.15.18 - esbuild-windows-32: 0.15.18 - esbuild-windows-64: 0.15.18 - esbuild-windows-arm64: 0.15.18 + "@esbuild/android-arm": 0.18.20 + "@esbuild/android-arm64": 0.18.20 + "@esbuild/android-x64": 0.18.20 + "@esbuild/darwin-arm64": 0.18.20 + "@esbuild/darwin-x64": 0.18.20 + "@esbuild/freebsd-arm64": 0.18.20 + "@esbuild/freebsd-x64": 0.18.20 + "@esbuild/linux-arm": 0.18.20 + "@esbuild/linux-arm64": 0.18.20 + "@esbuild/linux-ia32": 0.18.20 + "@esbuild/linux-loong64": 0.18.20 + "@esbuild/linux-mips64el": 0.18.20 + "@esbuild/linux-ppc64": 0.18.20 + "@esbuild/linux-riscv64": 0.18.20 + "@esbuild/linux-s390x": 0.18.20 + "@esbuild/linux-x64": 0.18.20 + "@esbuild/netbsd-x64": 0.18.20 + "@esbuild/openbsd-x64": 0.18.20 + "@esbuild/sunos-x64": 0.18.20 + "@esbuild/win32-arm64": 0.18.20 + "@esbuild/win32-ia32": 0.18.20 + "@esbuild/win32-x64": 0.18.20 dependenciesMeta: "@esbuild/android-arm": optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true "@esbuild/linux-loong64": optional: true - esbuild-android-64: + "@esbuild/linux-mips64el": optional: true - esbuild-android-arm64: + "@esbuild/linux-ppc64": optional: true - esbuild-darwin-64: + "@esbuild/linux-riscv64": optional: true - esbuild-darwin-arm64: + "@esbuild/linux-s390x": optional: true - esbuild-freebsd-64: + "@esbuild/linux-x64": optional: true - esbuild-freebsd-arm64: + "@esbuild/netbsd-x64": optional: true - esbuild-linux-32: + "@esbuild/openbsd-x64": optional: true - esbuild-linux-64: + "@esbuild/sunos-x64": optional: true - esbuild-linux-arm: + "@esbuild/win32-arm64": optional: true - esbuild-linux-arm64: + "@esbuild/win32-ia32": optional: true - esbuild-linux-mips64le: - optional: true - esbuild-linux-ppc64le: - optional: true - esbuild-linux-riscv64: - optional: true - esbuild-linux-s390x: - optional: true - esbuild-netbsd-64: - optional: true - esbuild-openbsd-64: - optional: true - esbuild-sunos-64: - optional: true - esbuild-windows-32: - optional: true - esbuild-windows-64: - optional: true - esbuild-windows-arm64: + "@esbuild/win32-x64": optional: true bin: esbuild: bin/esbuild - checksum: ec12682b2cb2d4f0669d0e555028b87a9284ca7f6a1b26e35e69a8697165b35cc682ad598abc70f0bbcfdc12ca84ef888caf5ceee389237862e8f8c17da85f89 + checksum: 5d253614e50cdb6ec22095afd0c414f15688e7278a7eb4f3720a6dd1306b0909cf431e7b9437a90d065a31b1c57be60130f63fe3e8d0083b588571f31ee6ec7b languageName: node linkType: hard @@ -25149,24 +25000,6 @@ __metadata: languageName: node linkType: hard -"eslint-utils@npm:^3.0.0": - version: 3.0.0 - resolution: "eslint-utils@npm:3.0.0" - dependencies: - eslint-visitor-keys: ^2.0.0 - peerDependencies: - eslint: ">=5" - checksum: 0668fe02f5adab2e5a367eee5089f4c39033af20499df88fe4e6aba2015c20720404d8c3d6349b6f716b08fdf91b9da4e5d5481f265049278099c4c836ccb619 - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^2.0.0": - version: 2.0.0 - resolution: "eslint-visitor-keys@npm:2.0.0" - checksum: e07e9863fb8c9b1453f5ad1a26f3cc8dd6b349b26605cc06bc0c61215ac5b6f13a4d08c875218e6c0f8ac8fc06ca6e090df769e32c569f0fd2e6a848b8a76c75 - languageName: node - linkType: hard - "eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": version: 3.4.3 resolution: "eslint-visitor-keys@npm:3.4.3" @@ -25191,13 +25024,13 @@ __metadata: linkType: hard "eslint@npm:^8.33.0, eslint@npm:^8.6.0": - version: 8.50.0 - resolution: "eslint@npm:8.50.0" + version: 8.51.0 + resolution: "eslint@npm:8.51.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.6.1 "@eslint/eslintrc": ^2.1.2 - "@eslint/js": 8.50.0 + "@eslint/js": 8.51.0 "@humanwhocodes/config-array": ^0.11.11 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 @@ -25233,7 +25066,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 9ebfe5615dc84700000d218e32ddfdcfc227ca600f65f18e5541ec34f8902a00356a9a8804d9468fd6c8637a5ef6a3897291dad91ba6579d5b32ffeae5e31768 + checksum: 214fa5d1fcb67af1b8992ce9584ccd85e1aa7a482f8b8ea5b96edc28fa838a18a3b69456db45fc1ed3ef95f1e9efa9714f737292dc681e572d471d02fda9649c languageName: node linkType: hard @@ -25425,6 +25258,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/frontend-app-api": "workspace:^" @@ -25500,9 +25334,9 @@ __metadata: "@roadiehq/backstage-plugin-github-insights": ^2.0.5 "@roadiehq/backstage-plugin-github-pull-requests": ^2.2.7 "@roadiehq/backstage-plugin-travis-ci": ^2.0.5 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/jquery": ^3.3.34 "@types/react": "*" @@ -25512,9 +25346,8 @@ __metadata: cross-env: ^7.0.0 history: ^5.0.0 lodash: ^4.17.21 - prop-types: ^15.7.2 - react: ^17.0.2 - react-dom: ^17.0.2 + react: ^18.0.2 + react-dom: ^18.0.2 react-router: ^6.3.0 react-router-dom: ^6.3.0 react-use: ^17.2.4 @@ -25614,9 +25447,9 @@ __metadata: "@roadiehq/backstage-plugin-github-insights": ^2.0.5 "@roadiehq/backstage-plugin-github-pull-requests": ^2.2.7 "@roadiehq/backstage-plugin-travis-ci": ^2.0.5 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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/jquery": ^3.3.34 "@types/react": "*" @@ -25624,9 +25457,8 @@ __metadata: "@types/zen-observable": ^0.8.0 cross-env: ^7.0.0 history: ^5.0.0 - prop-types: ^15.7.2 - react: ^17.0.2 - react-dom: ^17.0.2 + react: ^18.0.2 + react-dom: ^18.0.2 react-router: ^6.3.0 react-router-dom: ^6.3.0 react-use: ^17.2.4 @@ -25652,6 +25484,7 @@ __metadata: "@backstage/plugin-catalog-backend-module-unprocessed": "workspace:^" "@backstage/plugin-devtools-backend": "workspace:^" "@backstage/plugin-entity-feedback-backend": "workspace:^" + "@backstage/plugin-jenkins-backend": "workspace:^" "@backstage/plugin-kubernetes-backend": "workspace:^" "@backstage/plugin-lighthouse-backend": "workspace:^" "@backstage/plugin-linguist-backend": "workspace:^" @@ -25734,7 +25567,7 @@ __metadata: "@gitbeaker/node": ^35.1.0 "@octokit/rest": ^19.0.3 "@opentelemetry/api": ^1.4.1 - "@opentelemetry/exporter-prometheus": ^0.39.1 + "@opentelemetry/exporter-prometheus": ^0.44.0 "@opentelemetry/sdk-metrics": ^1.13.0 "@types/dockerode": ^3.3.0 "@types/express": ^4.17.6 @@ -25896,7 +25729,7 @@ __metadata: languageName: node linkType: hard -"express-session@npm:^1.17.1": +"express-session@npm:^1.17.1, express-session@npm:^1.17.3": version: 1.17.3 resolution: "express-session@npm:1.17.3" dependencies: @@ -26594,7 +26427,7 @@ __metadata: languageName: node linkType: hard -"form-data-encoder@npm:^1.4.3, form-data-encoder@npm:^1.7.1": +"form-data-encoder@npm:^1.7.1": version: 1.7.1 resolution: "form-data-encoder@npm:1.7.1" checksum: a2a360d5588a70d323c12a140c3db23a503a38f0a5d141af1efad579dde9f9fff2e49e5f31f378cb4631518c1ab4a826452c92f0d2869e954b6b2d77b05613e1 @@ -26652,7 +26485,7 @@ __metadata: languageName: node linkType: hard -"formdata-node@npm:^4.0.0, formdata-node@npm:^4.3.1": +"formdata-node@npm:^4.3.1": version: 4.3.2 resolution: "formdata-node@npm:4.3.2" dependencies: @@ -27007,10 +26840,12 @@ __metadata: languageName: node linkType: hard -"get-tsconfig@npm:^4.4.0": - version: 4.4.0 - resolution: "get-tsconfig@npm:4.4.0" - checksum: e193558b4f0c84c81ae9688cf5b9950dc0b341e44f91b002713fd0c37cfb73108e1cd9998ed540bcc423f193fde32cc58a15e99dd469f5158a2eb4a148611176 +"get-tsconfig@npm:^4.4.0, get-tsconfig@npm:^4.7.0": + version: 4.7.2 + resolution: "get-tsconfig@npm:4.7.2" + dependencies: + resolve-pkg-maps: ^1.0.0 + checksum: 172358903250eff0103943f816e8a4e51d29b8e5449058bdf7266714a908a48239f6884308bd3a6ff28b09f692b9533dbebfd183ab63e4e14f073cda91f1bca9 languageName: node linkType: hard @@ -27778,7 +27613,7 @@ __metadata: languageName: node linkType: hard -"history@npm:^5.0.0": +"history@npm:^5.0.0, history@npm:^5.3.0": version: 5.3.0 resolution: "history@npm:5.3.0" dependencies: @@ -30098,10 +29933,10 @@ __metadata: languageName: node linkType: hard -"jose@npm:^4.15.1, jose@npm:^4.6.0": - version: 4.15.2 - resolution: "jose@npm:4.15.2" - checksum: 8f0cab1eef31243abe14a935b2b330cd95f10f9b69808fd642088ae5000e50e566664934537d2c6413ab2f6b54acd8265a5033da05157aa1260c5f1d7e57fab0 +"jose@npm:^4.14.6, jose@npm:^4.15.1, jose@npm:^4.6.0": + version: 4.15.3 + resolution: "jose@npm:4.15.3" + checksum: b76eeccc1d40d0eaf26dfaadc0f88fc15802c9105ab66a24ee223bd84369f7cb217f4a2cb852f5080ff6996170b3a73db2b2d26878b8905d99c36ca432628134 languageName: node linkType: hard @@ -30450,17 +30285,6 @@ __metadata: languageName: node linkType: hard -"json-schema-merge-allof@npm:^0.6.0": - version: 0.6.0 - resolution: "json-schema-merge-allof@npm:0.6.0" - dependencies: - compute-lcm: ^1.1.0 - json-schema-compare: ^0.2.2 - lodash: ^4.17.4 - checksum: 2008aede3f5d05d7870e7d5e554e5c6a5b451cfff1357d34d3d8b34e2ba57468a97c76aa5b967bdb411d91b98c734f19f350de578d25b2a0a27cd4e1ca92bd1d - languageName: node - linkType: hard - "json-schema-merge-allof@npm:^0.8.1": version: 0.8.1 resolution: "json-schema-merge-allof@npm:0.8.1" @@ -30973,11 +30797,11 @@ __metadata: linkType: hard "keyv@npm:^4.0.0, keyv@npm:^4.5.2": - version: 4.5.3 - resolution: "keyv@npm:4.5.3" + version: 4.5.4 + resolution: "keyv@npm:4.5.4" dependencies: json-buffer: 3.0.1 - checksum: 3ffb4d5b72b6b4b4af443bbb75ca2526b23c750fccb5ac4c267c6116888b4b65681015c2833cb20d26cf3e6e32dac6b988c77f7f022e1a571b7d90f1442257da + checksum: 74a24395b1c34bd44ad5cb2b49140d087553e170625240b86755a6604cd65aa16efdbdeae5cdb17ba1284a0fbb25ad06263755dbc71b8d8b06f74232ce3cdd72 languageName: node linkType: hard @@ -31589,7 +31413,7 @@ __metadata: languageName: node linkType: hard -"lodash.merge@npm:4.6.2, lodash.merge@npm:^4.6.2": +"lodash.merge@npm:^4.6.2": version: 4.6.2 resolution: "lodash.merge@npm:4.6.2" checksum: ad580b4bdbb7ca1f7abf7e1bce63a9a0b98e370cf40194b03380a46b4ed799c9573029599caebc1b14e3f24b111aef72b96674a56cfa105e0f5ac70546cdc005 @@ -33225,7 +33049,7 @@ __metadata: languageName: node linkType: hard -"msw@npm:^1.0.0, msw@npm:^1.0.1, msw@npm:^1.2.1, msw@npm:^1.2.3, msw@npm:^1.3.1": +"msw@npm:^1.0.0, msw@npm:^1.0.1, msw@npm:^1.2.1, msw@npm:^1.2.3, msw@npm:^1.3.0, msw@npm:^1.3.1": version: 1.3.2 resolution: "msw@npm:1.3.2" dependencies: @@ -33377,7 +33201,7 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.1.23, nanoid@npm:^3.3.6": +"nanoid@npm:^3.3.6": version: 3.3.6 resolution: "nanoid@npm:3.3.6" bin: @@ -33393,13 +33217,6 @@ __metadata: languageName: node linkType: hard -"natural-compare-lite@npm:^1.4.0": - version: 1.4.0 - resolution: "natural-compare-lite@npm:1.4.0" - checksum: 5222ac3986a2b78dd6069ac62cbb52a7bf8ffc90d972ab76dfe7b01892485d229530ed20d0c62e79a6b363a663b273db3bde195a1358ce9e5f779d4453887225 - languageName: node - linkType: hard - "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -33538,13 +33355,23 @@ __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 languageName: node linkType: hard +"node-fetch-commonjs@npm:^3.3.1": + version: 3.3.2 + resolution: "node-fetch-commonjs@npm:3.3.2" + dependencies: + node-domexception: ^1.0.0 + web-streams-polyfill: ^3.0.3 + checksum: 7cc9bc3cba02c88ae031028c07af7f5053d1968e7f8e06931cdca51a695d66bb9fc9bca11bde31915a3e70a957b8e240c568f7ff47af5757efb5526c4389f570 + languageName: node + linkType: hard + "node-fetch@npm:^1.0.1": version: 1.7.3 resolution: "node-fetch@npm:1.7.3" @@ -34269,15 +34096,15 @@ __metadata: languageName: node linkType: hard -"openid-client@npm:^5.2.1, openid-client@npm:^5.3.0": - version: 5.6.0 - resolution: "openid-client@npm:5.6.0" +"openid-client@npm:^5.2.1, openid-client@npm:^5.3.0, openid-client@npm:^5.4.3": + version: 5.6.1 + resolution: "openid-client@npm:5.6.1" dependencies: jose: ^4.15.1 lru-cache: ^6.0.0 object-hash: ^2.2.0 oidc-token-hash: ^5.0.3 - checksum: 414fe43c5aac07d8b8f5ea52ef1812374ff28140910977a1360781284b09d4a03c916d910017bf15003d602d859b3dcf9857d1dfe6f61508c8f5c52de334e6ea + checksum: 9d939cec57540e6dd3f67e9a248ec5ecec3b439b7ab5bd2e9fb4481bd03e8d030deedd87a447348194be7f3e93e84085841b0414033caf86479870f526cdbc2f languageName: node linkType: hard @@ -34932,10 +34759,10 @@ __metadata: languageName: node linkType: hard -"path-equal@npm:^1.1.2": - version: 1.2.2 - resolution: "path-equal@npm:1.2.2" - checksum: 948930eb6bbb5ddcc724f7a4339e2a98fe35269b5f46d88f85c588ed4713e7ec1c71da1629608606c6687216ba3afae710a77cfb5146b735a84d6199f06f247d +"path-equal@npm:^1.2.5": + version: 1.2.5 + resolution: "path-equal@npm:1.2.5" + checksum: 2bef7bcb98c7ae371c52c1562b2fc515bfd03bc1a5571df9a8591038db8d742ba2d1ff39aa5130853e6afb69e773ccba5095f54d2e6d17422ca03ef9047992d7 languageName: node linkType: hard @@ -36464,12 +36291,12 @@ __metadata: languageName: node linkType: hard -"ramda-adjunct@npm:^4.0.0": - version: 4.0.0 - resolution: "ramda-adjunct@npm:4.0.0" +"ramda-adjunct@npm:^4.0.0, ramda-adjunct@npm:^4.1.1": + version: 4.1.1 + resolution: "ramda-adjunct@npm:4.1.1" peerDependencies: ramda: ">= 0.29.0" - checksum: 449736c561a6d70c20a27c09d6002030632e7570f78fd46b1d8636211a87d5c7daf16f41ac1d84bc62020b9c4532fa62afe8fe5b3cb5d34105e21f994c331ead + checksum: 7cdae1129987afac3d2ab9188b62f949558f86ad14ef76b898bacf065da5542e213e53cb01f064444ad634dfa668148cd3351726017a11dfe141b6b4c3552808 languageName: node linkType: hard @@ -36720,16 +36547,15 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^17.0.2": - version: 17.0.2 - resolution: "react-dom@npm:17.0.2" +"react-dom@npm:^18.0.2": + version: 18.2.0 + resolution: "react-dom@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - scheduler: ^0.20.2 + scheduler: ^0.23.0 peerDependencies: - react: 17.0.2 - checksum: 1c1eaa3bca7c7228d24b70932e3d7c99e70d1d04e13bb0843bbf321582bc25d7961d6b8a6978a58a598af2af496d1cedcfb1bf65f6b0960a0a8161cb8dab743c + react: ^18.2.0 + checksum: 7d323310bea3a91be2965f9468d552f201b1c27891e45ddc2d6b8f717680c95a75ae0bc1e3f5cf41472446a2589a75aed4483aee8169287909fcd59ad149e8cc languageName: node linkType: hard @@ -36891,7 +36717,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^16.10.2, react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.6.3, react-is@npm:^16.7.0, react-is@npm:^16.8.0, react-is@npm:^16.8.6, react-is@npm:^16.9.0": +"react-is@npm:^16.10.2, react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.6.3, react-is@npm:^16.7.0, react-is@npm:^16.8.0, react-is@npm:^16.8.6": version: 16.13.1 resolution: "react-is@npm:16.13.1" checksum: f7a19ac3496de32ca9ae12aa030f00f14a3d45374f1ceca0af707c831b2a6098ef0d6bdae51bd437b0a306d7f01d4677fcc8de7c0d331eb47ad0f46130e53c5f @@ -37084,15 +36910,15 @@ __metadata: linkType: hard "react-router-dom@npm:^6.3.0": - version: 6.15.0 - resolution: "react-router-dom@npm:6.15.0" + version: 6.16.0 + resolution: "react-router-dom@npm:6.16.0" dependencies: - "@remix-run/router": 1.8.0 - react-router: 6.15.0 + "@remix-run/router": 1.9.0 + react-router: 6.16.0 peerDependencies: react: ">=16.8" react-dom: ">=16.8" - checksum: 95301837e293654f00934de6a4bdb27bfb06f613503e4cce7a93f19384793729832e7479d50faf3b9457d149014d4df40a3ee3a5193d7e3a3caadb7aaa6ec0f9 + checksum: 18b398924bb0f0d97cf2f71dab71d860b960a7a267b2f77388990c662bb6d8738bdc3042d92f713fd63d269ae9ad90df39c8e97661b6ba758bbb7386b9f20ae0 languageName: node linkType: hard @@ -37107,14 +36933,14 @@ __metadata: languageName: node linkType: hard -"react-router@npm:6.15.0, react-router@npm:^6.3.0": - version: 6.15.0 - resolution: "react-router@npm:6.15.0" +"react-router@npm:6.16.0, react-router@npm:^6.3.0": + version: 6.16.0 + resolution: "react-router@npm:6.16.0" dependencies: - "@remix-run/router": 1.8.0 + "@remix-run/router": 1.9.0 peerDependencies: react: ">=16.8" - checksum: 345b29277e13997f2625f0037f537eaf1955bb9f44ebfea80dd3ff83fc06273f7b64e1be944bfc75945fd2af5af917874133a8a93ed5ecaca523be8f045ae166 + checksum: b31c187e3fdcdf7294ffdad6ff834e14d012840c94d8ee8c7fbe451062a8fcb6e31e8bc7827fb1ff45445dd40fad2b8c96a7e98f0ac1c3eb1d716c257a0821c9 languageName: node linkType: hard @@ -37295,13 +37121,12 @@ __metadata: languageName: node linkType: hard -"react@npm:^17.0.2": - version: 17.0.2 - resolution: "react@npm:17.0.2" +"react@npm:^18.0.2": + version: 18.2.0 + resolution: "react@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: b254cc17ce3011788330f7bbf383ab653c6848902d7936a87b09d835d091e3f295f7e9dd1597c6daac5dc80f90e778c8230218ba8ad599f74adcc11e33b9d61b + checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b languageName: node linkType: hard @@ -37676,13 +37501,6 @@ __metadata: languageName: node linkType: hard -"regexpp@npm:^3.2.0": - version: 3.2.0 - resolution: "regexpp@npm:3.2.0" - checksum: a78dc5c7158ad9ddcfe01aa9144f46e192ddbfa7b263895a70a5c6c73edd9ce85faf7c0430e59ac38839e1734e275b9c3de5c57ee3ab6edc0e0b1bdebefccef8 - languageName: node - linkType: hard - "regexpu-core@npm:^5.3.1": version: 5.3.2 resolution: "regexpu-core@npm:5.3.2" @@ -37950,6 +37768,13 @@ __metadata: languageName: node linkType: hard +"resolve-pkg-maps@npm:^1.0.0": + version: 1.0.0 + resolution: "resolve-pkg-maps@npm:1.0.0" + checksum: 1012afc566b3fdb190a6309cc37ef3b2dcc35dff5fa6683a9d00cd25c3247edfbc4691b91078c97adc82a29b77a2660c30d791d65dab4fc78bfc473f60289977 + languageName: node + linkType: hard + "resolve.exports@npm:^2.0.0": version: 2.0.0 resolution: "resolve.exports@npm:2.0.0" @@ -38296,8 +38121,8 @@ __metadata: linkType: hard "rollup@npm:^2.60.2": - version: 2.77.3 - resolution: "rollup@npm:2.77.3" + version: 2.79.1 + resolution: "rollup@npm:2.79.1" dependencies: fsevents: ~2.3.2 dependenciesMeta: @@ -38305,7 +38130,7 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: b179c68249584565ddb5664a241e8e48c293b2207718d885b08ee25797d98857a383f06b544bb89819407da5a71557f4713309a278f61c4778bb32b1d3321a1c + checksum: 6a2bf167b3587d4df709b37d149ad0300692cc5deb510f89ac7bdc77c8738c9546ae3de9322b0968e1ed2b0e984571f5f55aae28fa7de4cfcb1bc5402a4e2be6 languageName: node linkType: hard @@ -38558,13 +38383,12 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:^0.20.2": - version: 0.20.2 - resolution: "scheduler@npm:0.20.2" +"scheduler@npm:^0.23.0": + version: 0.23.0 + resolution: "scheduler@npm:0.23.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: c4b35cf967c8f0d3e65753252d0f260271f81a81e427241295c5a7b783abf4ea9e905f22f815ab66676f5313be0a25f47be582254db8f9241b259213e999b8fc + checksum: d79192eeaa12abef860c195ea45d37cbf2bbf5f66e3c4dcd16f54a7da53b17788a70d109ee3d3dde1a0fd50e6a8fc171f4300356c5aee4fc0171de526bf35f8a languageName: node linkType: hard @@ -38694,7 +38518,7 @@ __metadata: languageName: node linkType: hard -"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.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": version: 7.5.4 resolution: "semver@npm:7.5.4" dependencies: @@ -38946,13 +38770,13 @@ __metadata: languageName: node linkType: hard -"short-unique-id@npm:^4.4.4": - version: 4.4.4 - resolution: "short-unique-id@npm:4.4.4" +"short-unique-id@npm:^5.0.2": + version: 5.0.3 + resolution: "short-unique-id@npm:5.0.3" bin: short-unique-id: bin/short-unique-id suid: bin/short-unique-id - checksum: 3507f2e97326e49180dd4edbf41dd762a76c591df3fd5b7c1e7592bfb0c2f5724d63e626cc6f581c717d3111374811ca1d77a728ac07b0b9041b2355700124d4 + checksum: 9e5e02276972b103d3f2808280b82ab9f90006dd0aea6a253158e71e3ed618c3ac8dfe509a267080b19826a5d4e20d7a3d1adb2f13e166109f56946da3fdff9b languageName: node linkType: hard @@ -40185,42 +40009,40 @@ __metadata: languageName: node linkType: hard -"swagger-client@npm:^3.20.0": - version: 3.20.0 - resolution: "swagger-client@npm:3.20.0" +"swagger-client@npm:^3.22.3": + version: 3.23.0 + resolution: "swagger-client@npm:3.23.0" dependencies: - "@babel/runtime-corejs3": ^7.20.13 - "@swagger-api/apidom-core": ">=0.74.1 <1.0.0" - "@swagger-api/apidom-json-pointer": ">=0.74.1 <1.0.0" - "@swagger-api/apidom-ns-openapi-3-1": ">=0.74.1 <1.0.0" - "@swagger-api/apidom-reference": ">=0.74.1 <1.0.0" + "@babel/runtime-corejs3": ^7.22.15 + "@swagger-api/apidom-core": ">=0.77.0 <1.0.0" + "@swagger-api/apidom-json-pointer": ">=0.77.0 <1.0.0" + "@swagger-api/apidom-ns-openapi-3-1": ">=0.77.0 <1.0.0" + "@swagger-api/apidom-reference": ">=0.77.0 <1.0.0" cookie: ~0.5.0 - cross-fetch: ^3.1.5 deepmerge: ~4.3.0 fast-json-patch: ^3.0.0-1 - form-data-encoder: ^1.4.3 - formdata-node: ^4.0.0 is-plain-object: ^5.0.0 js-yaml: ^4.1.0 - lodash: ^4.17.21 + node-abort-controller: ^3.1.1 + node-fetch-commonjs: ^3.3.1 qs: ^6.10.2 traverse: ~0.6.6 - url: ~0.11.0 - checksum: c61452d0c810e05ec319dfc9bf8b876a87d1d5ed74156764ccc627e79e8a6c0d84f4660754dd1e2f7570adfa17a89c2d16cc337421b7da3bec0b428224a70436 + undici: ^5.24.0 + checksum: 988b672ed05b115504e2b09afd8285f694c1e5061854fa8ab3beb56e1a273d7f47e4ee5f25292693c7f695292bd2924d8e6c33f28bd86843859a5083f96044ac languageName: node linkType: hard "swagger-ui-react@npm:^5.0.0": - version: 5.6.2 - resolution: "swagger-ui-react@npm:5.6.2" + version: 5.9.0 + resolution: "swagger-ui-react@npm:5.9.0" dependencies: - "@babel/runtime-corejs3": ^7.22.11 + "@babel/runtime-corejs3": ^7.23.1 "@braintree/sanitize-url": =6.0.4 base64-js: ^1.5.1 classnames: ^2.3.1 css.escape: 1.5.1 deep-extend: 0.6.0 - dompurify: =3.0.5 + dompurify: =3.0.6 ieee754: ^1.2.1 immutable: ^3.x.x js-file-download: ^0.4.12 @@ -40243,7 +40065,7 @@ __metadata: reselect: ^4.1.8 serialize-error: ^8.1.0 sha.js: ^2.4.11 - swagger-client: ^3.20.0 + swagger-client: ^3.22.3 url-parse: ^1.5.10 xml: =1.0.1 xml-but-prettier: ^1.0.1 @@ -40251,7 +40073,7 @@ __metadata: peerDependencies: react: ">=17.0.0" react-dom: ">=17.0.0" - checksum: 50a9ad4ed40a87b2a5b169ac1697c163123491ee4ffcc1a4d617f578bf0636d3246caf92811122c9ec73b7ebe34df41f0298e5de4f05647474c8d8352f7cb194 + checksum: 73ebfeaaad364899f7c3304cbe30a165066970b65a4822c6d22c0ae7f00cbe476849571bacdb938ef4e173579cb9c1ea9623b8c677bc452bcd57e8fb27ff63f6 languageName: node linkType: hard @@ -40413,16 +40235,16 @@ __metadata: "@backstage/theme": "workspace:^" "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 - "@testing-library/dom": ^8.0.0 - "@testing-library/jest-dom": ^5.10.1 - "@testing-library/react": ^12.1.3 + "@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": "*" "@types/react-dom": "*" cross-env: ^7.0.0 history: ^5.0.0 - react: ^17.0.2 - react-dom: ^17.0.2 + react: ^18.0.2 + react-dom: ^18.0.2 react-router-dom: ^6.3.0 react-use: ^17.2.4 languageName: unknown @@ -40660,15 +40482,6 @@ __metadata: languageName: node linkType: hard -"tmp-promise@npm:^3.0.2": - version: 3.0.2 - resolution: "tmp-promise@npm:3.0.2" - dependencies: - tmp: ^0.2.0 - checksum: 2d8457c9512e896633f64fab33e5e3fd273c4d8fca33cfc74a04a104a0b921d15ed3e832c4f2a50108635ac88264afef85abddbe5ad8480e15f55fc7f8e76969 - languageName: node - linkType: hard - "tmp@npm:^0.0.33": version: 0.0.33 resolution: "tmp@npm:0.0.33" @@ -40678,7 +40491,7 @@ __metadata: languageName: node linkType: hard -"tmp@npm:^0.2.0, tmp@npm:^0.2.1": +"tmp@npm:^0.2.1": version: 0.2.1 resolution: "tmp@npm:0.2.1" dependencies: @@ -40902,6 +40715,15 @@ __metadata: languageName: node linkType: hard +"ts-api-utils@npm:^1.0.1": + version: 1.0.3 + resolution: "ts-api-utils@npm:1.0.3" + peerDependencies: + typescript: ">=4.2.0" + checksum: 441cc4489d65fd515ae6b0f4eb8690057add6f3b6a63a36073753547fb6ce0c9ea0e0530220a0b282b0eec535f52c4dfc315d35f8a4c9a91c0def0707a714ca6 + languageName: node + linkType: hard + "ts-easing@npm:^0.2.0": version: 0.2.0 resolution: "ts-easing@npm:0.2.0" @@ -41243,31 +41065,21 @@ __metadata: languageName: node linkType: hard -"typescript-json-schema@npm:^0.55.0": - version: 0.55.0 - resolution: "typescript-json-schema@npm:0.55.0" +"typescript-json-schema@npm:^0.61.0": + version: 0.61.0 + resolution: "typescript-json-schema@npm:0.61.0" dependencies: "@types/json-schema": ^7.0.9 "@types/node": ^16.9.2 glob: ^7.1.7 - path-equal: ^1.1.2 + path-equal: ^1.2.5 safe-stable-stringify: ^2.2.0 ts-node: ^10.9.1 - typescript: ~4.8.2 + typescript: ~5.1.0 yargs: ^17.1.1 bin: typescript-json-schema: bin/typescript-json-schema - checksum: 4188e9d4cc1f1fc3201e2aa06b8d87d35695b0eaf049ff9d2cd3027d87406efc6978c4f90c2bf06f4fcd8d6dd40ceb65e744dc3cf9b412e1f74b8eb5bae96a05 - languageName: node - linkType: hard - -"typescript@npm:~4.8.2": - version: 4.8.4 - resolution: "typescript@npm:4.8.4" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 3e4f061658e0c8f36c820802fa809e0fd812b85687a9a2f5430bc3d0368e37d1c9605c3ce9b39df9a05af2ece67b1d844f9f6ea8ff42819f13bcb80f85629af0 + checksum: 8359d5ca8ebcb96dca9cd968b46ea21da40a92ee872a44a7b5c6c8f8f4cd1ffbd0ea457752f3be7d44379ea286ccfaee1d40ab1810321ee45d0ecece80ed45ed languageName: node linkType: hard @@ -41281,13 +41093,13 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@~4.8.2#~builtin<compat/typescript>": - version: 4.8.4 - resolution: "typescript@patch:typescript@npm%3A4.8.4#~builtin<compat/typescript>::version=4.8.4&hash=a1c5e5" +"typescript@npm:~5.1.0": + version: 5.1.6 + resolution: "typescript@npm:5.1.6" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 563a0ef47abae6df27a9a3ab38f75fc681f633ccf1a3502b1108e252e187787893de689220f4544aaf95a371a4eb3141e4a337deb9895de5ac3c1ca76430e5f0 + checksum: b2f2c35096035fe1f5facd1e38922ccb8558996331405eb00a5111cc948b2e733163cc22fab5db46992aba7dd520fff637f2c1df4996ff0e134e77d3249a7350 languageName: node linkType: hard @@ -41301,6 +41113,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@~5.1.0#~builtin<compat/typescript>": + version: 5.1.6 + resolution: "typescript@patch:typescript@npm%3A5.1.6#~builtin<compat/typescript>::version=5.1.6&hash=a1c5e5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 21e88b0a0c0226f9cb9fd25b9626fb05b4c0f3fddac521844a13e1f30beb8f14e90bd409a9ac43c812c5946d714d6e0dee12d5d02dfc1c562c5aacfa1f49b606 + languageName: node + linkType: hard + "ua-parser-js@npm:^0.7.30": version: 0.7.33 resolution: "ua-parser-js@npm:0.7.33" @@ -41389,19 +41211,26 @@ __metadata: languageName: node linkType: hard -"underscore@npm:^1.12.1, underscore@npm:^1.13.6, underscore@npm:~1.13.2": +"underscore@npm:^1.12.1, underscore@npm:~1.13.2": version: 1.13.6 resolution: "underscore@npm:1.13.6" checksum: d5cedd14a9d0d91dd38c1ce6169e4455bb931f0aaf354108e47bd46d3f2da7464d49b2171a5cf786d61963204a42d01ea1332a903b7342ad428deaafaf70ec36 languageName: node linkType: hard -"undici@npm:^5.12.0, undici@npm:^5.8.0": - version: 5.22.1 - resolution: "undici@npm:5.22.1" +"undici-types@npm:~5.25.1": + version: 5.25.3 + resolution: "undici-types@npm:5.25.3" + checksum: ec9d2cc36520cbd9fbe3b3b6c682a87fe5be214699e1f57d1e3d9a2cb5be422e62735f06e0067dc325fd3dd7404c697e4d479f9147dc8a804e049e29f357f2ff + languageName: node + linkType: hard + +"undici@npm:^5.12.0, undici@npm:^5.24.0, undici@npm:^5.8.0": + version: 5.25.4 + resolution: "undici@npm:5.25.4" dependencies: - busboy: ^1.6.0 - checksum: 048a3365f622be44fb319316cedfaa241c59cf7f3368ae7667a12323447e1822e8cc3d00f6956c852d1478a6fde1cbbe753f49e05f2fdaed229693e716ebaf35 + "@fastify/busboy": ^2.0.0 + checksum: 654da161687de893127a685be61a19cb5bae42f4595c316ebf633929d871ac3bcd33edcb74156cea90655dfcd100bfe9b53a4f4749d52fc6ad2232f49a6ca8ab languageName: node linkType: hard @@ -41701,7 +41530,7 @@ __metadata: languageName: node linkType: hard -"url@npm:^0.11.0, url@npm:~0.11.0": +"url@npm:^0.11.0": version: 0.11.0 resolution: "url@npm:0.11.0" dependencies: @@ -42254,7 +42083,7 @@ __metadata: languageName: node linkType: hard -"web-streams-polyfill@npm:^3.2.0, web-streams-polyfill@npm:^3.2.1": +"web-streams-polyfill@npm:^3.0.3, web-streams-polyfill@npm:^3.2.0, web-streams-polyfill@npm:^3.2.1": version: 3.2.1 resolution: "web-streams-polyfill@npm:3.2.1" checksum: b119c78574b6d65935e35098c2afdcd752b84268e18746606af149e3c424e15621b6f1ff0b42b2676dc012fc4f0d313f964b41a4b5031e525faa03997457da02 @@ -42645,10 +42474,10 @@ __metadata: linkType: hard "winston@npm:^3.2.1": - version: 3.10.0 - resolution: "winston@npm:3.10.0" + version: 3.11.0 + resolution: "winston@npm:3.11.0" dependencies: - "@colors/colors": 1.5.0 + "@colors/colors": ^1.6.0 "@dabh/diagnostics": ^2.0.2 async: ^3.2.3 is-stream: ^2.0.0 @@ -42659,7 +42488,7 @@ __metadata: stack-trace: 0.0.x triple-beam: ^1.3.0 winston-transport: ^4.5.0 - checksum: 47df0361220d12b46d1b3c98a1c380a3718321739d527a182ce7984fc20715e5b0b55db0bcd3fd076d1b1d3261903b890b053851cfd4bc028bda7951fa8ca2e0 + checksum: ca4454070f7a71b19f53c8c1765c59a013dab220edb49161b2e81917751d3e9edc3382430e4fb050feda04fb8463290ecab7cbc9240ec8d3d3b32a121849bbb0 languageName: node linkType: hard @@ -42913,15 +42742,6 @@ __metadata: languageName: node linkType: hard -"xterm-addon-attach@npm:^0.8.0": - version: 0.8.0 - resolution: "xterm-addon-attach@npm:0.8.0" - peerDependencies: - xterm: ^5.0.0 - checksum: 2ac70bdd1c97eb05b83b4573132ed9d3686c07ed14212e273800a5693bb0f3ea41c570b49ac90cb95a1e593d5a2764a28c13b649c596054bf5aa87c8489069eb - languageName: node - linkType: hard - "xterm-addon-attach@npm:^0.9.0": version: 0.9.0 resolution: "xterm-addon-attach@npm:0.9.0" @@ -42931,15 +42751,6 @@ __metadata: languageName: node linkType: hard -"xterm-addon-fit@npm:^0.7.0": - version: 0.7.0 - resolution: "xterm-addon-fit@npm:0.7.0" - peerDependencies: - xterm: ^5.0.0 - checksum: 512d41f80d6f9427ba02dab4e6fd642e94775a9cf7ef72ae4b55eab2a36856b5c67069bfc66b4af412fdce29a0842f9c6382af3672f0b514c4352dfd47defe8f - languageName: node - linkType: hard - "xterm-addon-fit@npm:^0.8.0": version: 0.8.0 resolution: "xterm-addon-fit@npm:0.8.0"